html icon indicating copy to clipboard operation
html copied to clipboard

JavaScript ShadowRealm proposal integration

Open littledan opened this issue 5 years ago • 72 comments

This patch gives the TC39 JavaScript ShadowRealm proposal semantics in HTML. ShadowRealms are given an environment settings object; in general, ShadowRealms inherit their settings from the outer environment.

When modules are used in ShadowRealms, module specifiers are interpreted with respect to the base URL of the surrounding environment, but when a module is imported within a ShadowRealm, it is a separate copy from what may be loaded in the surrounding environment or other ShadowRealms.

This patch implements the plan described earlier at https://github.com/tc39/proposal-realms/issues/225#issuecomment-592159225.

The ShadowRealm proposal is currently at Stage 3.

  • [ ] At least two implementers are interested (and none opposed):
    • (none yet)
  • [ ] Tests are written and can be reviewed and commented upon at:
    • (none yet)
  • [ ] Implementation bugs are filed: (none yet)
    • Chrome: …
    • Firefox: …
    • Safari: …

(See WHATWG Working Mode: Changes for more details.)


/browsers.html ( diff ) /browsing-the-web.html ( diff ) /dom.html ( diff ) /index.html ( diff ) /infrastructure.html ( diff ) /references.html ( diff ) /webappapis.html ( diff )

littledan avatar Mar 06 '20 17:03 littledan

I'm not sure if this may be missing something to give Realms sufficiently concrete behavior, so reviews will be appreciated if folks have time. In particular, in the February 2020 TC39 meeting, the Realm proposal champions announced that they would be seeking Stage 3 in the March 2020 meeting, and I think it'd be best if we had the HTML interactions basically worked out and agreed on before Stage 3. See also https://github.com/tc39/proposal-realms/issues/225. (Note that the current rendered Realm spec text is a bit out of date; for now, you can cross-reference the source.)

littledan avatar Mar 06 '20 17:03 littledan

/cc @bzbarsky. At a glance, the proposed semantics of inheriting from the "parent settings object" seem most likely to integrate well without major issues. (I'm glad these have a settings object at all; that wasn't clear from the proposal.)

Here is a mix of vague concerns and concrete questions that I've been thinking about in this space. I think this proposal gives reasonable answers to most of them, but perhaps not all (especially the vague concerns).

  • Right now every realm is a window or a worker. I think there are probably parts of the web and spec ecosystem that make this assumption, especially around the agent cluster business. Breaking that assumption (which could be stated something like, every realm either has a document or is only asynchronously available) could be tricky.

  • What happens if one of these realms is used for an entry realm/incumbent realm for a web platform API, like window.open() or worker.postMessage()? (I think they cannot end up as current or relevant realms since these realms do not have web platform APIs inside of them.)

  • How will these realms behave when faced with host-specific scenarios such as resolving modules, or reporting errors? E.g. what happens in terms of window.onerror reporting, and the reporting API, if you do jsRealmGlobal.eval("throw new Error('foo')")?

  • How will objects from these realms behave when faced with web platform features that depend on every object having a realm/global object pointer? (Those features might assume such a global is a window or a worker.) E.g., what happens when you take an object from one of these realms and feed it into call a user object's operation, such as when using addEventListener()?

  • How do these realms interact with "can run script" checks which currently depend on browsing context pointers and fully active status? Arguably these realms, since they are not attached to a fully active document, should never be able to run script.

  • How does this proposal mesh with the web platform's general move away from allowing synchronous cross-realm access (like iframe), in favor of asynchronous realm-creation APIs (like portals, workers/worklets, and iframe disallowdocumentaccess (https://github.com/whatwg/html/pull/4606))? If we guard future powerful web platform features behind a "no sync cross-realm access allowed" opt-in, will we be able to prohibit the creation of these realms (e.g. from the host hook)? This also touches on the implementer interest question; it's not clear there's implementer support for adding a new way to synchronously create realms on the web.

domenic avatar Mar 06 '20 18:03 domenic

@annevk @bholley

bzbarsky avatar Mar 06 '20 20:03 bzbarsky

@EdgarChen

bzbarsky avatar Mar 06 '20 20:03 bzbarsky

Thanks for the prompt and detailed feedback. It looks like we have some more plumbing to do.

