From 90519f8414c0e6d57e87a53720d77cfffe874306 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Mon, 3 Nov 2025 16:35:31 +0800 Subject: [PATCH 1/2] feat: support read wasm from memory fs --- e2e/wasm/index.test.ts | 9 +++++++++ e2e/wasm/src/factorial.wasm | Bin 0 -> 154 bytes e2e/wasm/src/factorial.wasm.d.ts | 1 + packages/core/src/core/plugins/external.ts | 2 +- packages/core/src/core/plugins/mockRuntime.ts | 11 +++++++++++ packages/core/src/runtime/worker/loadModule.ts | 17 +++++++++++++++++ packages/core/src/utils/error.ts | 7 +++++-- 7 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 e2e/wasm/index.test.ts create mode 100644 e2e/wasm/src/factorial.wasm create mode 100644 e2e/wasm/src/factorial.wasm.d.ts diff --git a/e2e/wasm/index.test.ts b/e2e/wasm/index.test.ts new file mode 100644 index 00000000..83b31e65 --- /dev/null +++ b/e2e/wasm/index.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@rstest/core'; + +test('WASM factorial', async () => { + const { _Z4facti: AsyncFactorial } = await import('./src/factorial.wasm'); + + expect(AsyncFactorial(1)).toBe(1); + expect(AsyncFactorial(2)).toBe(2); + expect(AsyncFactorial(3)).toBe(6); +}); diff --git a/e2e/wasm/src/factorial.wasm b/e2e/wasm/src/factorial.wasm new file mode 100644 index 0000000000000000000000000000000000000000..50ce8c098a4ce68742a7198ac3f24acc5044d88e GIT binary patch literal 154 zcmZQbEY4+QU|?WuYiMX-U`$}FXRKjv0<#%dTEKJx0|RR_M1+y85yW6%p9-Rw*m6^I z^NT8(7&zjiOwtmQOEMW4xDJDr?gf)fbxaNl433N*ybKBqYn&Ks6d9cu6`7bF6qpnk fo$70p80!>4EXGh?25tqWo&4M`K(_$F2YYS+izOn~ literal 0 HcmV?d00001 diff --git a/e2e/wasm/src/factorial.wasm.d.ts b/e2e/wasm/src/factorial.wasm.d.ts new file mode 100644 index 00000000..67641458 --- /dev/null +++ b/e2e/wasm/src/factorial.wasm.d.ts @@ -0,0 +1 @@ +export function _Z4facti(n: number): number; diff --git a/packages/core/src/core/plugins/external.ts b/packages/core/src/core/plugins/external.ts index 3f45c2d6..b915a9f7 100644 --- a/packages/core/src/core/plugins/external.ts +++ b/packages/core/src/core/plugins/external.ts @@ -15,7 +15,7 @@ const autoExternalNodeModules: ( return callback(); } - if (request.startsWith('@swc/helpers/')) { + if (request.startsWith('@swc/helpers/') || request.endsWith('.wasm')) { // @swc/helper is a special case (Load by require but resolve to esm) return callback(); } diff --git a/packages/core/src/core/plugins/mockRuntime.ts b/packages/core/src/core/plugins/mockRuntime.ts index 4276eb40..3b223502 100644 --- a/packages/core/src/core/plugins/mockRuntime.ts +++ b/packages/core/src/core/plugins/mockRuntime.ts @@ -48,6 +48,17 @@ class MockRuntimeRspackPlugin { module.source!.source = Buffer.from(finalSource); } + + if (module.name === 'async_wasm_loading') { + const finalSource = module.source!.source.toString('utf-8').replace( + // Sets the object configurable so that imported properties can be spied + // Hard coded in EJS template https://github.com/web-infra-dev/rspack/tree/7df875eb3ca3bb4bcb21836fdf4e6be1f38a057c/crates/rspack_plugin_wasm/src/runtime + 'readFile(', + 'readWasmFile(', + ); + + module.source!.source = Buffer.from(finalSource); + } }, ); }); diff --git a/packages/core/src/runtime/worker/loadModule.ts b/packages/core/src/runtime/worker/loadModule.ts index 4a24e3ba..2ca0d91c 100644 --- a/packages/core/src/runtime/worker/loadModule.ts +++ b/packages/core/src/runtime/worker/loadModule.ts @@ -171,6 +171,23 @@ export const loadModule = ({ assetFiles, interopDefault, ), + readWasmFile: ( + wasmPath: string, + callback: (err: Error | null, data?: Buffer) => void, + ) => { + const currentDirectory = path.dirname(distPath); + const joinedPath = isRelativePath(wasmPath) + ? path.join(currentDirectory, wasmPath) + : wasmPath; + const content = assetFiles[joinedPath]; + if (content) { + callback(null, Buffer.from(content, 'utf-8')); + } else { + callback( + new Error(`WASM file ${joinedPath} not found in asset files.`), + ); + } + }, __rstest_dynamic_import__: defineRstestDynamicImport({ testPath, interopDefault, diff --git a/packages/core/src/utils/error.ts b/packages/core/src/utils/error.ts index c696bdbb..8eadca71 100644 --- a/packages/core/src/utils/error.ts +++ b/packages/core/src/utils/error.ts @@ -67,8 +67,11 @@ export async function printError( fullStack: error.fullStack, getSourcemap, }); - - if (!stackFrames.length && error.stack.length) { + if ( + !stackFrames.length && + Array.isArray(error.stack) && + error.stack.length + ) { logger.log( color.gray( "No error stack found, set 'DEBUG=rstest' to show fullStack.", From ed0cce8b03ef2f4f817df6f54e3cae6eed4b0340 Mon Sep 17 00:00:00 2001 From: "gaoyuan.1226" Date: Fri, 7 Nov 2025 11:15:01 +0800 Subject: [PATCH 2/2] fix: normalize wasm path --- packages/core/src/runtime/worker/loadModule.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/src/runtime/worker/loadModule.ts b/packages/core/src/runtime/worker/loadModule.ts index 2ca0d91c..4e329d10 100644 --- a/packages/core/src/runtime/worker/loadModule.ts +++ b/packages/core/src/runtime/worker/loadModule.ts @@ -175,11 +175,10 @@ export const loadModule = ({ wasmPath: string, callback: (err: Error | null, data?: Buffer) => void, ) => { - const currentDirectory = path.dirname(distPath); const joinedPath = isRelativePath(wasmPath) - ? path.join(currentDirectory, wasmPath) + ? path.join(path.dirname(distPath), wasmPath) : wasmPath; - const content = assetFiles[joinedPath]; + const content = assetFiles[path.normalize(joinedPath)]; if (content) { callback(null, Buffer.from(content, 'utf-8')); } else {