demo · v139
try/catch vs onerror
Before v139, a CSP-blocked worker constructor threw SecurityError at the call site — your try caught it. From v139 the constructor returns a worker that asynchronously fires an error event. Code paths that relied on the throw now silently appear to start, then fail later. Side-by-side demo, with the bridging snippet.
| case | pre-139 (Chromium) | v139+ (spec-compliant) |
|---|---|---|
| blocked Worker constructor | throws SecurityError | returns Worker, fires error |
| blocked SharedWorker constructor | throws SecurityError | returns SharedWorker, fires error |
| blocked script fetch (allowed init) | fires error event | fires error event |
| worker URL violates CSP | sometimes throws, sometimes onerror | always onerror |
simulated app
output log
recommended bridge
function makeWorker(url) {
let w;
try {
w = new Worker(url);
} catch (e) {
// pre-139 CSP block path. Treat the same as onerror.
return { ok: false, reason: 'sync-throw', error: e };
}
return new Promise((resolve) => {
w.onerror = (e) => resolve({ ok: false, reason: 'async-error', error: e.message });
// No error inside one frame == we have a live worker.
queueMicrotask(() => resolve({ ok: true, worker: w }));
});
}