Skip to content

Commit 5bb8cc3

Browse files
authoredAug 25, 2024··
feat: add initSync() to initialize WASM synchronously (#100)
This uses the synchronous WebAssembly APIs to compile the WASM part synchronously, which allows users to initialize the library and parse synchronously with WASM without having to resort to the JS version. This would be useful for Node.js core to use the WASM version in paths that require synchronous initialization (it currently always uses the JS version for that).
1 parent 7c74749 commit 5bb8cc3

File tree

7 files changed

+33
-7
lines changed

7 files changed

+33
-7
lines changed
 

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ When using the ESM version, Wasm is supported instead:
5959

6060
```js
6161
import { parse, init } from 'cjs-module-lexer';
62-
// init needs to be called and waited upon
62+
// init() needs to be called and waited upon, or use initSync() to compile
63+
// Wasm blockingly and synchronously.
6364
await init();
6465
const { exports, reexports } = parse(source);
6566
```

‎lexer.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export interface Exports {
55

66
export declare function parse(source: string, name?: string): Exports;
77
export declare function init(): Promise<void>;
8+
export declare function initSync(): void;

‎lexer.js

+1
Original file line numberDiff line numberDiff line change
@@ -1439,4 +1439,5 @@ function isExpressionTerminator (curPos) {
14391439
const initPromise = Promise.resolve();
14401440

14411441
module.exports.init = () => initPromise;
1442+
module.exports.initSync = () => {};
14421443
module.exports.parse = parseCJS;

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"scripts": {
1515
"test-js": "mocha -b -u tdd test/*.js",
1616
"test-wasm": "cross-env WASM=1 mocha -b -u tdd test/*.js",
17-
"test": "npm run test-wasm && npm run test-js",
17+
"test-wasm-sync": "cross-env WASM_SYNC=1 mocha -b -u tdd test/*.js",
18+
"test": "npm run test-wasm && npm run test-wasm-sync && npm run test-js",
1819
"bench": "node --expose-gc bench/index.mjs",
1920
"build": "node build.js ; babel dist/lexer.mjs -o dist/lexer.js ; terser dist/lexer.js -o dist/lexer.js",
2021
"build-wasm": "make lib/lexer.wasm && node build.js",

‎src/lexer.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,30 @@ function copyLE (src, outBuf16) {
9090
outBuf16[i] = src.charCodeAt(i++);
9191
}
9292

93+
function getWasmBytes() {
94+
const binary = 'WASM_BINARY'; // This string will be replaced by build.js.
95+
if (typeof window !== 'undefined' && typeof atob === 'function')
96+
return Uint8Array.from(atob(binary), x => x.charCodeAt(0));
97+
return Buffer.from(binary, 'base64');
98+
}
99+
93100
let initPromise;
94101
export function init () {
95102
if (initPromise)
96103
return initPromise;
97104
return initPromise = (async () => {
98-
const compiled = await WebAssembly.compile(
99-
(binary => typeof window !== 'undefined' && typeof atob === 'function' ? Uint8Array.from(atob(binary), x => x.charCodeAt(0)) : Buffer.from(binary, 'base64'))
100-
('WASM_BINARY')
101-
)
105+
const compiled = await WebAssembly.compile(getWasmBytes());
102106
const { exports } = await WebAssembly.instantiate(compiled);
103107
wasm = exports;
104108
})();
105109
}
110+
111+
export function initSync () {
112+
if (wasm) {
113+
return;
114+
}
115+
const compiled = new WebAssembly.Module(getWasmBytes());
116+
const { exports } = new WebAssembly.Instance(compiled);
117+
wasm = exports;
118+
return;
119+
}

‎test/_unit.js

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ async function loadParser () {
77
const m = await import('../dist/lexer.mjs');
88
await m.init();
99
parse = m.parse;
10+
} else if (process.env.WASM_SYNC) {
11+
const m = require('../dist/lexer.js');
12+
m.initSync();
13+
parse = m.parse;
1014
}
1115
else {
1216
parse = require('../lexer.js').parse;

‎test/integration.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ async function loadParser () {
88
const m = await import('../dist/lexer.mjs');
99
await m.init();
1010
parse = m.parse;
11+
} else if (process.env.WASM_SYNC) {
12+
const m = require('../dist/lexer.js');
13+
m.initSync();
14+
parse = m.parse;
1115
}
1216
else {
1317
parse = require('../lexer.js').parse;
@@ -31,7 +35,7 @@ suite('Samples', () => {
3135
const selfSource = fs.readFileSync(process.cwd() + '/lexer.js').toString();
3236
test('Self test', async () => {
3337
const { exports } = parse(selfSource);
34-
assert.deepStrictEqual(exports, ['init', 'parse']);
38+
assert.deepStrictEqual(exports, ['init', 'initSync', 'parse']);
3539
});
3640

3741
files.forEach(({ file, code }) => {

0 commit comments

Comments
 (0)
Please sign in to comment.