user13082750
user13082750

Reputation: 73

Does the entire code in the top level of the manifest v3 service worker run repeatedly every time it wakes up?

Tested: In order to avoid repeated execution of some code (like chrome.contextMenus.create repeated execution makes

Unchecked runtime.lastError: Cannot create item with duplicate id

), it needs to be moved into chrome.runtime.onInstalled.addListener. But some code (like chrome.action.onClicked.addListener) moved into chrome.runtime.onInstalled.addListener won't run on next wakeup.

If chrome.action.onClicked.addListener is placed at the top level of the service worker,

will the Listener be added again every time the service worker wakes up,

Will there be multiple duplicate listeners?

will the functions in the new added Listener and in Listener added previous be executed both?

https://developer.chrome.com/docs/extensions/mv3/service_workers/ saying:

A background service worker is loaded when it is needed, and unloaded when it goes idle. Some examples include:

says 'unloaded when it goes idle', will the Listener added previous be unloaded too? ___if so,how awaking service worker again?

or only unload the functions in Listener added previous, and reserve the Listener empty shell just for awaking service worker ?

Upvotes: 3

Views: 825

Answers (1)

woxxom
woxxom

Reputation: 73506

Yes, it reruns anew.

No, there'll be no duplicate listeners.
No multiple threads, no sleeping/suspending/resuming.

The confusion is caused by a rather inept description in the old version of the documentation, now it's rewritten. What actually happens is that after a certain timeout the service worker is simply terminated. It doesn't "unload" or "resume". It "terminates completely" and "starts fresh".

When it terminates, the JavaScript environment disappears (JS listeners, variables, everything).

When it's started by the browser in reaction to an event to which you subscribed via addListener in the previous run of the SW, your SW script runs in its entirety. Each addListener for a chrome event registers this listener internally. Then the event that woke the worker will be dispatched to the listeners. This is why it is important to register the listeners synchronously in the first task of the event loop when the script starts (the old documentation used a rather arcane term "top-level" from the makers of V8 and oversimplified it to the need to declare the listeners in the global scope of the script, which is not mandatory because you can certainly do it inside a function call as long as it's synchronous).

The contextMenus API is different: the data is saved inside Chrome's internal preferences so there's no need to recreate it on each run, doing it inside chrome.runtime.onInstalled is sufficient. Firefox doesn't save them yet, but I guess they will do it once they implement MV3.

P.S.

The lifetime duration is 30 seconds after the last incoming external event. Using a runtime port adds another 5 minutes to the timeout. Using native host messaging keeps the service worker alive indefinitely, but it is also possible to emulate a persistent service worker to a degree even without native messaging: more info.

Another view in the extension, such as a popup, calls runtime.getBackgroundPage.

This is not true anymore in MV3.

Upvotes: 7

Related Questions