After calling importScripts, the worker object (on the main thread) is unexpectedly garbage-collected and the worker thread is terminated. This is because DedicatedWorkerGlobalScope::importScripts calls reportPendingActivity, which notifies the main thread that the worker is idle, regardless of whether there is active code after the importScripts call from JavaScript. Steps to reproduce: 1. Start WebKit Nightly and open the Inspector (e.g. on example.com) 2. Run the following snippet: ;(function() { // setTimeout because the bug only occurs when importScripts is called after the // worker script has completely run (in JSC). var code = 'setTimeout(' + function() { importScripts("data:,"); // V8 immediately terminates a thread when the worker object is GC'd, // while JSC continues running the worker script until the tab is closed, // so schedule the busy loop after GC on the main thread has run. setTimeout(function() { // Busy loop so we can observe whether the worker script is active. while (true) {} }, 1000); } + ');'; // Create worker without saving a reference. new Worker(URL.createObjectURL(new Blob([code]))); // Trigger GC setTimeout(function() { for (var i = 0; i < 25; ++i) new Array(Math.pow(2, i)); }, 500); })(); 3. Look at the Activity Monitor to watch the CPU usage of Safari. 4. Open a new tab and close the tab from step 3 (to force termination of the worker if not already done). 5. Quit Safari and repeat the above, but with importScripts commented out or removed. Expected result: - Step 3 and 5 should give the same results, i.e. 100% usage of a CPU core (caused by the busy loop). Actual result: - After step 3, the CPU usage of Safari is negligible. This shows that the scheduled busy loop never executes, i.e. the worker thread is terminated. - After step 5, the CPU usage of Safari is 100% (as expected). This difference in behavior shows that importScripts affects the garbage collection behavior. More info: - Similar bug in Blink, with work-around for web devs, and patch for Blink: https://crbug.com/572225 - The above example seems contrived, but it was a reduction from a bug that affected real-world code that uses RequireJS in a worker. The worker object was GC'd even though there were message listeners on the Worker instance.
Thank you for the great bug report!
Things might have changed since this was first reported, but I'd like to point out that if the snippet still does reproduce in current builds it's because `"data:,"` does not contain a proper JS mimeType. As far as I can see, this is actually in accordance with the specs, and it's a bit weird that other browsers do not throw here (e.g they'd throw with a non "data:" URL resulting in the same mimeType). But anyway, what happens currently has nothing to do with GC, and it's normal the worker is terminated before entering the busy loop (an error is even displayed).