Overall, this leads to an editorial question for HTML experts: Would it be better to associate a "parent" Document/Worker/Worklet with each Realm (and reference it in all the appropriate places), or to deepen the use of environment settings objects, so that more logic indirects through their algorithms (thus avoiding assembling ever-larger switch statements for global type)? I'm fine with writing up either; the former sounds like less work/a smaller delta.

/cc @bzbarsky. At a glance, the proposed semantics of inheriting from the "parent settings object" seem most likely to integrate well without major issues. (I'm glad these have a settings object at all; that wasn't clear from the proposal.)

Note that the Realm champion group agreed on these semantics in https://github.com/tc39/proposal-realms/issues/225. It wasn't clear to me either at first, so I asked.

Here is a mix of vague concerns and concrete questions that I've been thinking about in this space. I think this proposal gives reasonable answers to most of them, but perhaps not all (especially the vague concerns).

  • Right now every realm is a window or a worker. I think there are probably parts of the web and spec ecosystem that make this assumption, especially around the agent cluster business. Breaking that assumption (which could be stated something like, every realm either has a document or is only asynchronously available) could be tricky.

Thanks for pointing out a bunch of these cases below; I'll be happy to have help identifying more of them. Given successful past work on adding Worker and Worklet, I was hoping that we'll be able to figure everything out before too long. If we are left with errors or omissions (e.g., in unmaintained specs or earlier proposals), I'd want to make it clear to future spec readers and editors that the intention is to forward all behavior and state from the enclosing environment. Maybe we could write this in a note somewhere?

As far as agent clusters go, Realms created through the Realm API are in the same agent as their parent Realm. I'm not sure how/where to formalize/document this. Do you see any particular difficulties with integration with agent clusters?

  • What happens if one of these realms is used for an entry realm/incumbent realm for a web platform API, like window.open() or worker.postMessage()? (I think they cannot end up as current or relevant realms since these realms do not have web platform APIs inside of them.)

Yep, I see how this PR fails to handle this case. I think they should act like their parent Realm, which must (eventually, recursively) be something with already-defined semantics, e.g., a Window, Worker, or Worklet.

  • How will these realms behave when faced with host-specific scenarios such as resolving modules, or reporting errors? E.g. what happens in terms of window.onerror reporting, and the reporting API, if you do jsRealmGlobal.eval("throw new Error('foo')")?

Another good catch; again, it should forward to the error handler for the parent Realm (previous discussion).

  • How will objects from these realms behave when faced with web platform features that depend on every object having a realm/global object pointer? (Those features might assume such a global is a window or a worker.) E.g., what happens when you take an object from one of these realms and feed it into call a user object's operation, such as when using addEventListener()?

In general, my understanding is that we only end up using the "associated Realm" of functions and platform objects, so I'm failing to see where an addition mismatch would come from.

I'm having trouble finding where the "call a user object's operation" algorithm assumes that the global is a Window or Worker; I just see its use of the relevant exection context, which is defined in this PR. Maybe there's some other algorithm that runs into this issue?

  • How do these realms interact with "can run script" checks which currently depend on browsing context pointers and fully active status? Arguably these realms, since they are not attached to a fully active document, should never be able to run script.

Heh, I agree with that reading of this PR, which obviously isn't the intention. Again, this should forward up through the parent Realm.

  • How does this proposal mesh with the web platform's general move away from allowing synchronous cross-realm access (like iframe), in favor of asynchronous realm-creation APIs (like portals, workers/worklets, and iframe disallowdocumentaccess (#4606))? If we guard future powerful web platform features behind a "no sync cross-realm access allowed" opt-in, will we be able to prohibit the creation of these realms (e.g. from the host hook)? This also touches on the implementer interest question; it's not clear there's implementer support for adding a new way to synchronously create realms on the web.

I'm a big fan of new things in the web platform that allow splits into multiple processes/agent clusters--these mechanisms enable really strong isolation. I see the benefit of Realms to be complementary: they enable scenarios like emulating one environment on top of another, as well as creating sub-environments, e.g., for testing, as well as gradually migrating legacy code. So, I'm having trouble understanding what you're getting at with "general move"--these features seem complementary.

About implementer interest: maybe we could ask about this at the TC39 presentation where Realms is proposed for Stage 3? I wouldn't mind collecting positions and other kinds of feedback beforehand, but overall, I think the Realms proposal repository would be a better place to do so than this issue.

