-
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
Use inside settings to fetch the descendants of module worker in the worker module script graph #9571
Comments
Making this into a two-stage fetch that behaves half one way, and half another, doesn't make any sense to me. |
The benefits of this approach are:
Sure, the first fetch by necessity is different but everything after that uses the same settings. Having static and dynamic imports behave differently doesn't really make sense either. |
Having static and dynamic imports diverge makes perfect sense! The former is part of the initialization, initiated by the outside, and is done before the worker even exists (in some implementations, before the thread has even been spun up or the global object allocated). The latter is initiated by the inside, after initialization. In general, the outer page is initiating the initial graph fetch, and its CSP and security policies should apply. The inner worker is initiating dynamic imports, and so its security policies should apply. Trying to say that the worker code initiated the static imports seems incorrect, in that sense. It's the outer page that kicked it off. |
These sound like implementation details though. I think authors of worker code will be surprised if static and dynamic imports work differently.
In order to present a simpler conceptual model to web authors IMO it does makes more sense for this to behave as if the top level module is loading its static imports, even if that's not how it works internally. |
I think the authors of outer-page code will be surprised if the first fetch they kick off follow different security policies from the rest of the ones that follow it. Indeed, many web developers are used to an isomorphism: bundled code behaves the same as unbundled code. You are proposing to break that. So if anyone is presenting a more complex mental model, I believe it's your proposal. |
There is only be a single fetch when the worker code is bundled, and this would be unchanged. In unbundled code static imports would use a different CSP. I don't think this makes bundled code behave differently from unbundled code any more than it does already by virtue of that fact that it doesn't make any subsequent fetches. |
I can see that it may be surprising to some that there's a difference between child fetches in the initial module graph and dynamic imports, but still, I agree with @domenic. Especially this I think is compelling:
Also, as a data point, |
However, this is what we do for referrers, presumably? The top-level file is after all what is referring the imported files. And |
@youennf presented me with a case for the two-stage fetch in line with my thinking about authority above. In particular, what if the top-level file is a data: URL? In that case you would not want the scripts it references to be fetched with the authority of the parent document. In much the same way as you would not want that to happen with a data: URL |
Why not? When I type import 'data:text/javascript,import "./foo.html"'; in my parent document, I think it's the parent document that can be said to be fetching |
In that case you don't establish a new environment. But with a worker you do. And the environment that is established is that of an opaque origin. But then somehow that opaque origin is fetching resources with the authority (i.e., cookies, service worker(maybe not, given that matches on the URL?), no CORS) of the parent document. I think that goes against expectations. It would make sense if a |
I think my argument still makes sense with a worker. const w = new Worker('data:text/javascript,import "./foo.js"', { type: "module" }); I think the outer environment is what is causing |
@domenic and if it was not a |
I do not really see why we would treat workers and iframes differently in how they handle some of their subresources. For instance, if two contexts create the same shared worker at the same time, there is an inherent race on how/where the shared worker main script will be fetched. Also, from a service worker perspective, the shared worker main script fetch clientId is the ID of the context creating the shared worker object. |
After reviewing the above comments and discussing with @smaug---- I've changed my mind and think it's better to make static and dynamic imports' subresources both use the worker's settings object, since it's a new environment. The bundled/unbundled expectation may be broken, but it already doesn't always apply. For example the top-level CSP might allow only some origins, and bundling code would make everything use one origin. |
…dules Fixing web-platform-tests/interop#406 The test [dedicated|shared]-worker-import-csp.html will inject CSP headers on the top-level document for static import. https://github.com/web-platform-tests/wpt/blob/256877037fa53c4c90e48e7171a69ea0cef0d3be/workers/modules/dedicated-worker-import-csp.html#L21 And the top-level module worker script will 'static import' its descendants. https://github.com/web-platform-tests/wpt/blob/master/workers/modules/resources/static-import-remote-origin-script-worker.sub.js But due to the spec issue whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-csp.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-csp.html?label=experimental&label=master&aligned So removing these two tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these two files from interop-2023-modules completely)
…om interop-2023-modules Fixing web-platform-tests/interop#406 In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". https://github.com/web-platform-tests/wpt/blob/master/workers/modules/dedicated-worker-import-data-url-cross-origin.html#L13 And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' https://github.com/web-platform-tests/wpt/blob/master/workers/modules/resources/static-import-script-block-cross-origin.js The script "export-block-cross-origin.js" is same-origin with the document, but not same-origin with the worker script which is loaded by data: URI. Due to the spec issue, whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url-cross-origin.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-data-url-cross-origin.html?label=experimental&label=master&aligned So removing these two tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these two files from interop-2023-modules completely)
…worker-import-data-url.window.html from interop-2023-modules Fixing web-platform-tests/interop#406 In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. https://github.com/web-platform-tests/wpt/blob/2cd449b9df6f92862abac0143ac6fe674fd5278e/workers/modules/resources/import-test-cases.js#L13 https://github.com/web-platform-tests/wpt/blob/2cd449b9df6f92862abac0143ac6fe674fd5278e/workers/modules/resources/static-import-redirect-worker.js#L3 The script "export-on-load-script.js" is same-origin with the document, but not same-origin with the worker script which is loaded by data: URI. Due to the spec issue, whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url.any.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url.any.worker.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-data-url.window.html?label=experimental&label=master&aligned So removing these three tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these three files from interop-2023-modules completely)
…dules Fixing web-platform-tests/interop#406 The test [dedicated|shared]-worker-import-csp.html will inject CSP headers on the top-level document for static import. https://github.com/web-platform-tests/wpt/blob/256877037fa53c4c90e48e7171a69ea0cef0d3be/workers/modules/dedicated-worker-import-csp.html#L21 And the top-level module worker script will 'static import' its descendants. https://github.com/web-platform-tests/wpt/blob/master/workers/modules/resources/static-import-remote-origin-script-worker.sub.js But due to the spec issue whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-csp.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-csp.html?label=experimental&label=master&aligned So removing these two tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these two files from interop-2023-modules completely)
…om interop-2023-modules Fixing web-platform-tests/interop#406 In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". https://github.com/web-platform-tests/wpt/blob/master/workers/modules/dedicated-worker-import-data-url-cross-origin.html#L13 And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' https://github.com/web-platform-tests/wpt/blob/master/workers/modules/resources/static-import-script-block-cross-origin.js The script "export-block-cross-origin.js" is same-origin with the document, but not same-origin with the worker script which is loaded by data: URI. Due to the spec issue, whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url-cross-origin.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-data-url-cross-origin.html?label=experimental&label=master&aligned So removing these two tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these two files from interop-2023-modules completely)
…worker-import-data-url.window.html from interop-2023-modules Fixing web-platform-tests/interop#406 In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. https://github.com/web-platform-tests/wpt/blob/2cd449b9df6f92862abac0143ac6fe674fd5278e/workers/modules/resources/import-test-cases.js#L13 https://github.com/web-platform-tests/wpt/blob/2cd449b9df6f92862abac0143ac6fe674fd5278e/workers/modules/resources/static-import-redirect-worker.js#L3 The script "export-on-load-script.js" is same-origin with the document, but not same-origin with the worker script which is loaded by data: URI. Due to the spec issue, whatwg/html#9571 There isn't an agreement between browser vendors on which [settings object](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object) to use when fetching the descendants of module worker. https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url.any.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/dedicated-worker-import-data-url.any.worker.html?label=experimental&label=master&aligned https://wpt.fyi/results/workers/modules/shared-worker-import-data-url.window.html?label=experimental&label=master&aligned So removing these three tests from interop-2023-modules. (According to the README.md in wpt-metadata, when a 'label' is used, 'subtest' is omitted, so I remove these three files from interop-2023-modules completely)
…d be allowed.] failed as expected in [shared|dedicated]-worker-import-data-url-cross-origin.html.ini. r=dom-worker-reviewers,asuth In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' According to the current spec, the script "export-block-cross-origin.js" is in the same origin of the document, therefore it should be loaded. But with Gecko's implementation, the script "export-block-cross-origin.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187900
…cted in dedicated-worker-import-data-url.any.js and shared-worker-import-data-url.window.js. r=dom-worker-reviewers,asuth In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. According the current spec, the redirected 'export-on-load-script.js' is in the same-origin with the document, therefore it should be loaded. But with Gecko's implementation, the redirected script "export-on-load-script.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. (The first test case, which tests static import without redirect, the script 'export-on-load-script.js' could be loaded by Gecko because the script has the CORS header.) Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187901
I discussed this with Chromium team members (@nhiroki, @hiroshige-g, @yoshisatoyanagisawa and @domenic). We prefer the current spec, since it enables faster performance (and simplicity of the Chromium code). Chromium has an optimization (called PlzWorker) which initiates the module tree fetches outside of the renderer process. This plays nicer with the current spec, which is to use the document fetch client. With the proposed change, we would need to introduce a synchronization point, where we would have the worker context ready for CSP, and then process the submodule fetches. This is still implementable, but it will come with additional complexity and also performance hit. |
…d be allowed.] failed as expected in [shared|dedicated]-worker-import-data-url-cross-origin.html.ini. r=dom-worker-reviewers,asuth In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' According to the current spec, the script "export-block-cross-origin.js" is in the same origin of the document, therefore it should be loaded. But with Gecko's implementation, the script "export-block-cross-origin.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187900
…cted in dedicated-worker-import-data-url.any.js and shared-worker-import-data-url.window.js. r=dom-worker-reviewers,asuth In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. According the current spec, the redirected 'export-on-load-script.js' is in the same-origin with the document, therefore it should be loaded. But with Gecko's implementation, the redirected script "export-on-load-script.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. (The first test case, which tests static import without redirect, the script 'export-on-load-script.js' could be loaded by Gecko because the script has the CORS header.) Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187901
Some Chromium internal optimization isn't really a good reason for the spec to behave certain way. |
…d be allowed.] failed as expected in [shared|dedicated]-worker-import-data-url-cross-origin.html.ini. r=dom-worker-reviewers,asuth In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' According to the current spec, the script "export-block-cross-origin.js" is in the same origin of the document, therefore it should be loaded. But with Gecko's implementation, the script "export-block-cross-origin.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187900 UltraBlame original commit: 6e401be8c58633271e8a0813f2b9e98df1d5af8e
…cted in dedicated-worker-import-data-url.any.js and shared-worker-import-data-url.window.js. r=dom-worker-reviewers,asuth In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. According the current spec, the redirected 'export-on-load-script.js' is in the same-origin with the document, therefore it should be loaded. But with Gecko's implementation, the redirected script "export-on-load-script.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. (The first test case, which tests static import without redirect, the script 'export-on-load-script.js' could be loaded by Gecko because the script has the CORS header.) Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187901 UltraBlame original commit: 460e36a5e5aaca8ac8102a05e4357315e2c18583
…d be allowed.] failed as expected in [shared|dedicated]-worker-import-data-url-cross-origin.html.ini. r=dom-worker-reviewers,asuth In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' According to the current spec, the script "export-block-cross-origin.js" is in the same origin of the document, therefore it should be loaded. But with Gecko's implementation, the script "export-block-cross-origin.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187900 UltraBlame original commit: 6e401be8c58633271e8a0813f2b9e98df1d5af8e
…cted in dedicated-worker-import-data-url.any.js and shared-worker-import-data-url.window.js. r=dom-worker-reviewers,asuth In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. According the current spec, the redirected 'export-on-load-script.js' is in the same-origin with the document, therefore it should be loaded. But with Gecko's implementation, the redirected script "export-on-load-script.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. (The first test case, which tests static import without redirect, the script 'export-on-load-script.js' could be loaded by Gecko because the script has the CORS header.) Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187901 UltraBlame original commit: 460e36a5e5aaca8ac8102a05e4357315e2c18583
…d be allowed.] failed as expected in [shared|dedicated]-worker-import-data-url-cross-origin.html.ini. r=dom-worker-reviewers,asuth In the [static import script from data: URL should be allowed.] case, The worker will load the data URI, which imports "/resources/static-import-script-block-cross-origin.js". And static-import-script-block-cross-origin.js will static import 'export-block-cross-origin.js' According to the current spec, the script "export-block-cross-origin.js" is in the same origin of the document, therefore it should be loaded. But with Gecko's implementation, the script "export-block-cross-origin.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187900 UltraBlame original commit: 6e401be8c58633271e8a0813f2b9e98df1d5af8e
…cted in dedicated-worker-import-data-url.any.js and shared-worker-import-data-url.window.js. r=dom-worker-reviewers,asuth In this test, The worker will load a data URI, which import another test script statically, and the imported script will import 'export-on-load-script.js', which will be served with the CORS header 'Access-Control-Allow-Origin: *' in /workers/modules/resources/export-on-load-script.js.headers In the test case [Static import (redirect).], 'export-on-load-script.js' will be redirected, and the redirected script doesn't have the CORS header. According the current spec, the redirected 'export-on-load-script.js' is in the same-origin with the document, therefore it should be loaded. But with Gecko's implementation, the redirected script "export-on-load-script.js" is cross-origin with the main worker script (which is loaded by data URI), so the script is blocked. (The first test case, which tests static import without redirect, the script 'export-on-load-script.js' could be loaded by Gecko because the script has the CORS header.) Mark this test case as failed according to the spec issue whatwg/html#9571 Differential Revision: https://phabricator.services.mozilla.com/D187901 UltraBlame original commit: 460e36a5e5aaca8ac8102a05e4357315e2c18583
Hi everyone, thanks for discussing this. I recently returned from parental leave and after a bit of time reviewing this I think can clarify a bit. There are two issues here: one is the underlying principle, which is being discussed above. We might summarise that as “How should this work and why?”. The other is a functional issue, that is: at the moment browser have had to choose whether they support the CSP behaviour, or if they support service worker interception of modules. I think this is due to a collision in the spec.
To be more precise here: Firefox and Safari have the same behaviour, Chrome has different behaviour. Firefox and safari both pass the service workers interception test, which chrome does not. Conversely they both fail the CSP tests. When I was implementing this behavior, I found that issue was related to the environment. Using the outer environment passes the CSP tests (as spec'd), using the inner environment passes the service worker interception test. In my initial question in the original issue I raised the issue around service workers, I'll add more detail here: The problem in a bit more detail: The solution (as I understand it): I think. If I am right about this, we need to change the spec in order to support both the currently tested CSP behavior and the currently tested service worker behavior, and that change is to allow fetch to be aware of two environments for workers. This seems very complicated, and the other solution is to simply use the inner environment rather than the outer environment. This is what brings up the philosophical issue that we are all discussing here. This is my perspective of the current discussion. For our part, in February, after discussion internally (@smaug----, @asuth, @evilpie, myself and others), we decided that for the time being breaking service worker interception for all static imports represented a more serious issue than a more conservative CSP for loading static imports. This deviates from the spec'd behavior in HTML but fulfills the expectation of the service worker and also works in a way that users would expect (a similar argument to the bundling argument above being made in favor of CSP). I think we should go with the inner environment of the worker instead of the more complicated refactoring to fetching. It is cleaner, and there are good arguments in favor of the inner environment and breaking with the bundling expectation. As an outsider, when I was reviewing how CSP is handled for workers, I found it surprising that static imports would use the document’s CSP, for the same reason brought up by @youennf. In particular, I couldn’t justify the current behaviour through the bundling argument, because static imports can import arbitrary urls, this isn’t the case for bundled code which is by definition a single file. This is why I think the bundling argument ultimately falls apart and, given the additional complexity of the service worker interception, I think we should instead be using the inner environment. |
(This was the idea from @codehag and @smaug---- when they implemented module workers in Firefox,
but @codehag is on personal leave so I file the spec issue on her behalf.)
When fetch a module worker script graph, the specification uses the same environment settings object, a.k.a fetchClient to fetch the top-level module worker script and its descendants. To put it short, the specification requires to use the document's CSP to fetch the top-level module worker script and its descendants (static import).
The behavior is tested in WPT/dedicated-worker-import-csp.html
From @codehag and @smaug---- 's point of view, after the top-level module worker script is fetched, the worker will initialize its CSP list through the HTTP response, so it makes sense to use the worker's own CSP to fetch the descendants of the module worker. Also, this will align worker's static import with worker's dynamic import/importScripts(), all of them will use worker's CSP.
As mentioned above, this behavior is tested in interop-2023 of WPT, but Chrome/Firefox/Webkit have different behavior on this,
https://wpt.fyi/results/workers/modules/dedicated-worker-import-csp.html?label=master&label=experimental&product=chrome&product=firefox&product=safari&aligned&view=interop&q=label%3Ainterop-2023-modules
So I filed an issue here to open a discussion about this subject.
CC @domenic on the editor of this HTML spec
@hiroshige-g on the Chrome team
@Constellation on the Webkit team
@codehag @smaug---- @jonco3 and @zcorpan on the Firefox team
The text was updated successfully, but these errors were encountered: