diff --git a/src/plugin/runtime.ts b/src/plugin/runtime.ts index 89c882c..d221ade 100644 --- a/src/plugin/runtime.ts +++ b/src/plugin/runtime.ts @@ -1,3 +1,4 @@ +import { readPackageJSON } from "pkg-types"; import { UMWASM_HELPERS_ID, UNWASM_EXTERNAL_PREFIX, @@ -8,19 +9,33 @@ import { // https://marketplace.visualstudio.com/items?itemName=Tobermory.es6-string-html const js = String.raw; -export function getWasmBinding(asset: WasmAsset, opts: UnwasmPluginOptions) { +export async function getWasmBinding( + asset: WasmAsset, + opts: UnwasmPluginOptions, +) { + // -- Auto load imports -- + const autoImports = await getWasmImports(asset, opts); + // --- Environment dependent code to initialize the wasm module using inlined base 64 or dynamic import --- const envCode: string = opts.esmImport ? js` -async function _instantiate(imports) { +${autoImports}; + +async function _instantiate(imports = _imports) { const _mod = await import("${UNWASM_EXTERNAL_PREFIX}${asset.name}").then(r => r.default || r); - return WebAssembly.instantiate(_mod, imports) + try { + return await WebAssembly.instantiate(_mod, imports) + } catch (error) { + console.error('[wasm] [error]', error); + throw error; + } } ` : js` import { base64ToUint8Array } from "${UMWASM_HELPERS_ID}"; +${autoImports}; -function _instantiate(imports) { +function _instantiate(imports = _imports) { const _data = base64ToUint8Array("${asset.source.toString("base64")}") return WebAssembly.instantiate(_data, imports) } @@ -136,3 +151,38 @@ export function createLazyWasmModule(_instantiator) { } `; } + +export async function getWasmImports( + asset: WasmAsset, + opts: UnwasmPluginOptions, +) { + const importNames = Object.keys(asset.imports || {}); + if (importNames.length === 0) { + return "const _imports = { /* no imports */ }"; + } + // Try to resolve from nearest package.json + const pkgJSON = await readPackageJSON(asset.id); + + let code = "const _imports = {"; + + for (const moduleName of importNames) { + const importNames = asset.imports[moduleName]; + const pkgImport = + pkgJSON.imports?.[moduleName] || pkgJSON.imports?.[`#${moduleName}`]; + + if (pkgImport) { + code = `import * as _imports_${moduleName} from "${pkgImport}";\n${code}`; + } + code += `\n ${moduleName}: {`; + for (const name of importNames) { + code += pkgImport + ? `\n ${name}: _imports_${moduleName}.${name},\n` + : `\n ${name}: () => { throw new Error("\`${moduleName}.${name}\` is not provided!")},\n`; + } + code += " },\n"; + } + + code += "};\n"; + + return code; +} diff --git a/test/fixture/_shared.mjs b/test/fixture/_shared.mjs deleted file mode 100644 index 800c417..0000000 --- a/test/fixture/_shared.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export const imports = { - env: { - // eslint-disable-next-line unicorn/consistent-function-scoping - seed: () => () => Math.random() * Date.now(), - }, -}; diff --git a/test/fixture/dynamic-import.mjs b/test/fixture/dynamic-import.mjs index bb8cf8c..1fe0d57 100644 --- a/test/fixture/dynamic-import.mjs +++ b/test/fixture/dynamic-import.mjs @@ -1,8 +1,6 @@ const { sum } = await import("@fixture/wasm/sum.wasm"); - -const { imports } = await import("./_shared.mjs"); const { rand } = await import("@fixture/wasm/rand.wasm").then((r) => - r.default(imports), + r.default(), ); export function test() { diff --git a/test/fixture/static-import.mjs b/test/fixture/static-import.mjs index c54017f..0446719 100644 --- a/test/fixture/static-import.mjs +++ b/test/fixture/static-import.mjs @@ -1,8 +1,7 @@ -import { imports } from "./_shared.mjs"; import { sum } from "@fixture/wasm/sum.wasm"; import initRand, { rand } from "@fixture/wasm/rand.wasm"; -await initRand(imports); +await initRand(); export function test() { if (sum(1, 2) !== 3) { diff --git a/test/node_modules/@fixture/wasm/env.mjs b/test/node_modules/@fixture/wasm/env.mjs new file mode 100644 index 0000000..9dfdabd --- /dev/null +++ b/test/node_modules/@fixture/wasm/env.mjs @@ -0,0 +1 @@ +export const seed = () => Math.random() * Date.now() diff --git a/test/node_modules/@fixture/wasm/package.json b/test/node_modules/@fixture/wasm/package.json index 0aee66f..e077fc9 100644 --- a/test/node_modules/@fixture/wasm/package.json +++ b/test/node_modules/@fixture/wasm/package.json @@ -4,5 +4,8 @@ "type": "module", "exports": { "./*": "./*" + }, + "imports": { + "#env": "./env.mjs" } }