-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript ShadowRealm proposal integration #9893
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes to the module loading algorithms look ok.
For the record, we (people working on modules in TC39) have some ideas for splitting the stateless and stateful parts of Module Records in ECMA-262. If/once that will happen, it would be great to share a module map for the stateless parts across principal realms and shadow realms, so that basically in this case:
import "/foo";
new ShadowRealm().importValue("/foo", "bar");
we only call into fetch once (to get the stateless part) and then we create the stateful part twice in both realms.
I think this could benefit from review at this point |
Delete the Exposed attribute from AbortSignal.timeout, letting it inherit [Exposed=*] from AbortSignal. Cf. whatwg/html#9893 where other timers are being exposed in ShadowRealm global contexts.
ShadowRealms reached 2.7 in TC39. Acceptance of this PR by WHATWG editors is a blocking requirement for Stage 3, though it probably shouldn't be landed until the Web API set is finalized. |
4fd9960
to
9d8d9ec
Compare
This aligns with the lastest version of the PR implementing the javascript shadow realm proposal: whatwg/html#9893 This commit simply performs the rename before implementing the behaviour change.
As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness.
As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness.
As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness.
I'm |
Is there any reason to ever use the current principal realm, other than to grab the current principal global object and current principal settings object? If not, we probably should not EDIT: I'm pasting here a message I sent to Ms2ger, since it might help clarify.
|
Looking through all the usages of the current principal global object, it seems like it's also not meaningfully different from the global object associated to the current realm (i.e. the old current global object). Out of 8 usages:
Looking at the other specs that reference the curent global object, none of them are about APIs exposed in ShadowRealms. The only places where we actually need the current principal global object is when we enable/disable some features based on which global we are running in:
So again, do we actually need the concept of the current principal global object, or can we continue using the current global object (with the manual handling in HostLoadImportedModule to actually grab the global object of the principal realm)?
Is it intentional that ShadowRealms ignore the principal realm's import map? |
Talking to Nic, it seems that when you need a realm, you're most likely to want to use the (potentially synthetic) current realm, and when you need a settings object, you're most likely to want the current principal settings object. Practically the suggestion is that we'd remove the "current principal realm" definition, and where it's really needed, people can go through the current principal settings object. Any objections to that, @domenic (or others)? |
…, a=testonly Automatic update from web-platform-tests Change 'shadowrealm' global into a shorthand for all possible ShadowRealm scopes In order to automatically run tests not only in a ShadowRealm created in a window scope, but also in ShadowRealms created in other realms, change the 'shadowrealm' global type to a collection, and rename the existing ShadowRealm handler to 'shadowrealm-in-window'. -- Remove monkeypatch of globalThis.self in ShadowRealm As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness. -- Factor out JS code that will be common to multiple ShadowRealm handlers We will add multiple ShadowRealm handlers, and they will all need to set up certain global properties. Avoid repeating this code in each handler as well as in idlharness-shadowrealm.js. This should also increase readability, which is good since the ShadowRealm setup code can be confusing. -- Add 'shadowrealm-in-shadowrealm' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-shadowrealm.html variant. The test wrapper creates an outer ShadowRealm, which creates an inner ShadowRealm and runs the tests inside that, relaying the results through the outer ShadowRealm. -- Add 'shadowrealm-in-dedicatedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-dedicatedworker.html variant. The test loads an intermediate .any.worker-shadowrealm.js wrapper into a Worker, and forwards the message port to the Worker's message port so that fetch_tests_from_worker can receive the results. -- Add 'shadowrealm-in-sharedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-sharedworker.html variant. The test loads the same intermediate .any.worker-shadowrealm.js wrapper as .any.shadowrealm-in-dedicatedworker.html, but populates a 'port' variable with the port received from the connect event, instead of calling the global postMessage since that won't work in a SharedWorker. -- Add 'shadowrealm-in-serviceworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-serviceworker.html variant. We have to use a slightly different .any.serviceworker-shadowrealm.js wrapper from the wrapper used for the other types of workers, because dynamic import() is forbidden in ServiceWorker scopes. Instead, add a utility function to set up a fakeDynamicImport() function inside the ShadowRealm which uses the fetch adaptor to get the module's source text and evaluate it in the shadowRealm. Also add a case for ServiceWorkers to getPostMessageFunc(), which returns a postMessage() drop-in replacement that broadcasts the message to all clients, since test result messages from the ShadowRealm are not in response to any particular message received by the ServiceWorker. Note '.https.' needs to be added to the test path. -- Add 'shadowrealm-in-audioworklet' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-audioworklet.html variant. The wrapper here is similar to the one for ServiceWorkers, since dynamic import() is also forbidden in worklet scopes. But additionally fetch() is not exposed, so we add a utility function to set up the ability to call the window realm's fetch() through the AudioWorklet's message port. We also add /resources/testharness-shadowrealm-audioworkletprocessor.js to contain most of the AudioWorklet setup boilerplate, so that it isn't written inline in serve.py. Note '.https.' needs to be added to the test path. -- wpt-commits: 9c8db8af89efbe0f67b215af2a6b49e9564e2971, 65a205aea5d02ff5bea7b1a0579287035d02d6c4, eb9c8e7259ef8bd5cca5019c1ca15ccd430e81dc, 3a20c56893472783b5e20c0d61cbb7b7b278cc6d, 7d8458ed291b139307430a102180c9a617d7876e, 42160ae827c863ac6787c8451fe377901c8f0652, 59367bb21d053abb9ed6de3cca5409486816acc9, 60d6c48e5fa76876bc3924b9d6185dfb56c9ab1c wpt-pr: 49108
I'm fine adding such guidance, but I don't think it makes sense to only define some subset of concepts; there should be the full matrix of 2x3 concepts available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine adding such guidance, but I don't think it makes sense to only define some subset of concepts; there should be the full matrix of 2x3 concepts available.
As of today in this PR there are only 4 concepts:
- current realm (from ECMAScript)
- current principal realm
- current principal settings object
- current principal global object
The places where it would HTML would have used the "current settings object" are just either to grab the realm from it (i.e. in the modules algorithms), so this PR just uses the "current realm" directly, or to grab the global object (in HostPromiseRejectionTracker), so this PR just grabs it from the "current realm" instead.
As per #9893 (comment), I believe in all current usages of the "current principal global object", except for https://html.spec.whatwg.org/#pause, it would be cleaner (*) to use the "current global object": it probably makes sense to at least re-introduce it.
- "cleaner" = they are equivalent because those APIs depend on the DOM, the DOM is not available in ShadowRealm, and thus they are not exposed there. However, the rule of thumb I'm applying is, for example, "if ShadowRealms had their own DOM, should
customElements.define
define an element in the ShadowRealm itself or in the principal realm?"
…, a=testonly Automatic update from web-platform-tests Change 'shadowrealm' global into a shorthand for all possible ShadowRealm scopes In order to automatically run tests not only in a ShadowRealm created in a window scope, but also in ShadowRealms created in other realms, change the 'shadowrealm' global type to a collection, and rename the existing ShadowRealm handler to 'shadowrealm-in-window'. -- Remove monkeypatch of globalThis.self in ShadowRealm As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness. -- Factor out JS code that will be common to multiple ShadowRealm handlers We will add multiple ShadowRealm handlers, and they will all need to set up certain global properties. Avoid repeating this code in each handler as well as in idlharness-shadowrealm.js. This should also increase readability, which is good since the ShadowRealm setup code can be confusing. -- Add 'shadowrealm-in-shadowrealm' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-shadowrealm.html variant. The test wrapper creates an outer ShadowRealm, which creates an inner ShadowRealm and runs the tests inside that, relaying the results through the outer ShadowRealm. -- Add 'shadowrealm-in-dedicatedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-dedicatedworker.html variant. The test loads an intermediate .any.worker-shadowrealm.js wrapper into a Worker, and forwards the message port to the Worker's message port so that fetch_tests_from_worker can receive the results. -- Add 'shadowrealm-in-sharedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-sharedworker.html variant. The test loads the same intermediate .any.worker-shadowrealm.js wrapper as .any.shadowrealm-in-dedicatedworker.html, but populates a 'port' variable with the port received from the connect event, instead of calling the global postMessage since that won't work in a SharedWorker. -- Add 'shadowrealm-in-serviceworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-serviceworker.html variant. We have to use a slightly different .any.serviceworker-shadowrealm.js wrapper from the wrapper used for the other types of workers, because dynamic import() is forbidden in ServiceWorker scopes. Instead, add a utility function to set up a fakeDynamicImport() function inside the ShadowRealm which uses the fetch adaptor to get the module's source text and evaluate it in the shadowRealm. Also add a case for ServiceWorkers to getPostMessageFunc(), which returns a postMessage() drop-in replacement that broadcasts the message to all clients, since test result messages from the ShadowRealm are not in response to any particular message received by the ServiceWorker. Note '.https.' needs to be added to the test path. -- Add 'shadowrealm-in-audioworklet' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-audioworklet.html variant. The wrapper here is similar to the one for ServiceWorkers, since dynamic import() is also forbidden in worklet scopes. But additionally fetch() is not exposed, so we add a utility function to set up the ability to call the window realm's fetch() through the AudioWorklet's message port. We also add /resources/testharness-shadowrealm-audioworkletprocessor.js to contain most of the AudioWorklet setup boilerplate, so that it isn't written inline in serve.py. Note '.https.' needs to be added to the test path. -- wpt-commits: 9c8db8af89efbe0f67b215af2a6b49e9564e2971, 65a205aea5d02ff5bea7b1a0579287035d02d6c4, eb9c8e7259ef8bd5cca5019c1ca15ccd430e81dc, 3a20c56893472783b5e20c0d61cbb7b7b278cc6d, 7d8458ed291b139307430a102180c9a617d7876e, 42160ae827c863ac6787c8451fe377901c8f0652, 59367bb21d053abb9ed6de3cca5409486816acc9, 60d6c48e5fa76876bc3924b9d6185dfb56c9ab1c wpt-pr: 49108
…, a=testonly Automatic update from web-platform-tests Change 'shadowrealm' global into a shorthand for all possible ShadowRealm scopes In order to automatically run tests not only in a ShadowRealm created in a window scope, but also in ShadowRealms created in other realms, change the 'shadowrealm' global type to a collection, and rename the existing ShadowRealm handler to 'shadowrealm-in-window'. -- Remove monkeypatch of globalThis.self in ShadowRealm As per whatwg/html#9893, ShadowRealmGlobalScope should have a `self` attribute already. There is no need to monkeypatch it for the test harness. -- Factor out JS code that will be common to multiple ShadowRealm handlers We will add multiple ShadowRealm handlers, and they will all need to set up certain global properties. Avoid repeating this code in each handler as well as in idlharness-shadowrealm.js. This should also increase readability, which is good since the ShadowRealm setup code can be confusing. -- Add 'shadowrealm-in-shadowrealm' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-shadowrealm.html variant. The test wrapper creates an outer ShadowRealm, which creates an inner ShadowRealm and runs the tests inside that, relaying the results through the outer ShadowRealm. -- Add 'shadowrealm-in-dedicatedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-dedicatedworker.html variant. The test loads an intermediate .any.worker-shadowrealm.js wrapper into a Worker, and forwards the message port to the Worker's message port so that fetch_tests_from_worker can receive the results. -- Add 'shadowrealm-in-sharedworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-sharedworker.html variant. The test loads the same intermediate .any.worker-shadowrealm.js wrapper as .any.shadowrealm-in-dedicatedworker.html, but populates a 'port' variable with the port received from the connect event, instead of calling the global postMessage since that won't work in a SharedWorker. -- Add 'shadowrealm-in-serviceworker' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-serviceworker.html variant. We have to use a slightly different .any.serviceworker-shadowrealm.js wrapper from the wrapper used for the other types of workers, because dynamic import() is forbidden in ServiceWorker scopes. Instead, add a utility function to set up a fakeDynamicImport() function inside the ShadowRealm which uses the fetch adaptor to get the module's source text and evaluate it in the shadowRealm. Also add a case for ServiceWorkers to getPostMessageFunc(), which returns a postMessage() drop-in replacement that broadcasts the message to all clients, since test result messages from the ShadowRealm are not in response to any particular message received by the ServiceWorker. Note '.https.' needs to be added to the test path. -- Add 'shadowrealm-in-audioworklet' global This will add to any test with global=shadowrealm in its metadata, an .any.shadowrealm-in-audioworklet.html variant. The wrapper here is similar to the one for ServiceWorkers, since dynamic import() is also forbidden in worklet scopes. But additionally fetch() is not exposed, so we add a utility function to set up the ability to call the window realm's fetch() through the AudioWorklet's message port. We also add /resources/testharness-shadowrealm-audioworkletprocessor.js to contain most of the AudioWorklet setup boilerplate, so that it isn't written inline in serve.py. Note '.https.' needs to be added to the test path. -- wpt-commits: 9c8db8af89efbe0f67b215af2a6b49e9564e2971, 65a205aea5d02ff5bea7b1a0579287035d02d6c4, eb9c8e7259ef8bd5cca5019c1ca15ccd430e81dc, 3a20c56893472783b5e20c0d61cbb7b7b278cc6d, 7d8458ed291b139307430a102180c9a617d7876e, 42160ae827c863ac6787c8451fe377901c8f0652, 59367bb21d053abb9ed6de3cca5409486816acc9, 60d6c48e5fa76876bc3924b9d6185dfb56c9ab1c wpt-pr: 49108
<h6>Creating a Shadow Realm</h6> | ||
|
||
<p>When performing <span data-x="js-InitializeHostDefinedRealm">InitializeHostDefinedRealm</span> | ||
in the <code data-x="js-ShadowRealm-constructor">ShadowRealm</code> constructor, the steps to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally preferred the old steps for global object creation before dc9fddc as the steps if followed explicitly were more easily implementable without needing to add web specific changes into the javascript implementation. There is no clear hook for InitializeHostDefinedRealm
to say that it is being invoked in the ShadowRealm constructor.
I think this type of customization should ideally be explicitly stated at the call site of HostInitializeShadowRealm
, similar to how https://whatpr.org/html/9893/webappapis.html#creating-a-new-javascript-realm does where it is used like:
Let realm execution context be the result of creating a new realm given agent and the following customizations:
For the global object, create a new Window object.
For the global this binding, use browsingContext's WindowProxy object.
What makes this awkward is that HostInitializeShadowRealm
is being invoked in JS spec, where we would like to make that customization.
@@ -113690,25 +114036,15 @@ interface mixin <dfn interface>WindowOrWorkerGlobalScope</dfn> { | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess if we really need to have things conditionally exposed depending on whether the incumbent realm is a secure context, we'll also need to move isSecureContext
to UniversalGlobalScope. (2 lines above this)
|
||
// structured cloning | ||
any <span data-x="dom-structuredClone">structuredClone</span>(any value, optional <span>StructuredSerializeOptions</span> options = {}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still missing the event handlers that go along with the universally exposed stuff - onerror
, onrejectionhandled
, onunhandledrejection
.
I'm not sure if they should go here or in ShadowRealmGlobalScope. Adding them here might make things complicated. onerror
is part of GlobalEventHandlers which Document also includes. The latter two are part of WindowEventHandlers which HTMLBodyElement also includes. So either we add these to ShadowRealmGlobalScope, or we add them here and remove them from WorkerGlobalScope, GlobalEventHandlers, and WindowEventHandlers, then additionally re-add them to Document, HTMLBodyElement, and anywhere else they're supposed to be included.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(We'll also have to decide whether to have the weird signature that the onerror
handler has on Window and Worker globals)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to associate / plumb the shadow realm through the unhandled rejection hooks? Unhandled rejections for shadow realm promises cannot be reported in the main realm event because of the callable boundary. I see that HostPromiseRejectionTracker
only takes the promise, which may not be sufficient for the host to figure out which realm it belongs to.
Btw, there is still some pending implementation issues about which realm reactions are invoked in, but in the case of ShadowRealm they shouldn't apply since promises in these realms cannot interact with other realms.
I guess technically the host hook can lookup the current realm record.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll defer to @Ms2ger but I believe this is handled correctly by the current state of this PR's HostPromiseRejectionTracker. We get the ShadowRealm global from the running script's realm and otherwise from the current realm (although I'm not sure in which case the running script would be null during ShadowRealm execution.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok so HTML is already relying on the current realm.
@@ -113690,25 +114036,15 @@ interface mixin <dfn interface>WindowOrWorkerGlobalScope</dfn> { | |||
|
|||
undefined <span data-x="dom-reportError">reportError</span>(any e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On review, I think reportError
probably meets the criteria to be exposed in w3ctag/design-principles#510. Maybe move this to UniversalGlobalScope unless we have a good reason not to?
To replace #5339.
ShadowRealm
constructor denoland/deno#16211(See WHATWG Working Mode: Changes for more details.)
TODO:
/browsing-the-web.html ( diff )
/dom.html ( diff )
/embedded-content.html ( diff )
/form-elements.html ( diff )
/index.html ( diff )
/infrastructure.html ( diff )
/media.html ( diff )
/nav-history-apis.html ( diff )
/references.html ( diff )
/scripting.html ( diff )
/structured-data.html ( diff )
/timers-and-user-prompts.html ( diff )
/webappapis.html ( diff )
/workers.html ( diff )