littledan avatar Mar 09 '20 18:03 littledan

As far as agent clusters go, Realms created through the Realm API are in the same agent as their parent Realm. I'm not sure how/where to formalize/document this. Do you see any particular difficulties with integration with agent clusters?

Well, I think https://html.spec.whatwg.org/#integration-with-the-javascript-agent-formalism and https://html.spec.whatwg.org/#integration-with-the-javascript-agent-cluster-formalism make a lot of assumptions about everything being a window or worker (or worklet). Those would need extensive updates. And those sections have a bit of preexisting foundational shakiness which makes this hard:

  • It seems for non-window agents we talk about an agent's "set of realms", but for windows we have a realm -> agent pointer. (Set, e.g., in https://html.spec.whatwg.org/#initialise-the-document-object.) Ideally https://github.com/tc39/ecma262/issues/1357 would get solved and then we'd fix everything to have a realm -> agent pointer.

  • https://github.com/whatwg/html/issues/5210 is related.

In general, my understanding is that we only end up using the "associated Realm" of functions and platform objects, so I'm failing to see where an addition mismatch would come from.

Nope, we use it for user-provided objects, in https://heycam.github.io/webidl/#call-a-user-objects-operation step 4. This shows up in real-world code via something.addEventListener("event", { handleEvent() }) consulting the object's realm (not the handleEvent function's realm).

I'm having trouble finding where the "call a user object's operation" algorithm assumes that the global is a Window or Worker

I think you're right. I may have been thinking of the error reporting in https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke step 2.10.1, which builds on more shaky foundations (https://github.com/whatwg/html/issues/958).

So, I'm having trouble understanding what you're getting at with "general move"--these features seem complementary.

The intention is to prevent creation of sync-accessible realms, so there's a conflict, not a complement.

About implementer interest: maybe we could ask about this at the TC39 presentation where Realms is proposed for Stage 3?

I think you'll separately need implementer interest for the web platform implications before we can consider this for HTML. Implementation in JavaScript engines is one thing, but exposure to the web is another, often involving a different constituency (depending on the browser engine).

domenic avatar Mar 09 '20 19:03 domenic

So, I'm having trouble understanding what you're getting at with "general move"--these features seem complementary.

The intention is to prevent creation of sync-accessible realms, so there's a conflict, not a complement.

Where can I find more documentation about this intention, and how it relates to the use cases I mentioned? It'd be good to forward this feedback to TC39!

littledan avatar Mar 09 '20 19:03 littledan

I'm not sure it's documented centrally. It's more of a guiding principle in the development of new web APIs like workers, worklets, portals, etc. And disallowdocumentaccess allows us to "fix" the incorrect default that iframes have. Ideally we'll be able to move to a world where all realms are isolated from each other, with separate event loops. And there are very-early-stage experiments with rewarding this behavior (or punishing its opposite), e.g. never slow mode imagines a world where users have to give permission for a page to use slow APIs like sync realm creation, or you could use document policy to get that guarantee (and potentially get access to powerful features in exchange), etc.

You can also see it in the design of "meta-frameworks" like AMP which only allow executing JavaScript in a worker, and ensure all iframes are third-party so that they are isolated into separate event loops. These techniques are making their way into standards as well. (Although some of the AMP techniques are controversial, from what I can tell the ones about prohibiting performance worst-practices like document.write(), sync XHR, or sync realm creation are generally supported.)

domenic avatar Mar 09 '20 19:03 domenic

Edit: Let's have the conversation about whether we should go ahead with Realms, or whether they contradict web platform goals, in https://github.com/tc39/proposal-realms/issues/238. We can use this thread to work out the HTML integration on a technical level. I think the proposal repository is a better place to give this kind of high-level feedback because it is more likely to be visible to the people who are working on this proposal and the rest of TC39.

(Previous response collapsed in details)

Realms are definitely designed to have synchronous access to each other, sharing a common heap. Is this an "incorrect default"? Is the idea that Workers should supersede proposed Realm use cases?

I'd be interested to understand why sync realm creation is considered slow. (I'd imagine that the Realm API would be less overhead than iframe creation, but who knows.) It would indeed be unfortunate to introduce an API at the same time as introducing a mode which bans it.

littledan avatar Mar 09 '20 21:03 littledan

I don't plan to engage much on the TC39 repository; I'll leave that to others.

