You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SW has different script execution model from other workers. SW's script fetching and running execute in separate places with a different lifecycle.
Fetch a module worker script graph requires a settings object in the fetching phase to pare the scripts. (Fetch a classic worker script also requires this argument as well but seems not using for parsing in the fetching phase.)
We need to fix it such that module scripts parsed during the fetching phase can be used in subsequent Run Service Worker script executions.
Soft Update is using null for a job's client that's later passed to Fetch a classic worker script and Fetch a module worker script graph. This should be addressed, too.
I've been thinking about the environment settings object for service workers. Currently we create a settings object for a service worker whenever Run Service Worker needs a cold start. So, it's basically 1:1:1 to the realm and the global object as for other environments. However, having thought about it more, I think it should rather be bound to the service worker's lifetime instead of the realm and global object's lifetime. It seems most of the settings object's fields can be (or need to be) maintained across multiple global objects' creations and terminations. Moreover, fetching a * worker script requires a settings object, which isn't what service worker's Update algorithm strictly follows at the moment. (Update step 7 now passes a to-be-created environment settings object to fetch a * worker script.)
That considered, I propose we create an environment settings object for a service worker in Update algorithm before invoking fetch a * worker script. This settings object is associated with the service worker's script during fetch a * worker script execution. And Run Service Worker algorithm later uses this service worker's script's settings object to run the script with additional set up steps that associate the settings object with the created realm and the global object.
One tricky part is fetch a module worker script graph > .. > create a module script > ParseModule() requires a realm while service worker's Update doesn't create a realm. In my understanding, the only reason that the realm is passed is to set the created script's module record's [[Realm]] internal slot, right? If so, can I set/pass the environment settings object's Realm to undefined at this stage? And later override the value to the actual realm created in Run Service Worker?
To sum, I propose we redefine the lifetime of service worker's environment settings object to satisfy the service worker's processing model. It would look something like:
Update
Create an environment settings object with its realm initialized to undefined.
Realm execution context returns null.
Module map is initial empty map.
Create an event loop [1]
Fetch a * worker script with the created settings object
Set up the settings object with service worker's script's settings object and the created realm
Set script's module record's [[Realm]] to the given realm
Set realm's [[HostDefined]] field to the given settings object
[1] If it makes sense to create the event loop in Update and use it until the registration is cleared, we don't even have to back up the tasks to registration's task queue in Terminate Service Worker. Does it make sense?
Hmm. I think it would be pretty bad to break the 1:1:1 correspondence. A lot of the platform assumes that.
Also, note what "fetch a worker script" uses the settings object for: it uses it to determine the referrer and such. So I don't think the service worker should be fetching itself, should it? It should be the settings object of the page itself that is doing navigator.serviceWorker.register(). In other words, I think you need a separate settings object for the fetching, and for the running of scripts. The fetching should be "outside", e.g. the initiating document. Whereas the script running should be inside the service worker.
This might be different for future updates. But at least for the initial navigator.serviceWorker.register() it seems necessary.
One tricky part is fetch a module worker script graph > .. > create a module script > ParseModule() requires a realm while service worker's Update doesn't create a realm. In my understanding, the only reason that the realm is passed is to set the created script's module record's [[Realm]] internal slot, right? If so, can I set/pass the environment settings object's Realm to undefined at this stage? And later override the value to the actual realm created in Run Service Worker?
Something like that might work, although we'd need to modify the spec to allow not passing in a realm (we can't just treat undefined as if it's a realm). But I wonder if after considering the above we can find some way to avoid this. I'd be very surprised if any implementation actually parses service worker scripts before creating an instance of the JS engine for the service worker scripts to run in. And the spec should ideally not do something so different from implementations.
Activity
Merge pull request #1012 from domenic/fix-classic-worker-script
jungkees commentedon Dec 13, 2016
Soft Update is using null for a job's client that's later passed to Fetch a classic worker script and Fetch a module worker script graph. This should be addressed, too.
jungkees commentedon Mar 14, 2017
@domenic, @annevk,
I've been thinking about the environment settings object for service workers. Currently we create a settings object for a service worker whenever Run Service Worker needs a cold start. So, it's basically 1:1:1 to the realm and the global object as for other environments. However, having thought about it more, I think it should rather be bound to the service worker's lifetime instead of the realm and global object's lifetime. It seems most of the settings object's fields can be (or need to be) maintained across multiple global objects' creations and terminations. Moreover, fetching a * worker script requires a settings object, which isn't what service worker's Update algorithm strictly follows at the moment. (Update step 7 now passes a to-be-created environment settings object to fetch a * worker script.)
That considered, I propose we create an environment settings object for a service worker in Update algorithm before invoking fetch a * worker script. This settings object is associated with the service worker's script during fetch a * worker script execution. And Run Service Worker algorithm later uses this service worker's script's settings object to run the script with additional set up steps that associate the settings object with the created realm and the global object.
One tricky part is fetch a module worker script graph > .. > create a module script > ParseModule() requires a realm while service worker's Update doesn't create a realm. In my understanding, the only reason that the realm is passed is to set the created script's module record's [[Realm]] internal slot, right? If so, can I set/pass the environment settings object's Realm to undefined at this stage? And later override the value to the actual realm created in Run Service Worker?
To sum, I propose we redefine the lifetime of service worker's environment settings object to satisfy the service worker's processing model. It would look something like:
Update
Run Service Worker
[1] If it makes sense to create the event loop in Update and use it until the registration is cleared, we don't even have to back up the tasks to registration's task queue in Terminate Service Worker. Does it make sense?
WDYT?
domenic commentedon Mar 16, 2017
Hmm. I think it would be pretty bad to break the 1:1:1 correspondence. A lot of the platform assumes that.
Also, note what "fetch a worker script" uses the settings object for: it uses it to determine the referrer and such. So I don't think the service worker should be fetching itself, should it? It should be the settings object of the page itself that is doing
navigator.serviceWorker.register()
. In other words, I think you need a separate settings object for the fetching, and for the running of scripts. The fetching should be "outside", e.g. the initiating document. Whereas the script running should be inside the service worker.This might be different for future updates. But at least for the initial
navigator.serviceWorker.register()
it seems necessary.Something like that might work, although we'd need to modify the spec to allow not passing in a realm (we can't just treat undefined as if it's a realm). But I wonder if after considering the above we can find some way to avoid this. I'd be very surprised if any implementation actually parses service worker scripts before creating an instance of the JS engine for the service worker scripts to run in. And the spec should ideally not do something so different from implementations.
Configure script's settings and realm for service workers
Leave notes on service worker script fetching for V1
Leave notes on service worker script fetching for V1 (#1450)
jungkees commentedon Jul 19, 2019
Changing the milestone to V2 after adding notes and issues: 2e2d872.
Leave notes on service worker script fetching for V1 (w3c#1450)