ES Modules for Shared Workers
Author: elkurin@chromium.org (Eriko Kurimoto)
Last update: Feb 18, 2019
Status: Shipped in M82
Tracking bug: https://crbug.com/824646
Chrome Platform status: https://chromestatus.com/feature/5169440012369920
Chrome browser supports module scripts loading in shared workers. When the ‘module’ type is set on the constructor’s type attribute, worker scripts are loaded as ES modules and the import statement is available on worker contexts.
const worker = new SharedWorker(‘worker.js’, { name: ‘worker-name’, type: ‘module’}); |
The specification of this feature is here.
As of today we support 3 workers: Dedicated Workers, Shared Workers, and Service Workers. Each worker has a different script loading model and implementation. ES modules used to be supported only by Dedicated Workers (ES modules for Dedicated Workers). As a next step, we target Shared Workers that has a similar loading mechanism to Dedicated Workers.
Traditionally, we use Shared Workers as follows:
const worker = new SharedWorker(‘worker.js’, ‘worker-name’); |
This construction only works for classic script loading. The second argument of SharedWorker constructor used to take only DOMString as a worker’s name. Now, it takes DOMString OR WorkerOptions. (spec for WorkerOptions)
dictionary WorkerOptions { WorkerType type = "classic"; // credentials is only used if type is ‘module’ RequestCredentials credentials = "same-origin"; DOMString name = ""; }; enum WorkerType {‘classic’, ‘module’}; enum RequestCredentials {‘include’, ‘same-origin’, ‘omit’}; |
To use module Shared Workers, you need to set WorkerOptions’ type attribute to ‘module’ when you construct a shared worker. In WorkerOptions, credentials mode can also be specified from {‘include’, ‘same-origin’, ‘omit’}:
const worker = new SharedWorker(‘worker.js’, { name: ‘worker-name’, type: ‘module’, credentials: ‘same-origin’}); |
We continue to support DOMString name as the second argument of SharedWorker constructor and the default value of type attribute is ‘classic’, so the behavior of the traditional way of constructing SharedWorker (as below) doesn’t change.
const worker = new SharedWorker(‘worker.js’, ‘worker-name’); // new SharedWorker(‘worker.js’, { name: ‘worker-name’, type: ‘classic’ }); |
In Dedicated Worker, a worker thread is in the same renderer process with the main thread which calls a dedicated worker. Scripts loading for Dedicated Workers works as below:
As for Shared Workers, on the other hand, a worker thread could be in a different process with the main thread which calls a worker. The Shared Worker process can be accessed from more than one renderer process, so we need to find the Shared Worker process from the browser process. SharedWorkerServiceImpl finds the shared worker host[a][b][c][d][e][f]. It registers the renderer client if the corresponding thread exists, or creates a new thread if not. After finding the host, SharedWorkerHost sends the information to the main thread including the matching worker thread. Through this communication, script type and credentials mode parameters which are given by the constructor must be carried. These parameters are not used during this flow. After this step, the script loading mechanism is the same for Dedicated Workers. Therefore, the implementation for script fetching is using the same code path to Dedicated Workers.
Script loading for Shared Workers works as below:
The codes added in new code path is listed below:
Our implementation plans are follows:
Module scripts via <script> tag have already shipped in major browsers and there are plenty of web-platform-tests for it.
As for ES modules for Shared Workers, we added web-platform-test in workers/modules directory to test its behavior. SharedWorker cannot be nested nor called from Dedicated Workers, so there are no tests for constructing SharedWorker from workers.
Also we have web-platform-tests for ES modules for SharedWorker here as well: referrer-policy, mixed-content, upgrade-insecure-request.
Our main measure of success is a use counter for the constructor. This use counter is called when constructing a SharedWorker. If it is called without WorkerOption, it is distinguished as classic script loading since the default value of type attribute is ‘classic’.
You can see the chromestatus here: https://chromestatus.com/feature/5169440012369920
Not only module Shared Workers, Shared Workers itself is not yet supported in some browsers including Safari and Android Browser. From the interoperability perspective, this feature will not be supported by other browsers soon. However, module script loading for Dedicated Workers is already shipped and the worker spec has been discussed with other browser vendors and reached consensus.
[a]Is the matching mechanism changed (e.g. do type and credentials mode affect matching)? Or the additional parameters are just passed through browser process as-is without no additional impl/behavior changes?
[b]Currently, the matching mechanism is not changed. This is according to the spec. I'll make that clear in Doc.
But there is an ongoing spec issue whether we use the type value for matching or not (https://github.com/whatwg/html/issues/5235)
[c]_Marked as resolved_
[d]_Re-opened_
[e]_Marked as resolved_
[f]_Re-opened_