Realms are definitely designed to have synchronous access to each other, sharing a common heap. Is this an "incorrect default"? Is the idea that Workers should supersede proposed Realm use cases?

Yes; I've been giving this feedback to the realms champions for years. (This is part of why I am not excited about engaging in TC39 on the subject.)

It would indeed be unfortunate to introduce an API at the same time as introducing a mode which bans it.

I agree.

domenic avatar Mar 09 '20 22:03 domenic

I'm trying to wrap my head around the missing parts here if we keep with the forwarding settings object architecture. As I'm slowly doing this Domenic's complexity objections become more reasonable to me. Conceptually I still find the forwarding mechanic to be simple and generalizable, but a big effort seems to be needed to ensure that the resulting web specs remain actually coherent.

1. The invariant that all globals are windows/workers is broken.

An audit is needed here and in other web specs. This seems like the big outstanding TODO.

In messageEvent.source, for instance, the source attribute refers to "the Window object from which the message came", and doesn't refer to the global. With this PR that sentence becomes incoherent.

2. Implications of user Realms having their own module map

I'm not exactly clear what the implications are. Step 2 https://html.spec.whatwg.org/#fetch-a-single-module-script has an implicit assumption currently that each document (and thus event loop) has one fetch task per module map url key. This PR is morally equivalent in having the module map key be something like url+realm, is that right?

That might have implementation concerns, we should follow up with @yuki3. The user-realm module map entries are GCable, presumably, since user Realms have independent lifetimes, and the map would need to be additionally weakly keyed off the Realms, or something. Might be complicated.

3. The incumbent/entry settings object calculation

When determining the incumbent, the settings object is pulled off topmost execution context's Realm. In case the topmost execution context is a user Realm, it'll get that user Realm's forwarding settings object. That settings object behaves like the root settings object except in 3 cases AFAICT:

  1. Its Realm is the user Realm, not the root Realm
  2. It has its own execution context
  3. It has its own module map

I'm not seeing any obvious problems with this setup, e.g. the "prepare to run script" and "prepare to run callback" algorithms and their cleanup counterparts seem to be work as intended. Does this extend to all algorithms that use these concepts?

4. Error reporting

At first I thought userRealm.eval() would always be called by another user script, which ultimately must top out at a non-user realm. Uncaught exceptions from userRealm.eval propagate to the caller, which would eventually trigger the Runtime script error semantics on the root document.

But I guess that's wrong, as userRealm.eval could be posted to a task, and so error reporting needs to forward as well, which is not described in this PR.

5. Events and addEventListener() spec

This is beyond my expertise. Perusing https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener makes it seem like it might "just work" currently, since there's already a check if the callback Realm's global is a Window. An audit is also called for where places that have Realm and global-related logic should be explicitly reasoned through.

6. Realms cannot run any script since they do not have an active document.

My reading is that currently this PR is incorrect in the other way in that always allows a script to run in a user Realm, even if the root Document has disabled scripting.

Both https://html.spec.whatwg.org/#check-if-we-can-run-script and https://html.spec.whatwg.org/#concept-environment-script have checks for the global being a Window. In user realms' case, the global isn't a Window, so my reading is that step 1 of "check if we can run script" does not apply, step 2 does not apply since per the 3rd bullet point of "Scripting is enabled", scripting is enabled if the setting's global object is not a Window.

syg avatar Nov 06 '20 19:11 syg

In messageEvent.source, for instance, the source attribute refers to "the Window object from which the message came"

Yeah, that should almost certainly refer to a WindowProxy. The actual Window might not even be in the same process in a modern browser.

But yes, the thing stored in source is not a global, and how to determine it in the user Realm case is not obvious.

bzbarsky avatar Nov 07 '20 02:11 bzbarsky

These comments make me think that the environment settings object was the wrong layer to do this "forwarding" at, and instead, we should frame this integration as, "synthetic" Realms created with the Realm API refer to a "principal realm" which is used for all related web specs. This would avoid the need to do the large amount of refactoring that the approach in this PR implies. For example, for the source property, I was imagining that the source would be the outer Window or Worker where the Realm was created, for the current Realm which made the call to postMessage. I'm working on a new PR revision to frame Realm/HTML integration this way.

littledan avatar Nov 07 '20 12:11 littledan

Thanks! This helps me a lot putting some perspective on how I can work this out going through the details of this PR. I'll be in sync with @littledan to provide any support necessary.

leobalter avatar Nov 08 '20 00:11 leobalter

I've pushed a rebase and refactor of this PR, described in its commit message. This new version reflects the semantics that I was intending originally (that the Realms created with the Realm API never leak out into Web specs in a non-trivial way, that you're always deferring to their parent) but which I failed to express editorially, as has been pointed out above.

To answer the questions @syg listed above, in terms of this version:

1. The invariant that all globals are windows/workers is broken.

I guess this is already broken, since we added Worklets :) I fixed a little reference to that, as a drive-by. More types of global objects have been added in the past. I'm having trouble understanding what the invariant is here. This PR preserves the (modified) invariant that all principal global objects implement WindowProxy, WorkerGlobalScope or WorkletGlobalScope. However, it also exposes synthetic global objects which do not implement any WebIDL interface.

An audit is needed here and in other web specs. This seems like the big outstanding TODO.

This is true, but I think the scope is a bit reduced. We mostly have to worry about if other specs reach into JavaScript-internal data structures to get the [[Realm]] (fairly unlikely) or ask for the "current Realm" (more likely). In the latter case, this PR includes a note indicating that "current Realm" should be replaced by "current principal Realm" in other specs, generally. We'll have to do an audit of other specs for these two issues before landing.

In messageEvent.source, for instance, the source attribute refers to "the Window object from which the message came", and doesn't refer to the global. With this PR that sentence becomes incoherent.

The source comes from the incumbent settings object in https://html.spec.whatwg.org/#posting-messages:dom-messageevent-source . This version of the PR ensures that the incumbent Realm is always a principal Realm (so it is either a Window, Worker or Worklet).

2. Implications of user Realms having their own module map

I'm not exactly clear what the implications are. Step 2 https://html.spec.whatwg.org/#fetch-a-single-module-script has an implicit assumption currently that each document (and thus event loop) has one fetch task per module map url key. This PR is morally equivalent in having the module map key be something like url+realm, is that right?

Yes, the module map is used as a synchronization point, so either we need the realm as part of the module map key, or to give each realm its own separate module map. I think these are equivalent.

That might have implementation concerns, we should follow up with @yuki3. The user-realm module map entries are GCable, presumably, since user Realms have independent lifetimes, and the map would need to be additionally weakly keyed off the Realms, or something. Might be complicated.

The current PR hangs the module map off of the Realm, whether it's a principal or synthetic Realm, so no need for complicated GC semantics I think.

3. The incumbent/entry settings object calculation

When determining the incumbent, the settings object is pulled off topmost execution context's Realm. In case the topmost execution context is a user Realm, it'll get that user Realm's forwarding settings object. That settings object behaves like the root settings object except in 3 cases AFAICT:

1. Its Realm is the user Realm, not the root Realm

2. It has its own execution context

Note, the execution context ended up not being needed, so the synthetic realm settings object omits it.

3. It has its own module map

I'm not seeing any obvious problems with this setup, e.g. the "prepare to run script" and "prepare to run callback" algorithms and their cleanup counterparts seem to be work as intended. Does this extend to all algorithms that use these concepts?

Since no synthetic Realms don't implement any WebIDL interface and cannot be used in exposed, algorithms like "prepare to run script" and "prepare to run a callback" never need to run on it. And it's impossible to invoke these algorithms on synthetic realms in this PR version, by construction, as those algorithms expect an environment settings object, but synthetic realms do not have an environment settings object any more (instead, they have a synthetic realm settings object).

4. Error reporting

At first I thought userRealm.eval() would always be called by another user script, which ultimately must top out at a non-user realm. Uncaught exceptions from userRealm.eval propagate to the caller, which would eventually trigger the Runtime script error semantics on the root document.

But I guess that's wrong, as userRealm.eval could be posted to a task, and so error reporting needs to forward as well, which is not described in this PR.

The "target" for "report an error" is always a principal Realm, and "report an exception" will always find the corresponding principal, not synthetic, Realm, since it goes via the environment settings object. I'm not sure if this covers the path that you're thinking of; if it doesn't, the solution is probably through adding "the principal realm of" somewhere.

5. Events and addEventListener() spec

This is beyond my expertise. Perusing https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener makes it seem like it might "just work" currently, since there's already a check if the callback Realm's global is a Window. An audit is also called for where places that have Realm and global-related logic should be explicitly reasoned through.

