Skip to content

Commit

Permalink
refact(wasm): use helper module instead of banner (#607)
Browse files Browse the repository at this point in the history
* refact(wasm): use helper module instead of banner

* test(wasm): test inject helper logic
  • Loading branch information
chengcyber authored Oct 21, 2020
1 parent 274ba1c commit 1bf5b2c
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 54 deletions.
55 changes: 55 additions & 0 deletions packages/wasm/src/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export const HELPERS_ID = '\0wasmHelpers.js';

export const getHelpersModule = () => `
function _loadWasmModule (sync, filepath, src, imports) {
function _instantiateOrCompile(source, imports, stream) {
var instantiateFunc = stream ? WebAssembly.instantiateStreaming : WebAssembly.instantiate;
var compileFunc = stream ? WebAssembly.compileStreaming : WebAssembly.compile;
if (imports) {
return instantiateFunc(source, imports)
} else {
return compileFunc(source)
}
}
var buf = null
var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null
if (filepath && isNode) {
var fs = eval('require("fs")')
var path = eval('require("path")')
return new Promise((resolve, reject) => {
fs.readFile(path.resolve(__dirname, filepath), (error, buffer) => {
if (error != null) {
reject(error)
}
resolve(_instantiateOrCompile(buffer, imports, false))
});
});
} else if (filepath) {
return _instantiateOrCompile(fetch(filepath), imports, true)
}
if (isNode) {
buf = Buffer.from(src, 'base64')
} else {
var raw = globalThis.atob(src)
var rawLength = raw.length
buf = new Uint8Array(new ArrayBuffer(rawLength))
for(var i = 0; i < rawLength; i++) {
buf[i] = raw.charCodeAt(i)
}
}
if(sync) {
var mod = new WebAssembly.Module(buf)
return imports ? new WebAssembly.Instance(mod, imports) : mod
} else {
return _instantiateOrCompile(buf, imports, false)
}
}
export { _loadWasmModule };
`;
70 changes: 16 additions & 54 deletions packages/wasm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Plugin } from 'rollup';

import { RollupWasmOptions } from '../types';

import { getHelpersModule, HELPERS_ID } from './helper';

export function wasm(options: RollupWasmOptions = {}): Plugin {
const { sync = [], maxFileSize = 14 * 1024, publicPath = '' } = options;

Expand All @@ -15,7 +17,19 @@ export function wasm(options: RollupWasmOptions = {}): Plugin {
return {
name: 'wasm',

resolveId(id) {
if (id === HELPERS_ID) {
return id;
}

return null;
},

load(id) {
if (id === HELPERS_ID) {
return getHelpersModule();
}

if (!/\.wasm$/.test(id)) {
return null;
}
Expand Down Expand Up @@ -46,59 +60,6 @@ export function wasm(options: RollupWasmOptions = {}): Plugin {
);
},

banner: `
function _loadWasmModule (sync, filepath, src, imports) {
function _instantiateOrCompile(source, imports, stream) {
var instantiateFunc = stream ? WebAssembly.instantiateStreaming : WebAssembly.instantiate;
var compileFunc = stream ? WebAssembly.compileStreaming : WebAssembly.compile;
if (imports) {
return instantiateFunc(source, imports)
} else {
return compileFunc(source)
}
}
var buf = null
var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null
if (filepath && isNode) {
var fs = eval('require("fs")')
var path = eval('require("path")')
return new Promise((resolve, reject) => {
fs.readFile(path.resolve(__dirname, filepath), (error, buffer) => {
if (error != null) {
reject(error)
}
resolve(_instantiateOrCompile(buffer, imports, false))
});
});
} else if (filepath) {
return _instantiateOrCompile(fetch(filepath), imports, true)
}
if (isNode) {
buf = Buffer.from(src, 'base64')
} else {
var raw = globalThis.atob(src)
var rawLength = raw.length
buf = new Uint8Array(new ArrayBuffer(rawLength))
for(var i = 0; i < rawLength; i++) {
buf[i] = raw.charCodeAt(i)
}
}
if(sync) {
var mod = new WebAssembly.Module(buf)
return imports ? new WebAssembly.Instance(mod, imports) : mod
} else {
return _instantiateOrCompile(buf, imports, false)
}
}
`.trim(),

transform(code, id) {
if (code && /\.wasm$/.test(id)) {
const isSync = syncFiles.indexOf(id) !== -1;
Expand All @@ -115,7 +76,8 @@ export function wasm(options: RollupWasmOptions = {}): Plugin {
src = null;
}

return `export default function(imports){return _loadWasmModule(${+isSync}, ${publicFilepath}, ${src}, imports)}`;
return `import { _loadWasmModule } from ${JSON.stringify(HELPERS_ID)};
export default function(imports){return _loadWasmModule(${+isSync}, ${publicFilepath}, ${src}, imports)}`;
}
return null;
},
Expand Down
1 change: 1 addition & 0 deletions packages/wasm/test/fixtures/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'foo';
8 changes: 8 additions & 0 deletions packages/wasm/test/fixtures/injectHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import sample from './sample.wasm';
import foo from './foo';

const instance = sample({ env: {} });

t.is(instance.exports.main(), 3, 'wasm loaded');

t.is(foo, 'foo');
28 changes: 28 additions & 0 deletions packages/wasm/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,31 @@ try {
} catch (err) {
// worker threads aren't fully supported in Node versions before 11.7.0
}

test('injectHelper', async (t) => {
t.plan(4);

const injectImport = `import { _loadWasmModule } from ${JSON.stringify('\0wasmHelpers.js')};`;

const bundle = await rollup({
input: 'fixtures/injectHelper.js',
plugins: [
wasm({
sync: ['fixtures/sample.wasm']
}),
{
name: 'test-detect',
transform: (code, id) => {
if (id.endsWith('sample.wasm')) {
t.true(code.includes(injectImport));
}
if (id.endsWith('foo.js')) {
t.true(!code.includes(injectImport));
}
return code;
}
}
]
});
await testBundle(t, bundle);
});

0 comments on commit 1bf5b2c

Please sign in to comment.