From 6611af0daa794e739fc64830e404914ff1956774 Mon Sep 17 00:00:00 2001 From: Zephyr Lykos Date: Tue, 30 Apr 2024 23:42:09 +0800 Subject: [PATCH] Implement externalized WASM build, fix #96 --- build.js | 102 +++++++++++++++++++++++++-------------------------- package.json | 5 ++- src/lexer.js | 19 +++++++--- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/build.js b/build.js index 8db7738..883f6e8 100755 --- a/build.js +++ b/build.js @@ -1,73 +1,69 @@ const fs = require('fs'); -const { buildSync } = require('esbuild'); -const path = require('path/posix') +const esbuild = require('esbuild'); -const { EXTERNAL_PATH } = process.env; -const MINIFY = !EXTERNAL_PATH; +let minify = true; +let cjsBuild = true; +let esmBuild = true; -try { fs.mkdirSync('./dist'); } -catch (e) {} +for (const arg of process.argv) { + switch (arg) { + case '--without-cjs': { + cjsBuild = false; + break; + } + case '--without-esm': { + esmBuild = false; + break; + } + case '--no-minify': { + minify = false; + break; + } + default: + continue; + } +} + +fs.mkdirSync('./dist', { recursive: true }); const wasmBuffer = fs.readFileSync('./lib/lexer.wasm'); const pjson = JSON.parse(fs.readFileSync('./package.json').toString()); -buildSync({ +/** @type {esbuild.BuildOptions} */ +const buildOptions = { entryPoints: ['./src/lexer.js'], - outfile: './dist/lexer.mjs', bundle: true, - minify: MINIFY, + minify, platform: 'node', - format: 'esm', banner: { - js: `/* cjs-module-lexer ${pjson.version} */` + js: `/* cjs-module-lexer ${pjson.version} */`, }, - define: EXTERNAL_PATH ? { - WASM_BINARY: 'undefined', - EXTERNAL_PATH: `'${path.join(EXTERNAL_PATH, 'lib/lexer.wasm')}'`, - } : { + outfile: './dist/lexer.mjs', + format: 'esm', + define: { WASM_BINARY: `'${wasmBuffer.toString('base64')}'`, - EXTERNAL_PATH: 'undefined' - } -}) - -if (EXTERNAL_PATH) { - buildSync({ - stdin: { - contents: `'use strict'; -let lazy; -async function init () { - if (!lazy) { - lazy = await import(require('node:url').pathToFileURL(require('node:module').createRequire('${EXTERNAL_PATH}/dist/lexer.js').resolve('./lexer.mjs'))); - } - module.exports = lazy; - return lazy.init(); -} - -function parse (source, name = '@') { - if (!lazy) - throw new Error('Not initialized'); + }, +}; - return lazy.parse(source, name); +if (esmBuild) { + // ESM builds are used when importing from npm. + // Assume lib/lexer.wasm exists. + esbuild.buildSync({ + ...buildOptions, + define: { + WASM_BINARY: 'undefined', + }, + }); } -module.exports = { init, parse };`, - loader: 'js', - }, +if (cjsBuild) { + // CJS builds are used for libnode inlined builtins. + esbuild.buildSync({ + ...buildOptions, outfile: './dist/lexer.js', - minify: MINIFY, - platform: 'node', format: 'cjs', + logOverride: { + 'empty-import-meta': 'silent' + }, }); -} else { - buildSync({ - entryPoints: ['./dist/lexer.mjs'], - outfile: './dist/lexer.js', - minify: MINIFY, - platform: 'node', - format: 'cjs', - banner: { - js: `/* cjs-module-lexer ${pjson.version} */` - } - }) } - diff --git a/package.json b/package.json index dae6bea..c4fce79 100755 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "mocha": "^9.1.3" }, "files": [ - "dist", + "dist/", + "lib/lexer.wasm", "lexer.d.ts" ], "repository": { @@ -41,4 +42,4 @@ "url": "https://github.com/nodejs/cjs-module-lexer/issues" }, "homepage": "https://github.com/nodejs/cjs-module-lexer#readme" -} \ No newline at end of file +} diff --git a/src/lexer.js b/src/lexer.js index f3dc575..13e71b2 100755 --- a/src/lexer.js +++ b/src/lexer.js @@ -90,19 +90,26 @@ function copyLE (src, outBuf16) { outBuf16[i] = src.charCodeAt(i++); } -const loadWasm = (typeof EXTERNAL_PATH === "string" && (async () => { - return (await import("node:fs/promises")) +/* + * Load from file when WASM_BINARY isn't inlined. + * A LogicalExpression is used here instead of a ConditionalExpression, + * to ensure esbuild perform dead code elimination correctly. + */ +const loadWasm = (typeof WASM_BINARY === 'undefined' && (async () => { + // we can safely assume import.meta works here with the following workaround. + // https://github.com/nodejs/cjs-module-lexer/blob/bcc6ce4/build.js#L36-L53 + return (await import('node:fs/promises')) .readFile( - (await import("node:url")).fileURLToPath( - import.meta.resolve("../lib/lexer.wasm") + (await import('node:url')).fileURLToPath( + import.meta.resolve('../lib/lexer.wasm') ) ); })) || (async () => { const binary = WASM_BINARY - if (typeof window !== "undefined" && typeof atob === "function") { + if (typeof window !== 'undefined' && typeof atob === 'function') { return Uint8Array.from(atob(binary), (x) => x.charCodeAt(0)); } else { - return Buffer.from(binary, "base64"); + return Buffer.from(binary, 'base64'); } });