This is beyond my expertise as well, but skimming the DOM spec, I think one thing that may need to be updated is WebIDL's associated Realm definition: the associated Realm of platform objects will always be a principal Realm, but for function objects, we'll need to reference function.[[Realm]]'s principal realm. This issue comes up in the inner invoke algorithm. I'm not really sure what the issue is that you're referring to with addEventListener--I think the Realms there are already all principal Realms by construction (since they have WebIDL interfaces implemented on them).

6. Realms cannot run any script since they do not have an active document.

My reading is that currently this PR is incorrect in the other way in that always allows a script to run in a user Realm, even if the root Document has disabled scripting.

Both https://html.spec.whatwg.org/#check-if-we-can-run-script and https://html.spec.whatwg.org/#concept-environment-script have checks for the global being a Window. In user realms' case, the global isn't a Window, so my reading is that step 1 of "check if we can run script" does not apply, step 2 does not apply since per the 3rd bullet point of "Scripting is enabled", scripting is enabled if the setting's global object is not a Window.

I'm having trouble understanding how this scenario would come up. It looks to me like the entrypoints to the "scripting is enabled"/"scripting is disabled" algorithms come from dealing with elements or documents, so they'll always pass in the environments settings object of a Window, Worker or Worklet. I think if we leave these algorithms as is, in terms of expecting an environment settings object as an argument, then this amounts to an implicit assertion that it's dealing with a principal Realm, as synthetic Realms no longer have an environment settings object.


One thing I could do is sprinkle the text with assertions that various realms being passed around are principal. I'm not sure whether or not this is necessary or helpful. Thanks for your reviews and patience as I figure out how to frame this PR.

littledan avatar Nov 09 '20 17:11 littledan

@domenic noted

However a major point of contention remains around the integration with the web platform's module system (tc39/proposal-realms#261). In current implementations the module map is tied to "real" realms, which come with associated security principals, fetch clients, HTTP cache partitions, etc. These "synthetic" realms want to create their own module maps, which will require significant rearchitecting, in both spec and implementation.

I'd like to understand what this means. This PR contains the spec update. Are there more spec updates expected? Could you elaborate on the implementation concerns? I'd like to understand what the problem is with forwarding to the relevant principal Realm, with the associated properties you mention.

littledan avatar Nov 16 '20 23:11 littledan

Discussion about exposing Web APIs from Realms' globals by default has been ongoing; see https://github.com/tc39/proposal-realms/issues/284#issuecomment-742373591 . Tentatively, it seems reasonable to expose certain Web APIs (such as TextEncoder and atob) on Realms. This will take some more significant work on the HTML/DOM/WebIDL side, to determine exactly what to expose, and build the specification mechanics to do so; I'm not sure when we will get around to this.

littledan avatar Dec 10 '20 08:12 littledan

To be clear, I'd expect that to be part of the work done before entering stage 3.

domenic avatar Dec 10 '20 14:12 domenic

To be clear, I'd expect that to be part of the work done before entering stage 3.

@domenic I agree at the point I want the thread for https://github.com/tc39/proposal-realms/issues/284#issuecomment-742373591 to be resolved before Stage 3 to tell a clear direction for how this integration and implementation should go.

At the same time, I feel like TC39 should not exercise any decision making or governance over specific host APIs. The specifics of this work depends on the Web Platform side.

I believe we have the current options being at stake there:

  1. The proposed HostInitializeSyntheticRealm hook disallows adding properties ("_It is not expected that this hook would add properties to the Realm's global object.")
  2. The proposal allow properties initialization a. It might still disallow something specific like non-configurable properties b. It might just ignore item a

I'm in favor of 2, possibly 2.a. I recognize the item 1 is a no go for to make this integration possible and I believe it won't reflect other platforms as well such as Node, XS, etc.

The idea of not allowing any host properties seems, IMO, weakened by the fact we already have ECMAScript built-ins already. A synthetic realm is not super "clean" by nature.

Saying that, I hope we can find a good working direction for what should be added in this Web Platform integration, but I hope it doesn't become a blocker alone.

leobalter avatar Dec 10 '20 21:12 leobalter

See https://github.com/tc39/proposal-realms/issues/238#issuecomment-766300440

erights avatar Jan 24 '21 06:01 erights

