URL.revokeObjectURL() after new Worker(blobURL) causes intermittent "Module not found" errors because blob content is fetched asynchronously on the worker thread, not during construction.
Works in Chrome/Firefox. Fails in Deno.
MAIN THREAD (synchronous)
new Worker(blobUrl)
→ op_create_worker (parses URL only, spawns thread)
→ returns immediately
URL.revokeObjectURL(blobUrl) ← removes blob from store
WORKER THREAD (asynchronous)
run_web_worker()
→ preload_main_module()
→ blob_store.get_object_url() ← returns None! blob was revoked
| File | Role |
|---|---|
runtime/js/11_workers.js:94-138 |
JS Worker constructor, calls op_create_worker |
runtime/ops/worker_host.rs:159-293 |
op_create_worker — parses URL, spawns thread, does NOT fetch blob |
runtime/web_worker.rs:1120-1157 |
Worker startup — preload_main_module() fetches module here (too late) |
cli/file_fetcher.rs:113-121 |
BlobStoreAdapter — async blob fetch happens here |
ext/web/blob.rs:68-96 |
BlobStore — get_object_url() is a sync HashMap lookup, read_all() is async |
In runtime/js/11_workers.js, detect blob: URLs and read the content before calling op_create_worker, passing it as sourceCode (path already exists for classic workers).
Requires a new sync op op_worker_read_blob_url in Rust. The BlobStore.get_object_url() is already sync (HashMap get), and createObjectURL blobs are in-memory Vec<u8>, so a sync read is trivial.
In op_create_worker, if the specifier is a blob: URL, clone the Arc<Blob> from the BlobStore before returning. Pass it through to the worker thread's module loader so the data outlives revokeObjectURL.
~5-10 lines changed in runtime/ops/worker_host.rs, plus threading the cloned blob to the module loader.
- No new ops needed
- No changes to JS layer
- Doesn't duplicate blob data (just an Arc clone = ref count bump)
- Matches how browsers handle it (spec says blob content is captured at construction)
No. Node.js worker_threads doesn't support blob URLs at all — it requires absolute file paths or relative paths starting with ./ or ../. Both real Node.js and Deno's compat layer reject blob URLs at construction time. This is a Web Worker API-only issue.
let workerBlob = new Blob([`
self.onmessage = async function(e) {
console.log('Worker got message');
}
`], {type:"application/javascript"});
let workerURL = URL.createObjectURL(workerBlob);
let worker = new Worker(workerURL, {type:"module"});
URL.revokeObjectURL(workerURL); // ← causes race condition
worker.postMessage('');