I keep getting back error code: 18, SecurityError from Edge and Safari while trying to use a Web Worker. The workers are fine in Firefox / Chrome however. I'm using an inlined worker that I pass zero-dependency data processing functions to.
My CSP has looked:
add_header Content-Security-Policy "default-src 'self'; worker-src 'self' 'inline' *.example.com";
I can add in other nice to haves like local stylesheets and googleapis.com on my own, but I'm curious how to get the Worker to not throw a Security error
Snippet from worker method
// Create an "inline" worker (1:1 at definition time)
const worker = new Worker(
// Use a data URI for the worker's src. It inlines the target function and an RPC handler:
'data:,$$='+asyncFunction+';onmessage='+(e => {
/* global $$ */
// Invoking within then() captures exceptions in the supplied async function as rejections
Promise.resolve(e.data[1]).then(
v => $$.apply($$, v)
).then(
// success handler - callback(id, SUCCESS(0), result)
// if `d` is transferable transfer zero-copy
d => {
postMessage([e.data[0], 0, d], [d].filter(x => (
(x instanceof ArrayBuffer) ||
(x instanceof MessagePort) ||
(x instanceof ImageBitmap)
)));
},
// error handler - callback(id, ERROR(1), error)
er => { postMessage([e.data[0], 1, '' + er]); }
);
})
);
Edge throws this error for the worker:
[object DOMException]: {code: 18, message: "SecurityError", name:
"SecurityError"}
code: 18
message: "SecurityError"
name: "SecurityError"
I'm not sure why the data url is causing a security error but you can use URL.createObjectURL
to load a worker script, which seems to work properly in Edge (I didn't test it in safari).
Here's what that would look like:
// Create the worker script as a string
const script = '$$='+asyncFunction+';onmessage='+(e => {
/* global $$ */
// Invoking within then() captures exceptions in the supplied async function as rejections
Promise.resolve(e.data[1]).then(
v => $$.apply($$, v)
).then(
// success handler - callback(id, SUCCESS(0), result)
// if `d` is transferable transfer zero-copy
d => {
postMessage([e.data[0], 0, d], [d].filter(x => (
(x instanceof ArrayBuffer) ||
(x instanceof MessagePort) ||
(x instanceof ImageBitmap)
)));
},
// error handler - callback(id, ERROR(1), error)
er => { postMessage([e.data[0], 1, '' + er]); }
);
});
// Create a local url to load the worker
const blob = new Blob([script]);
const workerUrl = URL.createObjectURL(blob);
const worker = new Worker(workerUrl);
Let me know if you need any clarification!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With