Skip to content

Commit 1bf5b2c

Browse files
authored
refact(wasm): use helper module instead of banner (#607)
* refact(wasm): use helper module instead of banner * test(wasm): test inject helper logic
1 parent 274ba1c commit 1bf5b2c

File tree

5 files changed

+108
-54
lines changed

5 files changed

+108
-54
lines changed

packages/wasm/src/helper.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export const HELPERS_ID = '\0wasmHelpers.js';
2+
3+
export const getHelpersModule = () => `
4+
function _loadWasmModule (sync, filepath, src, imports) {
5+
function _instantiateOrCompile(source, imports, stream) {
6+
var instantiateFunc = stream ? WebAssembly.instantiateStreaming : WebAssembly.instantiate;
7+
var compileFunc = stream ? WebAssembly.compileStreaming : WebAssembly.compile;
8+
9+
if (imports) {
10+
return instantiateFunc(source, imports)
11+
} else {
12+
return compileFunc(source)
13+
}
14+
}
15+
16+
var buf = null
17+
var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null
18+
19+
if (filepath && isNode) {
20+
var fs = eval('require("fs")')
21+
var path = eval('require("path")')
22+
23+
return new Promise((resolve, reject) => {
24+
fs.readFile(path.resolve(__dirname, filepath), (error, buffer) => {
25+
if (error != null) {
26+
reject(error)
27+
}
28+
29+
resolve(_instantiateOrCompile(buffer, imports, false))
30+
});
31+
});
32+
} else if (filepath) {
33+
return _instantiateOrCompile(fetch(filepath), imports, true)
34+
}
35+
36+
if (isNode) {
37+
buf = Buffer.from(src, 'base64')
38+
} else {
39+
var raw = globalThis.atob(src)
40+
var rawLength = raw.length
41+
buf = new Uint8Array(new ArrayBuffer(rawLength))
42+
for(var i = 0; i < rawLength; i++) {
43+
buf[i] = raw.charCodeAt(i)
44+
}
45+
}
46+
47+
if(sync) {
48+
var mod = new WebAssembly.Module(buf)
49+
return imports ? new WebAssembly.Instance(mod, imports) : mod
50+
} else {
51+
return _instantiateOrCompile(buf, imports, false)
52+
}
53+
}
54+
export { _loadWasmModule };
55+
`;

packages/wasm/src/index.ts

Lines changed: 16 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { Plugin } from 'rollup';
66

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

9+
import { getHelpersModule, HELPERS_ID } from './helper';
10+
911
export function wasm(options: RollupWasmOptions = {}): Plugin {
1012
const { sync = [], maxFileSize = 14 * 1024, publicPath = '' } = options;
1113

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

20+
resolveId(id) {
21+
if (id === HELPERS_ID) {
22+
return id;
23+
}
24+
25+
return null;
26+
},
27+
1828
load(id) {
29+
if (id === HELPERS_ID) {
30+
return getHelpersModule();
31+
}
32+
1933
if (!/\.wasm$/.test(id)) {
2034
return null;
2135
}
@@ -46,59 +60,6 @@ export function wasm(options: RollupWasmOptions = {}): Plugin {
4660
);
4761
},
4862

49-
banner: `
50-
function _loadWasmModule (sync, filepath, src, imports) {
51-
function _instantiateOrCompile(source, imports, stream) {
52-
var instantiateFunc = stream ? WebAssembly.instantiateStreaming : WebAssembly.instantiate;
53-
var compileFunc = stream ? WebAssembly.compileStreaming : WebAssembly.compile;
54-
55-
if (imports) {
56-
return instantiateFunc(source, imports)
57-
} else {
58-
return compileFunc(source)
59-
}
60-
}
61-
62-
var buf = null
63-
var isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null
64-
65-
if (filepath && isNode) {
66-
var fs = eval('require("fs")')
67-
var path = eval('require("path")')
68-
69-
return new Promise((resolve, reject) => {
70-
fs.readFile(path.resolve(__dirname, filepath), (error, buffer) => {
71-
if (error != null) {
72-
reject(error)
73-
}
74-
75-
resolve(_instantiateOrCompile(buffer, imports, false))
76-
});
77-
});
78-
} else if (filepath) {
79-
return _instantiateOrCompile(fetch(filepath), imports, true)
80-
}
81-
82-
if (isNode) {
83-
buf = Buffer.from(src, 'base64')
84-
} else {
85-
var raw = globalThis.atob(src)
86-
var rawLength = raw.length
87-
buf = new Uint8Array(new ArrayBuffer(rawLength))
88-
for(var i = 0; i < rawLength; i++) {
89-
buf[i] = raw.charCodeAt(i)
90-
}
91-
}
92-
93-
if(sync) {
94-
var mod = new WebAssembly.Module(buf)
95-
return imports ? new WebAssembly.Instance(mod, imports) : mod
96-
} else {
97-
return _instantiateOrCompile(buf, imports, false)
98-
}
99-
}
100-
`.trim(),
101-
10263
transform(code, id) {
10364
if (code && /\.wasm$/.test(id)) {
10465
const isSync = syncFiles.indexOf(id) !== -1;
@@ -115,7 +76,8 @@ export function wasm(options: RollupWasmOptions = {}): Plugin {
11576
src = null;
11677
}
11778

118-
return `export default function(imports){return _loadWasmModule(${+isSync}, ${publicFilepath}, ${src}, imports)}`;
79+
return `import { _loadWasmModule } from ${JSON.stringify(HELPERS_ID)};
80+
export default function(imports){return _loadWasmModule(${+isSync}, ${publicFilepath}, ${src}, imports)}`;
11981
}
12082
return null;
12183
},

packages/wasm/test/fixtures/foo.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default 'foo';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import sample from './sample.wasm';
2+
import foo from './foo';
3+
4+
const instance = sample({ env: {} });
5+
6+
t.is(instance.exports.main(), 3, 'wasm loaded');
7+
8+
t.is(foo, 'foo');

packages/wasm/test/test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,31 @@ try {
121121
} catch (err) {
122122
// worker threads aren't fully supported in Node versions before 11.7.0
123123
}
124+
125+
test('injectHelper', async (t) => {
126+
t.plan(4);
127+
128+
const injectImport = `import { _loadWasmModule } from ${JSON.stringify('\0wasmHelpers.js')};`;
129+
130+
const bundle = await rollup({
131+
input: 'fixtures/injectHelper.js',
132+
plugins: [
133+
wasm({
134+
sync: ['fixtures/sample.wasm']
135+
}),
136+
{
137+
name: 'test-detect',
138+
transform: (code, id) => {
139+
if (id.endsWith('sample.wasm')) {
140+
t.true(code.includes(injectImport));
141+
}
142+
if (id.endsWith('foo.js')) {
143+
t.true(!code.includes(injectImport));
144+
}
145+
return code;
146+
}
147+
}
148+
]
149+
});
150+
await testBundle(t, bundle);
151+
});

0 commit comments

Comments
 (0)