From 8014e4fea1e1bdcf5b0afa9f0807c8d112e488cf Mon Sep 17 00:00:00 2001 From: Vedant Roy Date: Fri, 24 Apr 2020 20:34:05 -0400 Subject: [PATCH 1/3] Make wasm plugin work with service workers The code generated by @rollup/plugin-wasm breaks when executed in a service worker because window is undefined. --- packages/wasm/src/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/wasm/src/index.js b/packages/wasm/src/index.js index 2332a68a8..48b494000 100755 --- a/packages/wasm/src/index.js +++ b/packages/wasm/src/index.js @@ -30,7 +30,9 @@ export default function wasm(options = {}) { if (isNode) { buf = Buffer.from(src, 'base64') } else { - var raw = window.atob(src) + var raw; + if (typeof window === 'object') raw = window.atob(src) + else raw = self.atob(src) var rawLength = raw.length buf = new Uint8Array(new ArrayBuffer(rawLength)) for(var i = 0; i < rawLength; i++) { From f51a1472bffef0b9cce49357ae860acfd5c44ccc Mon Sep 17 00:00:00 2001 From: Vedant Roy Date: Sat, 25 Apr 2020 01:31:04 -0400 Subject: [PATCH 2/3] Add test for worker scenario and simplify the fix Instead of checking whether window is defined, we can just use globalThis. --- packages/wasm/src/index.js | 4 +--- packages/wasm/test/fixtures/worker.js | 11 ++++++++++ packages/wasm/test/test.js | 31 +++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 packages/wasm/test/fixtures/worker.js diff --git a/packages/wasm/src/index.js b/packages/wasm/src/index.js index 48b494000..b64485fba 100755 --- a/packages/wasm/src/index.js +++ b/packages/wasm/src/index.js @@ -30,9 +30,7 @@ export default function wasm(options = {}) { if (isNode) { buf = Buffer.from(src, 'base64') } else { - var raw; - if (typeof window === 'object') raw = window.atob(src) - else raw = self.atob(src) + var raw = globalThis.atob(src) var rawLength = raw.length buf = new Uint8Array(new ArrayBuffer(rawLength)) for(var i = 0; i < rawLength; i++) { diff --git a/packages/wasm/test/fixtures/worker.js b/packages/wasm/test/fixtures/worker.js new file mode 100644 index 000000000..948d53a7c --- /dev/null +++ b/packages/wasm/test/fixtures/worker.js @@ -0,0 +1,11 @@ +import sample from './sample.wasm'; +// atob doesn't exist in node, so we fake it +// in the browser, globalThis.atob will exist +// eslint-disable-next-line no-undef +globalThis.atob = (str) => Buffer.from(str, 'base64').toString('binary'); +// trick the wasm loader into thinking we are in the browser +const realProcess = process; +// eslint-disable-next-line no-global-assign, no-undefined +process = undefined; +sample({}); +realProcess.exit(0); diff --git a/packages/wasm/test/test.js b/packages/wasm/test/test.js index 26487d800..fb6ef832c 100755 --- a/packages/wasm/test/test.js +++ b/packages/wasm/test/test.js @@ -4,13 +4,19 @@ import test from 'ava'; // eslint-disable-next-line no-unused-vars, import/no-unresolved, import/extensions import wasm from '../dist/index'; +const { Worker } = require('worker_threads'); + const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor; -const testBundle = async (t, bundle) => { +const generateCode = async (bundle) => { const { output } = await bundle.generate({ format: 'cjs' }); const [{ code }] = output; - const func = new AsyncFunction('t', `let result;\n\n${code}\n\nreturn result;`); + return code; +}; +const testBundle = async (t, bundle) => { + const code = await generateCode(bundle); + const func = new AsyncFunction('t', `let result;\n\n${code}\n\nreturn result;`); return func(t); }; @@ -61,3 +67,24 @@ test('imports', async (t) => { }); await testBundle(t, bundle); }); + +test('worker', async (t) => { + t.plan(2); + + const bundle = await rollup({ + input: 'test/fixtures/worker.js', + plugins: [wasm()] + }); + const code = await generateCode(bundle); + const executeWorker = () => { + const worker = new Worker(code, { eval: true }); + return new Promise((resolve, reject) => { + worker.on('error', (err) => reject(err)); + worker.on('exit', (exitCode) => resolve(exitCode)); + }); + }; + await t.notThrowsAsync(async () => { + const result = await executeWorker(); + t.true(result === 0); + }); +}); From f10b9c46f86a9ba6164863f1232971ec304132ef Mon Sep 17 00:00:00 2001 From: Vedant Roy Date: Sat, 25 Apr 2020 22:32:59 -0400 Subject: [PATCH 3/3] Only run worker test if worker_threads supported --- packages/wasm/test/test.js | 41 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/packages/wasm/test/test.js b/packages/wasm/test/test.js index fb6ef832c..a63e553ac 100755 --- a/packages/wasm/test/test.js +++ b/packages/wasm/test/test.js @@ -4,8 +4,6 @@ import test from 'ava'; // eslint-disable-next-line no-unused-vars, import/no-unresolved, import/extensions import wasm from '../dist/index'; -const { Worker } = require('worker_threads'); - const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor; const generateCode = async (bundle) => { @@ -68,23 +66,28 @@ test('imports', async (t) => { await testBundle(t, bundle); }); -test('worker', async (t) => { - t.plan(2); +try { + const { Worker } = require('worker_threads'); + test('worker', async (t) => { + t.plan(2); - const bundle = await rollup({ - input: 'test/fixtures/worker.js', - plugins: [wasm()] - }); - const code = await generateCode(bundle); - const executeWorker = () => { - const worker = new Worker(code, { eval: true }); - return new Promise((resolve, reject) => { - worker.on('error', (err) => reject(err)); - worker.on('exit', (exitCode) => resolve(exitCode)); + const bundle = await rollup({ + input: 'test/fixtures/worker.js', + plugins: [wasm()] + }); + const code = await generateCode(bundle); + const executeWorker = () => { + const worker = new Worker(code, { eval: true }); + return new Promise((resolve, reject) => { + worker.on('error', (err) => reject(err)); + worker.on('exit', (exitCode) => resolve(exitCode)); + }); + }; + await t.notThrowsAsync(async () => { + const result = await executeWorker(); + t.true(result === 0); }); - }; - await t.notThrowsAsync(async () => { - const result = await executeWorker(); - t.true(result === 0); }); -}); +} catch (err) { + // worker threads aren't fully supported in Node versions before 11.7.0 +}