fix(wasm): parse source-phase import glue without evaluation

This commit is contained in:
morluto
2026-10-24 02:35:57 +08:00
parent c3e4c116d5
commit fd08a22742
4 changed files with 35 additions and 4 deletions
+6
View File
@@ -194,3 +194,9 @@ After building, run `REA_WABT_BIN_DIRECTORY=/absolute/wabt/bin node
scripts/verify-wasm-interface-comparison.mjs` for original-module comparison
through the compiled CLI and stdio MCP. It uses owned fixtures and WABT 1.0.42;
no WASM module is instantiated or executed.
Glue parsing accepts Node-supported WASM source-phase imports, including
`import source module from "./module.wasm"` and
`await import.source("./module.wasm")`. Their string literals retain the same
coordinates and local candidate associations as ordinary import literals; these
are static source observations, without module instantiation or execution.
+2
View File
@@ -231,6 +231,8 @@ try {
'fetch("./module.wasm"); new URL("https://example.invalid/module.wasm?version=1", import.meta.url);';
const glueSources = [
glueSource,
'import source module from "./module.wasm"; new URL("https://example.invalid/module.wasm?version=1", import.meta.url);',
'const module = await import.source("./module.wasm"); new URL("https://example.invalid/module.wasm?version=1", import.meta.url);',
`\uFEFF${glueSource}`,
`\uFEFF\n${glueSource}`,
`#!/usr/bin/env node\n${glueSource}`,
@@ -87,6 +87,7 @@ const parseWithRuntimeContext = (
* `.ts/.cts/.mts` (angle-bracket assertions, not JSX) and for all
* declaration files. `.mts` (including `.d.mts`) sets
* `disallowAmbiguousJSXLike`, matching tsc's `.mts` mode.
* - `sourcePhaseImports` retains Node-supported WASM source imports as AST data.
* - `decorators-legacy` always present: without it decorated sources fail
* hard instead of reporting recovered syntax, losing every derived fact.
* - Unknown paths retain the existing JSX- and TypeScript-capable contract
@@ -94,7 +95,8 @@ const parseWithRuntimeContext = (
*/
export const parserPluginsForPath = (sourcePath?: string): ParserPlugin[] => {
const path = sourcePath ?? "";
if (/\.(?:js|jsx|mjs|cjs)$/iu.test(path)) return ["decorators-legacy", "jsx"];
const syntax: ParserPlugin[] = ["decorators-legacy", "sourcePhaseImports"];
if (/\.(?:js|jsx|mjs|cjs)$/iu.test(path)) return [...syntax, "jsx"];
const dts = /\.d\.(?:ts|mts|cts)$/iu.test(path);
const isTsLike = /\.(?:ts|cts|mts)$/iu.test(path);
const isTsx = /\.tsx$/iu.test(path);
@@ -107,9 +109,7 @@ export const parserPluginsForPath = (sourcePath?: string): ParserPlugin[] => {
},
];
const jsxCapable = !dts && (isTsx || !isTsLike);
return jsxCapable
? ["decorators-legacy", "jsx", typescript]
: ["decorators-legacy", typescript];
return jsxCapable ? [...syntax, "jsx", typescript] : [...syntax, typescript];
};
/** `.mjs` and `.mts` explicitly select module mode. */
+23
View File
@@ -435,3 +435,26 @@ it.each(["\n", "\r", "\u2028", "\u2029"])(
}
},
);
it.each([
'import source module from "./module.wasm";',
'const module = await import.source("./module.wasm");',
'import * as module from "./module.wasm";',
'const module = await import("./module.wasm");',
])("retains source-phase and ordinary WASM import literals: %s", (source) => {
const offset = source.indexOf('"./module.wasm"');
expect(
associateWasmGlue(source, "/app/glue.mjs", ["/app/module.wasm"]),
).toEqual({
parse_status: "complete",
references: [
{
value: "./module.wasm",
line: 1,
column: offset,
candidate_paths: ["/app/module.wasm"],
association: "local-path-candidate",
evidence_kind: "static-literal",
},
],
});
});