My understanding of the feedback from Chrome, delivered by @syg in the May 2021 TC39 meeting, was that for Realms to be acceptable for Stage 3, the necessary change in this patch is that we move towards the model where there is one module map per document, rather than per Realm, and this module map is keyed by both the module specifier and Realm.

The observable impact of this change will be to guarantee that there be only one fetch per module specifier per document (without relying on unspecified network caching behavior which probably exists reliably cross-browser in practice). I don't think this change has any effect on whether a future "compartments" proposal can define a different module map within a document--it's just that we don't need such a mechanism for Realms.

My understanding of Chrome's position is that the WebIDL work to expose the right set of globals needs to be done before landing this PR and before TC39 Stage 4, but is not a TC39 Stage 3 prerequisite. @syg please correct me if I'm misunderstanding any of this.

I'm working on a rebase + change to keying, which should be ready some time this week; apologies for my delay here, but I think the agreed-on semantics are well-understood among those active in this conversation.

littledan avatar Jul 06 '21 09:07 littledan

Thanks for checking, that sounds about right.

syg avatar Jul 07 '21 20:07 syg

I've now uploaded a patch that has the agreed-upon semantics. The idea is that the enclosing environment settings object has the only module map that is fetched into over the network. So the specific realm is no longer passed into the procedure to fetch a single module--this is instead always done in the document/worker level. Synthetic realms also have their own module maps that are copies of the modules from the main module map, so they can have their own instance that closes over the appropriate global object, but they come from the parent document/worker.

Reviews are appreciated!

littledan avatar Jul 12 '21 15:07 littledan

I rebased and updated to some name changes in the proposal - lemme know if this is blocked on anything on our side.

Ms2ger avatar Jan 18 '22 15:01 Ms2ger

Thanks @Ms2ger for taking this on. I think @domenic will have to review the module bits, which seems like the most substantive change as at least per tc39/proposal-shadowrealm#225 (comment) that's the main difference. Is that still a largely accurate summary?

I believe that's correct.

It seems confusing that JS will continue using "current Realm", but we can't. Don't we only have to make the distinction for APIs that can be used inside a shadow realm? And only then in a limited number of cases? I'd prefer a solution where we don't introduce "current underlying Realm" as synonym for JS's "current Realm". (Apologies if we've discussed this before. It's been so long that I've forgotten most context.)

I wasn't involved here from the start, but from the discussion upthread, it seems like we came up with this setup to avoid auditing the entire web platform for uses of "current Realm" that assume they get a "web" realm (window or worker); ES doesn't need this, because it (presumably) never makes such an assumption. Does that answer your question?

Why is this called synthetic and not shadow?

I'm guessing this is because ShadowRealm was called Realm before, and this was the adjective we came up with to distinguish them from other realms. I can change that.

Ms2ger avatar Mar 14 '22 14:03 Ms2ger

Can we instead change the ECMAScript definitions so that "current Realm" continues to mean "non-shadow Realm", and thus avoid changing tons of specs?

domenic avatar Mar 14 '22 15:03 domenic

Wouldn't builtin methods executing inside a shadow realm have their current realm be a shadow realm, on the web or otherwise?

ljharb avatar Mar 14 '22 15:03 ljharb

It seems we'd have to audit "current Realm" either way though, no? So I guess I'd rather only add "current principal Realm" or some such and use that as needed. In most cases web platform standards will use "current global object" and such, which we're defining to use the current principal Realm.

annevk avatar Mar 15 '22 13:03 annevk

It seems we'd have to audit "current Realm" either way though, no?

It depends on who you mean by "we". If we go with keeping "current Realm" to mean "principal realm", then web standards authors would not, but JS spec editors, and to a lesser extent HTML and Web IDL spec editors, would. Whereas if we change the meaning of "current Realm" to also include shadow realms, then everyone would need such audits. So I prefer the former.

In most cases web platform standards will use "current global object" and such, which we're defining to use the current principal Realm.

I'd be very uncomfortable with having "current global object" / "current environment settings object" not be 1:1 with "current realm".

domenic avatar Mar 15 '22 15:03 domenic

Hi folks, I'd like to start moving this forward again, since implementations are ongoing. Do I understand correctly that the main concerns at this point are about whether "current {Realm/...}" might be a ShadowRealm or not? How do we reach a conclusion there?

Ms2ger avatar May 11 '22 14:05 Ms2ger