developit / web-worker

Consistent Web Workers in browser and Node.

Home Page:https://npm.im/web-worker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Blob URL does not work on Node.js

sindresorhus opened this issue · comments

The readme says:

Worker() accepts a module URL, Blob URL or Data URL

But running the following on Node.js 18 results in a crash:

import Worker from 'web-worker';

const blob = new Blob(['foo'], {type: 'text/javascript'});
const url = URL.createObjectURL(blob);
const worker = new Worker(url, {type: 'module'});
node:internal/errors:466
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_INVALID_URL_SCHEME]: The URL must be of scheme file
    at new NodeError (node:internal/errors:377:5)
    at Object.fileURLToPath (node:internal/url:1484:11)
    at new Worker (/Users/sindresorhus/dev/oss/make-asynchronous/node_modules/web-worker/cjs/node.js:108:19)
    at file:///Users/sindresorhus/dev/oss/make-asynchronous/x.js:5:16
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:409:24)
    at async loadESM (node:internal/process/esm_loader:85:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12) {
  code: 'ERR_INVALID_URL_SCHEME'
}

Encountered the same issue in a private repo. Will link back once public.

I too would love to have blob support.

Blob URLs are not available in the worker thread, so they need to be resolved prior to the thread being started. So the way to implement this would be to:

  • Resolve the object URL in the main thread to a Blob
  • Pass the resolved Blob on to the threads.Worker object directly
  • In parseDataUrl(), if the resolved Blob is defined, return {type: urlBlob.type, data: await urlBlob.text()}
  • Make the chain from parseDataUrl() async functions

Seems to work for me this way in a quick and dirty test, but I'm not sure if there are other details that need to be looked at.

Transfering disc based blobs (from fs.openAsBlob(path)) are not transferable to other threads. therefore it might be better to just resolve the blob.text() in the main tread and pass the actual code to the worker rather than transferring a blob.

an alternative could be to read it as blob.arrayBuffer() cuz this can be transfered (zero-copied) over.