Need to key function identities off effective script origins of both caller and object #8
Comments
What is the effective script origin of the object (of its global object?) and why would it be necessary to use that as part of the key since the map lives on the object? |
Suppose we have Window |a| from foo.example.com and Window |b| from bar.example.com. |a| sets document.domain to 'example.com', and then grabs a reference to b.location (which appears cross-origin). Next, |b| also sets document.domain to 'example.com'. The Location object and behavior observed by the script in |a| change (to become same-origin), even though the effective script origin of |a| did not change. In practice, Gecko clears the cache whenever either of the effective script origins change, whether or not that change causes them to become same-origin. |
Okay, so what we want to say here is that crossOriginKey is a tuple consisting of the effective script origin of this' Realm's global object and this' associated Document's effective script origin. |
Nit: as far as I can tell only Documents have effective script origins... I think you end up wanting "incumbent settings object's responsible document's effective script origin." |
Per previous discussion, I think we should use the current realm rather than the incumbent settings object here. |
@bholley in what cases would that be different? Since settings objects are the only place to get an effective script origin right now, I think you would end up having to say the same thing in more words (e.g. "the settings object whose realm execution context is the top-level execution context of the current realm", which is just "incumbent settings object") |
They differ in the case of invoking a non-scripted cross-realm same-origin function. The current realm is that of the function, whereas the incumbent script represents that of the caller. I've been pushing for the removal of incumbent script, because it makes things unnecessarily complicated. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=26603 |
Apologies if I am confused, but from my understanding the caller script is the entry script, and the incumbent script is that of the function. A code example might help clarify. |
No, the entry script is the script that was first entered by the platform (i.e. via event listener dispatch), before any cross-global function calls happen. It's a dumb concept but needed for web-compat. This is all described in https://www.w3.org/Bugs/Public/show_bug.cgi?id=26603#c0 . Entry global, incumbent global, and current realm global can all differ from each other. |
I guess this has all been hashed out in the previous bug so you don't need to reeducate me here. I do find that bug confusing since it contains few code examples, instead substituting a lot of unfamiliar vocabulary like "scripted function". Anyway, I am skeptical of introducing a third concept at this stage, and would prefer we stick with entry + incumbent, and in the future redefine incumbent to mean current realm or similar. But we can wait until review time for me to voice those concerns. |
A scripted function is a function that has a SourceElements associated with it (i.e. one that was defined by script). This is relevant because incumbent script is defined in terms of SourceElements, and many functions (notably DOM methods) have no such thing.
I agree that we should reduce the number of concepts. We will basically always need Current Realm and Entry Global, so it's a question of whether we can write this spec to avoid depending on Incumbent Global, which is something that would ideally be removed. |
I think if we use "this' Realm's corresponding environment settings object's effective script origin" for where I wrote "this' Realm's global object's effective script origin" above we should also be good, no? |
No. (1) It's not clear what "this' Realm" refers to; (2) Realms don't have corresponding environment settings objects. |
An object is always created in some Realm/global object, that's where it's prototype et al come from. You said that since you can get from a environment settings object to a Realm, you can also go the other way around. I guess the language might need some changes, but I was hoping that much would be clear. |
I guess this has probably been discussed before, so apologies again. But does every implementation actually store an object's realm on each object, beyond just creation time? It seems unlikely you'd want to add another 32/64 bits to each object and carry that around forever. |
Gecko/SM stores it on everything (it's actually inferred from various other things). ISTR Boris saying that Blink/V8 stored it for Functions, but not Objects. But I'm not totally sure. |
Yeah, per the spec only functions have realms. |
Okay, I was just trying to find a way around using the incumbent settings object since that does not really match what we want in the long run. (To find the realm, could we just enumerate the realms in the "continent" and see which one has the corresponding prototype object?) |
So, the issue of whether or not non-function objects can easily find their realm isn't relevant here. We aren't talking about the realm of the cross-origin objects, but rather the realm of the code that is accessing them. Code that accesses a property is either a top-level script or a function, both of which should have easily-accessible realms. The "current realm" and "incumbent script" are usually the same, but the concept of "incumbent script" is more complicated because it has to resolve to some script somewhere, which is tricky in certain asynchronous cases (i.e. setTimeout(someNativeFunction.bind(...), 0) when there is no script on the stack when the function runs. In that case, the Incumbent Script needs to remember what script was running when the WebIDL callback was created. So consider the case where we have same-origin windows A and B and cross-origin C. In the case where A does: B.setTimeout(B.Object.getOwnPropertyDescriptor.bind(null, C, 'location')) The access check algorithm will run against window B in the "current realm" strategy (since that's where the function lives) and A in the "incumbent script" strategy (since that's how incumbent script deals with asynchronous calls to non-scripted functions). For access-control stuff, we want to do the simple thing of asking "can the function that's currently executing access this thing". Our script security architecture is currently unaware of the concept of incumbent script (since it's only used for edge cases), and I'm not sure I could easily add it. |
|
Actually, 1 is addressed by ECMAScript, which defines "the current Realm". |
(As for earlier, apparently per IDL all IDL defined objects have an associated realm/global. So that is in fact available.) |
The other part of the key is the property name. There's also the weirdness that, at least in Gecko, we clear the map when document.domain changes on either side. It might be possible to represent this behavior by also adding the effective script origin of |this| into the tuple, since you can never revisit an earlier value of document.domain. |
Worth adding tests for this case too if they aren't there already.
The text was updated successfully, but these errors were encountered: