diff --git a/package.json b/package.json index 2ca0b84..3c873a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wasm-worker", - "version": "0.2.0", + "version": "0.3.0", "description": "Move a WebAssembly module into its own thread", "main": "lib/index.js", "jsnext:main": "es/index.js", diff --git a/src/index.js b/src/index.js index 3040d08..d375332 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ export default function wasmWorker(source, options = {}) { const { getImportObject, ...otherOptions } = options; const worker = new Worker( - `data:,ACTIONS=${JSON.stringify(ACTIONS)}getImportObject=${getImportObject};` + + `data:,ACTIONS=${JSON.stringify(ACTIONS)};getImportObject=${getImportObject};` + `moduleInstance=null;onmessage=${workerOnMessage}`, otherOptions, ); diff --git a/src/worker.js b/src/worker.js index 7505bd1..e7aa24a 100644 --- a/src/worker.js +++ b/src/worker.js @@ -18,40 +18,41 @@ export default function worker(e) { Promise.resolve() .then(() => { let res; + const importObject = getImportObject !== undefined + ? getImportObject() + : { + memoryBase: 0, + tableBase: 0, + memory: new WebAssembly.Memory({ initial: 256 }), + table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' }), + }; + if (typeof payload === 'string') { res = fetch(payload); - if (WebAssembly.compileStreaming !== undefined) { - return WebAssembly.compileStreaming(res); + if (WebAssembly.instantiateStreaming !== undefined) { + return WebAssembly.instantiateStreaming(res, importObject); } res = res.then(response => response.arrayBuffer()); } else { res = Promise.resolve(payload); } - return res.then(buffer => WebAssembly.compile(buffer)); + + return res + .then(buff => WebAssembly.compile(buff)) + .then(module => + WebAssembly.instantiate(module, importObject).then(instance => ({ module, instance })), + ); + }) + .then(({ module, instance }) => { + // eslint-disable-next-line + moduleInstance = instance; + onSuccess({ + exports: WebAssembly.Module + .exports(module) + .filter(exp => exp.kind === 'function') + .map(exp => exp.name), + }); }) - .then(module => - WebAssembly.instantiate( - module, - getImportObject !== undefined - ? getImportObject() - : { - memoryBase: 0, - tableBase: 0, - memory: new WebAssembly.Memory({ initial: 256 }), - table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' }), - }, - ) - .then((inst) => { - // eslint-disable-next-line - moduleInstance = inst; - onSuccess({ - exports: WebAssembly.Module - .exports(module) - .filter(exp => exp.kind === 'function') - .map(exp => exp.name), - }); - }), - ) .catch(onError); } else if (action === ACTIONS.CALL_FUNCTION_EXPORT) { const { func, params } = payload; diff --git a/test/worker.spec.js b/test/worker.spec.js index 459203d..4d09e82 100644 --- a/test/worker.spec.js +++ b/test/worker.spec.js @@ -5,7 +5,13 @@ import bytes from './bytes'; describe('worker', () => { beforeEach(() => { - fetchMock.mock(/bytes.wasm/, new Response(bytes)); + fetchMock.mock(/bytes.wasm/, new Response(bytes, { + status: 200, + statusText: 'OK', + headers: { + 'Content-type': 'application/wasm', + }, + })); }); afterEach(() => { @@ -15,7 +21,7 @@ describe('worker', () => { // we need this test because we cannot mock fetch in integrations // since we are using 2 diffent contexts. // so, use only the worker function - it('should instantiate a module from a url using compileStreaming', (done) => { + it('should instantiate a module from a url using instantiateStreaming', (done) => { // initialize scope, this is automatically injected by ../src/index.js /* eslint-disable */ @@ -33,26 +39,25 @@ describe('worker', () => { const id = 0; const action = ACTIONZ.COMPILE_MODULE; - const _compile = WebAssembly.compile; - WebAssembly.compile = jasmine.createSpy('compile').and.callFake((...params) => - _compile(...params) - ); - const _compileStreaming = WebAssembly.compileStreaming; - WebAssembly.compileStreaming = jasmine.createSpy('compileStreaming').and.callFake(req => - req - .then(res => res.arrayBuffer()) - .then(res => _compile(res)) + const _instantiate = WebAssembly.instantiate; + WebAssembly.instantiate = jasmine.createSpy('instantiate').and.callFake((...params) => + _instantiate(...params) ); + const _instantiateStreaming = WebAssembly.instantiateStreaming; + WebAssembly.instantiateStreaming = + jasmine.createSpy('instantiateStreaming').and.callFake((...params) => + _instantiateStreaming(...params) + ); // assert on post message // eslint-disable-next-line const self = { postMessage: (res) => { - expect(WebAssembly.compileStreaming).toHaveBeenCalled(); - expect(WebAssembly.compile).not.toHaveBeenCalled(); - WebAssembly.compileStreaming = _compileStreaming; - WebAssembly.compile = _compile; + expect(WebAssembly.instantiateStreaming).toHaveBeenCalled(); + expect(WebAssembly.instantiate).not.toHaveBeenCalled(); + WebAssembly.instantiateStreaming = _instantiateStreaming; + WebAssembly.instantiate = _instantiate; expect(res).toBeDefined(); expect(res.id).toEqual(id); expect(res.action).toEqual(action); @@ -79,7 +84,7 @@ describe('worker', () => { }); }); - it('should instantiate a module from a url using compile as fallback', (done) => { + it('should instantiate a module from a url using instantiate as fallback', (done) => { // initialize scope, this is automatically injected by ../src/index.js /* eslint-disable */ @@ -97,20 +102,20 @@ describe('worker', () => { const id = 0; const action = ACTIONZ.COMPILE_MODULE; - const _compile = WebAssembly.compile; - WebAssembly.compile = jasmine.createSpy('compile').and.callFake((...params) => - _compile(...params) + const _instantiate = WebAssembly.instantiate; + WebAssembly.instantiate = jasmine.createSpy('instantiate').and.callFake((...params) => + _instantiate(...params) ); - const _compileStreaming = WebAssembly.compileStreaming; - WebAssembly.compileStreaming = undefined; + const _instantiateStreaming = WebAssembly.instantiateStreaming; + WebAssembly.instantiateStreaming = undefined; // assert on post message // eslint-disable-next-line const self = { postMessage: (res) => { - expect(WebAssembly.compile).toHaveBeenCalled(); - WebAssembly.compileStreaming = _compileStreaming; - WebAssembly.compile = _compile; + expect(WebAssembly.instantiate).toHaveBeenCalled(); + WebAssembly.instantiateStreaming = _instantiateStreaming; + WebAssembly.instantiate = _instantiate; expect(res).toBeDefined(); expect(res.id).toEqual(id); expect(res.action).toEqual(action);