Socket
Socket
Sign inDemoInstall

@surma/rollup-plugin-off-main-thread

Package Overview
Dependencies
4
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.4.2 to 2.0.0

tests/fixtures/import-meta-worker/a.js

149

index.js

@@ -18,2 +18,3 @@ /**

const MagicString = require("magic-string");
const tippex = require("tippex");

@@ -28,5 +29,2 @@ const defaultOpts = {

useEval: false,
// A RegExp to find `new Workers()` calls. The second capture group _must_
// capture the provided file name without the quotes.
workerRegexp: /new Worker\((["'])(.+?)\1(,[^)]+)?\)/g,
// Function name to use instead of AMD’s `define`.

@@ -41,3 +39,3 @@ amdFunctionName: "define",

// Silence the warning about ESM being badly supported in workers.
silenceESMWorkerWarning: false,
silenceESMWorkerWarning: false
};

@@ -62,6 +60,8 @@

outputOptions({ format }) {
if ((format === "esm" || format === "es") && !opts.silenceESMWorkerWarning) {
this.warn(
'Very few browsers support ES modules in Workers. If you want to your code to run in all browsers, set `output.format = "amd";`'
);
if (format === "esm" || format === "es") {
if (!opts.silenceESMWorkerWarning) {
this.warn(
'Very few browsers support ES modules in Workers. If you want to your code to run in all browsers, set `output.format = "amd";`'
);
}
// In ESM, we never prepend a loader.

@@ -81,3 +81,4 @@ isEsmOutput = true;

const resolved = await this.resolve(path, importer);
if (!resolved) throw Error(`Cannot find module '${path}' from '${importer}'`);
if (!resolved)
throw Error(`Cannot find module '${path}' from '${importer}'`);
const newId = resolved.id;

@@ -97,58 +98,94 @@

async transform(code, id) {
// Copy the regexp as they are stateful and this hook is async.
const workerRegexp = new RegExp(
opts.workerRegexp.source,
opts.workerRegexp.flags
);
if (!workerRegexp.test(code)) {
return;
}
// A regexp to find static `new Worker` invocations.
// File part matches one of:
// - '...'
// - "..."
// - `import.meta.url`
// - `new URL('...', import.meta.url)
// - `new URL("...", import.meta.url)
// Also matches optional options param.
const workerRegexp = /new\s+Worker\(\s*('.*?'|".*?"|import\.meta\.url|new\s+URL\(('.*?'|".*?"),\s*import\.meta\.url\))\s*(?:,(.+?))?\)/gs;
const ms = new MagicString(code);
// Reset the regexp
workerRegexp.lastIndex = 0;
while (true) {
const match = workerRegexp.exec(code);
if (!match) {
break;
}
const workerFile = match[2];
let optionsObject = {};
// Parse the optional options object
if (match[3] && match[3].length > 0) {
// FIXME: ooooof!
optionsObject = new Function(`return ${match[3].slice(1)};`)();
}
if (!isEsmOutput) {
delete optionsObject.type;
}
const replacementPromises = [];
if (!new RegExp("^.*/").test(workerFile)) {
this.warn(
`Paths passed to the Worker constructor must be relative or absolute, i.e. start with /, ./ or ../ (just like dynamic import!). Ignoring "${workerFile}".`
// Tippex is performing regex matching under the hood, but automatically ignores comments
// and string contents so it's more reliable on JS syntax.
tippex.match(
code,
workerRegexp,
(
fullMatch,
directWorkerFile,
workerFile = directWorkerFile,
optionsStr = ""
) => {
let workerIdPromise;
if (directWorkerFile === "import.meta.url") {
// Turn the current file into a chunk
workerIdPromise = Promise.resolve(id);
} else {
// Otherwise it's a string literal either directly or in the URL
// constructor, which we treat as the same thing.
// Cut off surrounding quotes.
workerFile = workerFile.slice(1, -1);
if (!/^\.{0,2}\//.test(workerFile)) {
this.warn(
`Paths passed to the Worker constructor must be relative or absolute, i.e. start with /, ./ or ../ (just like dynamic import!). Ignoring "${workerFile}".`
);
return;
}
workerIdPromise = this.resolve(workerFile, id).then(res => res.id);
}
// We need to get this before the `await`, otherwise `lastIndex`
// will be already overridden.
const matchIndex = workerRegexp.lastIndex - fullMatch.length;
const workerParametersStartIndex = matchIndex + "new Worker(".length;
const workerParametersEndIndex =
matchIndex + fullMatch.length - ")".length;
// Parse the optional options object if provided.
optionsStr = optionsStr.trim();
if (optionsStr) {
let optionsObject = new Function(`return ${optionsStr};`)();
if (!isEsmOutput) {
delete optionsObject.type;
}
optionsStr = JSON.stringify(optionsObject);
optionsStr = optionsStr === "{}" ? "" : `, ${optionsStr}`;
}
// tippex.match accepts only sync callback, but we want to perform &
// wait for async job here, so we track those promises separately.
replacementPromises.push(
(async () => {
const resolvedWorkerFile = await workerIdPromise;
workerFiles.push(resolvedWorkerFile);
const chunkRefId = this.emitFile({
id: resolvedWorkerFile,
type: "chunk"
});
ms.overwrite(
workerParametersStartIndex,
workerParametersEndIndex,
`import.meta.ROLLUP_FILE_URL_${chunkRefId}${optionsStr}`
);
})()
);
continue;
}
);
const resolvedWorkerFile = (await this.resolve(workerFile, id)).id;
workerFiles.push(resolvedWorkerFile);
const chunkRefId = this.emitFile({
id: resolvedWorkerFile,
type: "chunk"
});
// No matches found.
if (!replacementPromises.length) {
return;
}
const workerParametersStartIndex = match.index + "new Worker(".length;
const workerParametersEndIndex =
match.index + match[0].length - ")".length;
// Wait for all the scheduled replacements to finish.
await Promise.all(replacementPromises);
ms.overwrite(
workerParametersStartIndex,
workerParametersEndIndex,
`import.meta.ROLLUP_FILE_URL_${chunkRefId}, ${JSON.stringify(
optionsObject
)}`
);
}
return {

@@ -155,0 +192,0 @@ code: ms.toString(),

{
"name": "@surma/rollup-plugin-off-main-thread",
"version": "1.4.2",
"version": "2.0.0",
"description": "Use Rollup with workers and ES6 modules today.",

@@ -31,4 +31,5 @@ "main": "index.js",

"ejs": "^2.6.1",
"magic-string": "^0.25.0"
"magic-string": "^0.25.0",
"tippex": "^3.0.0"
}
}

@@ -48,2 +48,10 @@ # rollup-plugin-off-main-thread

If required, the plugin also supports explicitly module-relative paths:
```js
const worker = new Worker(new URL("./worker.js", import.meta.url), {
type: "module"
});
```
### Importing workers as URLs

@@ -50,0 +58,0 @@

@@ -44,4 +44,6 @@ /**

"./tests/fixtures/import-worker-url/entry.js",
"./tests/fixtures/import-meta-worker/entry.js",
"./tests/fixtures/import-worker-url-custom-scheme/entry.js",
"./tests/fixtures/assets-in-worker/entry.js"
"./tests/fixtures/assets-in-worker/entry.js",
"./tests/fixtures/url-import-meta-worker/entry.js"
].map(async input => {

@@ -48,0 +50,0 @@ const pathName = path.dirname(input);

@@ -14,2 +14,8 @@ /**

/*
* This is commented out and should be ignored by the plugin.
* If it doesn't, Rollup and test will fail.
* new Worker("non-existing-worker", { type: "module" });
*/
// The type module should get removed for AMD format!

@@ -16,0 +22,0 @@ const w = new Worker("./worker.js", { type: "module" });

@@ -26,3 +26,3 @@ /**

window.addEventListener("message", function l(ev) {
if (/^https?:\/\/[^/]+\/a-[0-9a-f]+\.js$/.test(ev.data)) {
if (/^https?:\/\/.+\.js$/.test(ev.data)) {
window.removeEventListener("message", l);

@@ -29,0 +29,0 @@ done();

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc