| 12:02 | <benjamingr_> | o/ |
| 12:02 | <benjamingr_> | Hey, if someone has overwritten `fetch` in a web page is there any way to get a reference to the original? |
| 12:03 | <benjamingr_> | I know I can grab it from an `iframe` but that messes with the referrer, it's not transferrable so I can't move it from the worker (I can facade it, maybe - but would rather not) |
| 12:08 | <Ms2ger> | benjamingr_, can you grab the function from the iframe and then do other_fetch.call(window)? |
| 12:09 | <Ms2ger> | Not sure if that would work |
| 12:09 | <benjamingr_> | That would mess with the referrer header |
| 12:10 | <Ms2ger> | Then your only option is to beat whatever code is overwriting it to the punch |
| 12:11 | <benjamingr_> | Can't, other ideas welcome |
| 12:12 | <Ms2ger> | I don't think there's any |
| 12:12 | <Ms2ger> | Maybe Domenic has some |
| 12:13 | <benjamingr_> | Domenic is/was working on a getOriginals which would have solved this for me anyway - but that's still a long way away afaik |
| 13:33 | <Domenic> | That shouldn't mess with the referrer if you use . call |
| 13:33 | <benjamingr_> | Ah, interesting, why? |
| 13:34 | Domenic | is unsure what benjamingr_ thinks of as "long" |
| 13:34 | <Domenic> | It uses the this value to compute things |
| 13:34 | <benjamingr_> | Ah, fabulous, I had no idea - thanks |
| 13:34 | <benjamingr_> | "long" - not something I can use in a PoC I want to do "just so it's cool" in the next 2-3 months. |
| 13:35 | <Domenic> | Yeah 2-3 months is a tight constraint |
| 13:36 | <benjamingr_> | + not one you should or would be interested in fulfilling just for my PoC :D |
| 13:46 | <benjamingr_> | It's a little surprising to me since I'd expect `fetch(url)` to behave similarly to `fetch.call(window, url)` since either fetch is unbound (which means it gets `window` by default as context in loose mode) or it is bound in which case I don't understand why `.call` sets its this. |
| 13:46 | <benjamingr_> | What am I missing Domenic? |
| 13:50 | <Domenic> | I don't understand the confusion. It's unbound. Which means you can change its this value with .call. but the default this value is indeed window. No contradiction. |
| 13:51 | <Domenic> | Notice that Ms2ger is specifically suggesting using otherFetch.call(window), to change the this value of otherFetch. |
| 13:58 | <benjamingr_> | https://www.irccloud.com/pastebin/qw9X1cpj/ |
| 13:59 | <benjamingr_> | "No contradiction." - I don't understand that part - it's unbound, the default value is indeed window, but when `.call`ing it and setting it explicitly to `window` it sets the referrer. |
| 14:05 | <wanderview> | benjamingr_: do you get the same behavior in different browsers? |
| 14:06 | <benjamingr_> | I haven't tested. I'm 95% convinced that this is the fact I've been sick myself and dealing with a sick relative and that there is a reasonable reason for this like me not understanding `this` for APIs across contexts. I'll check |
| 14:08 | <Ms2ger> | I think it's at least as likely that some browsers use the wrong object |
| 14:08 | <benjamingr_> | wanderview - Firefox sends the referrer anyway. |
| 14:09 | <benjamingr_> | So Firefox and Chrome behave differently and Chrome's behavior deviates from my understanding of how `this` works in JavaScript. The problem is that I still don't know if I should open a crbug or bugzilla. |
| 14:17 | <wanderview> | benjamingr_: I don't see a WPT test for this, but maybe I'm just not finding it... |
| 14:19 | <benjamingr_> | I think I'll look into it some more and open an issue in the `fetch` repo, I still believe this is just sleep deprivation so I'm hesitant to spend more of other peoples' time |
| 14:20 | <wanderview> | sounds reasonable... thanks! (and I hope you and your relative feel better) |
| 14:21 | <benjamingr_> | I guess if `fetch` itself is in strict mode it can explicitly check the `.call` value and differentiate but still confusing. Thanks for helping - I will update! |
| 14:21 | <Domenic> | Imagine the following code: `otherWindow.fetch = (...args) => { const referrerToUse = this.document.URL; }` |
| 14:21 | <Domenic> | Then if you do `otherWindow.fetch(...)` it will use `otherWindow.document.URL` as the referrer |
| 14:21 | <Domenic> | But if you do `otherWindow.fetch.call(window, ...)` it will use `window.document.URL` as the referrer |
| 14:22 | <Domenic> | Thus, if you want to get a "clean" copy of fetch (i.e. `otherWindow.fetch`), but have it use the "normal" referrer as if you were using "normal" `window.fetch()`, it suffices to just do `otherWindow.fetch.call(window, ...)` |
| 14:22 | <benjamingr_> | I think I understand what I was missing - if I grab a function from another context then when invoking it the `this` value is set to the global object _of that realm_ rather than the one I'm in - that should have been obvious. Thanks Domenic! |
| 14:25 | <Ms2ger> | Domenic, how about let f = otherWindow.fetch; f()? |
| 14:30 | <benjamingr_> | Ms2ger: when you call `f` there it calls it with `otherWindow` as the `this` since that's the global of its environment |
| 14:30 | <Domenic> | No... that's not how this works. |
| 14:31 | <Domenic> | It'll call it with undefined as this. Which per Web IDL gets converted to `window`, I am pretty sure. |
| 14:32 | <Domenic> | Oh nope, per Web IDL it gets converted to `otherWindow`, it looks like. |
| 14:32 | <Domenic> | https://heycam.github.io/webidl/#dfn-create-operation-function 2.1.2.1 |
| 14:33 | <Domenic> | `window` wouldn't have made sense anyway, nevermind. +1 benjamingr_. |
| 14:35 | <wanderview> | so does any browser dtrt? |
| 14:36 | <benjamingr_> | Well - Firefox is behaving differently by sending `Referrer` from an iframe when Chrome doesn't. Personally I like Chrome's behaviour better as a default and the only reason I need this "hack" is that there is nothing like `getOriginals` in the browser yet. |
| 14:37 | <benjamingr_> | Other things that would have helped - `fetch` being transferable, `ReadableStream` being transferable (that'd make the shim easy). They're both 'hacks' for what I really want (a clean reference I can rely on). |
| 19:38 | <TimothyGu> | benjamingr_: hmm, so what was the conclusion here? tbh I don't see anything in the spec for fetch() I'm reading that uses the `this` object in anyway |
| 19:39 | <TimothyGu> | The place where the referrer header gets set is step 2 in https://fetch.spec.whatwg.org/#dom-global-fetch, with the implication that "initial value of Request" refers to that in the realm for which this fetch() function was created |
| 19:39 | <benjamingr_> | Well, two things - first: Firefox and Chrome behave differently regarding the `Referer` header in iframes. |
| 19:39 | <TimothyGu> | Step 13 in https://fetch.spec.whatwg.org/#dom-request says the "current settings object" is used, which for fetch() means that of the realm it was created for |
| 19:39 | <TimothyGu> | Interesting |
| 19:40 | <benjamingr_> | Second, Chrome's `this` behaves differently than I expect in `fetch` (and not in accordance to which the `fetch` function was created). I really like this behaviour but only because it's the only way I have to get a safe `fetch` as an SDK |
| 19:40 | <TimothyGu> | I see... |
| 19:42 | <benjamingr_> | I'd expect a same origin iframe without a `src` set to send XHR and fetch exactly the same way as the parent document - but that's unrelated. Chrome doing Firefox's behavior would be great. Otherwise I'd have to grab `fetch` from a worker and since neither `ReadableStream` nor `fetch` itself is transferable that's quite a bit of work. |
| 19:43 | <TimothyGu> | Yeah, but having to create a whole new iframe just for a fetch() method (which prevents the iframe from being GC'd) is not that great |
| 19:44 | <TimothyGu> | If Firefox's fetch is bound to the window it was created for, I think that's the right behavior here |
| 19:45 | <benjamingr_> | Domenic posted a spec link explaining why it isn't IIRC |
| 19:45 | <benjamingr_> | Something about 2.1.2.1 https://heycam.github.io/webidl/#dfn-create-operation-function |
| 19:46 | <TimothyGu> | Yeah that has to do with how the `this` value is set |
| 19:46 | <TimothyGu> | But `fetch` doesn't (or shouldn't) use the `this` value at all |
| 19:46 | <Domenic> | Blargh |
| 19:46 | <Domenic> | I didn't actually check the spec, I just assumed it used the relevant global, because that's the guidance these days |
| 19:47 | <Domenic> | But TimothyGu's right that the behavior seems to happen implicitly in "the initial value of Request" |
| 19:47 | <Domenic> | So I think it should still be relevant (= realm of this) due to https://github.com/heycam/webidl/issues/135 |
| 19:47 | <Domenic> | But it's borderline |
| 19:48 | <Domenic> | "invoking the initial value of the Response constructor" is different from what 135 is talking about, which is "a new Request object" |
| 19:48 | <Domenic> | It'd be hard to argue that the spec is clear here and any browser is specifically wrong |
| 19:52 | <benjamingr_> | I'm not sure Firefox behaves differently, just that it sends the `Referer` header anyway |
| 19:52 | <benjamingr_> | Any suggestions on how to check this welcome as the differing behavior in Chrome between `fetch` and `fetch.call(window` doesn't exist on Firefox as far as I know. |
| 20:01 | <Domenic> | Filed https://github.com/whatwg/fetch/issues/777 |
| 20:02 | <Domenic> | It does seem like for practical purposes you may be in trouble here |
| 20:02 | <Domenic> | Even if in theory the spec gives you the tools you want |