[GH-ISSUE #4001] [Bug] WASM glue inspection omits string literals in JavaScript directive prologues #1589

Closed
opened 2026-10-16 21:07:32 +00:00 by bsakaguchi · 5 comments
Owner

Originally created by @coygeek on GitHub (Oct 15, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4001

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

inspect-wasm-artifact omits a .wasm string literal when Babel parses it as a directive at the start of the JavaScript program. Inspection succeeds with validation: "valid" and glue parse_status: "complete", but returns no references. Adding a leading empty statement makes the same literal appear as a local path candidate.

Reproduction

Use the source revision below with its locked dependencies and built CLI. Configure caller-supplied WABT 1.0.42 through REA_WABT_BIN_DIRECTORY. Run these commands from a disposable source checkout, using relative fixture paths as shown:

node --input-type=module - <<'JS'
import { writeFileSync } from "node:fs";
writeFileSync("module.wasm", Buffer.from("0061736d01000000", "hex"));
writeFileSync("glue.js", '"module.wasm";\n');
writeFileSync("glue-control.js", ';"module.wasm";\n');
JS
node scripts/rea.mjs inspect-wasm-artifact module.wasm --glue_paths glue.js --json
node scripts/rea.mjs inspect-wasm-artifact module.wasm --glue_paths glue-control.js --json

Inspect normalized_result.glue[0]. Each reduced command was executed once. Both exited zero; only the control retained the literal. An earlier two-line probe likewise retained the ordinary literal on its second line and omitted the directive on its first line.

Expected behavior

Retain the directive occurrence as a static-literal reference with value module.wasm, line 1, column 0, and the selected module as a local path candidate. Preserve the control's reference at column 1.

docs/wasm-artifacts.md:89-96 promises retained .wasm string literals with coordinates and candidate associations. These are literal associations without a data-flow or runtime-loading claim, so a directive's lack of loading behavior does not explain the omission.

Impact and scope

P2, supported. Successful, parser-complete inspection omits a supported literal association for the reproduced directive-prologue input. This is a bounded evidence omission; it does not establish a missed runtime load or prevalence in application bundles.

A practical workaround is to inspect the unchanged glue file's directive prologue directly and retain that source evidence. Changing the input as in the control demonstrates the parser distinction but does not replace evidence about the original file.

REA version

rea 6.5.0 at source commit 4692bb3330

The cited adapter and documentation are unchanged on current origin/main at 6fcfc5b5e0c063300cd5278dd8bad5b1ab1374f6. The failure mechanism still holds by source inspection; the full CLI reproduction was not rerun on that revision.

Runtime and platform

Node 24.18.0; macOS arm64; real caller-supplied WABT 1.0.42. No provider or parser was mocked.

Target and artifact context

An eight-byte valid empty WebAssembly core module, hex 0061736d01000000, plus the two one-line JavaScript fixtures above. The selected module is automatically included among candidate paths. No WASM module was executed.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Observed relevant fields in normalized_result.glue[0]:

Directive fixture:

{"parse_status":"complete","references":[]}

Leading-empty-statement control:

{"parse_status":"complete","references":[{"value":"module.wasm","line":1,"column":1,"association":"local-path-candidate","evidence_kind":"static-literal"}]}

The full control reference also contains the selected module in candidate_paths; the host-specific prefix is omitted above. Both calls report validation: "valid" and exit zero. These results come from the compiled public CLI with real WABT.

Typed outcome or recovery expected

Return the supported literal association while retaining exact selected byte digests and parser status. Continue to describe it as a static candidate rather than runtime-loading proof.

Analysis or suspected cause

Source-derived reasoning: src/wasm/WasmGlueAdapter.ts:25-38 accepts Babel StringLiteral and expression-free TemplateLiteral nodes. A DirectiveLiteral matches neither branch.

Additional context

A proposed regression check should also cover the directive position inside a function body. That location was not executed in the reduced CLI reproduction above.

Related open #3402 and PR #3455 concern equivalent candidate path spellings. This report concerns an omitted literal before path matching. Related open #3952 concerns directive changes in structural fingerprints, a separate output contract.

Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4001 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `inspect-wasm-artifact` omits a `.wasm` string literal when Babel parses it as a directive at the start of the JavaScript program. Inspection succeeds with `validation: "valid"` and glue `parse_status: "complete"`, but returns no references. Adding a leading empty statement makes the same literal appear as a local path candidate. ### Reproduction Use the source revision below with its locked dependencies and built CLI. Configure caller-supplied WABT 1.0.42 through `REA_WABT_BIN_DIRECTORY`. Run these commands from a disposable source checkout, using relative fixture paths as shown: ```sh node --input-type=module - <<'JS' import { writeFileSync } from "node:fs"; writeFileSync("module.wasm", Buffer.from("0061736d01000000", "hex")); writeFileSync("glue.js", '"module.wasm";\n'); writeFileSync("glue-control.js", ';"module.wasm";\n'); JS node scripts/rea.mjs inspect-wasm-artifact module.wasm --glue_paths glue.js --json node scripts/rea.mjs inspect-wasm-artifact module.wasm --glue_paths glue-control.js --json ``` Inspect `normalized_result.glue[0]`. Each reduced command was executed once. Both exited zero; only the control retained the literal. An earlier two-line probe likewise retained the ordinary literal on its second line and omitted the directive on its first line. ### Expected behavior Retain the directive occurrence as a `static-literal` reference with value `module.wasm`, line 1, column 0, and the selected module as a local path candidate. Preserve the control's reference at column 1. [`docs/wasm-artifacts.md:89-96`](https://github.com/morluto/rea/blob/4692bb33300c7cb77b095b6cc0c33da861c1b860/docs/wasm-artifacts.md#L89-L96) promises retained `.wasm` string literals with coordinates and candidate associations. These are literal associations without a data-flow or runtime-loading claim, so a directive's lack of loading behavior does not explain the omission. ### Impact and scope P2, supported. Successful, parser-complete inspection omits a supported literal association for the reproduced directive-prologue input. This is a bounded evidence omission; it does not establish a missed runtime load or prevalence in application bundles. A practical workaround is to inspect the unchanged glue file's directive prologue directly and retain that source evidence. Changing the input as in the control demonstrates the parser distinction but does not replace evidence about the original file. ### REA version rea 6.5.0 at source commit 4692bb33300c7cb77b095b6cc0c33da861c1b860 The cited adapter and documentation are unchanged on current `origin/main` at `6fcfc5b5e0c063300cd5278dd8bad5b1ab1374f6`. The failure mechanism still holds by source inspection; the full CLI reproduction was not rerun on that revision. ### Runtime and platform Node 24.18.0; macOS arm64; real caller-supplied WABT 1.0.42. No provider or parser was mocked. ### Target and artifact context An eight-byte valid empty WebAssembly core module, hex `0061736d01000000`, plus the two one-line JavaScript fixtures above. The selected module is automatically included among candidate paths. No WASM module was executed. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Observed relevant fields in `normalized_result.glue[0]`: Directive fixture: ```json {"parse_status":"complete","references":[]} ``` Leading-empty-statement control: ```json {"parse_status":"complete","references":[{"value":"module.wasm","line":1,"column":1,"association":"local-path-candidate","evidence_kind":"static-literal"}]} ``` The full control reference also contains the selected module in `candidate_paths`; the host-specific prefix is omitted above. Both calls report `validation: "valid"` and exit zero. These results come from the compiled public CLI with real WABT. ### Typed outcome or recovery expected Return the supported literal association while retaining exact selected byte digests and parser status. Continue to describe it as a static candidate rather than runtime-loading proof. ### Analysis or suspected cause Source-derived reasoning: [`src/wasm/WasmGlueAdapter.ts:25-38`](https://github.com/morluto/rea/blob/4692bb33300c7cb77b095b6cc0c33da861c1b860/src/wasm/WasmGlueAdapter.ts#L25-L38) accepts Babel `StringLiteral` and expression-free `TemplateLiteral` nodes. A `DirectiveLiteral` matches neither branch. ### Additional context A proposed regression check should also cover the directive position inside a function body. That location was not executed in the reduced CLI reproduction above. Related open [#3402](https://github.com/morluto/rea/issues/3402) and [PR #3455](https://github.com/morluto/rea/pull/3455) concern equivalent candidate path spellings. This report concerns an omitted literal before path matching. Related open [#3952](https://github.com/morluto/rea/issues/3952) concerns directive changes in structural fingerprints, a separate output contract.
Author
Owner

@XinwangTao commented on GitHub (Oct 15, 2026):

Confirmed: a leading string literal at program start is parsed as a directive by Babel and skipped by the literal collector, which is why the control with the leading semicolon surfaces it. Directives are still string expressions in the AST, so collecting their values as static-literal references is the right fix and keeps glue discovery consistent regardless of statement position.

<!-- gh-comment-id:6186719053 --> @XinwangTao commented on GitHub (Oct 15, 2026): Confirmed: a leading string literal at program start is parsed as a directive by Babel and skipped by the literal collector, which is why the control with the leading semicolon surfaces it. Directives are still string expressions in the AST, so collecting their values as static-literal references is the right fix and keeps glue discovery consistent regardless of statement position.
Author
Owner

@Sriram-PR commented on GitHub (Oct 15, 2026):

I'll take this one. Reproduced on main (6fcfc5b) with WABT 1.0.42 on Linux: glue.js comes back complete with no references, the ; control has module.wasm at column 1. Babel parses the leading literal as a Directive, and the glue literal collector only accepts StringLiteral and plain template literals, so the DirectiveLiteral is skipped. Plan: collect directive literals too, decoding their escapes (Babel keeps directive values raw) so "module\x2ewasm" matches like the string literal does, plus a regression test with the issue's directive and control. PR shortly.

<!-- gh-comment-id:6187108458 --> @Sriram-PR commented on GitHub (Oct 15, 2026): I'll take this one. Reproduced on main (6fcfc5b) with WABT 1.0.42 on Linux: `glue.js` comes back `complete` with no references, the `;` control has `module.wasm` at column 1. Babel parses the leading literal as a `Directive`, and the glue literal collector only accepts `StringLiteral` and plain template literals, so the `DirectiveLiteral` is skipped. Plan: collect directive literals too, decoding their escapes (Babel keeps directive values raw) so `"module\x2ewasm"` matches like the string literal does, plus a regression test with the issue's directive and control. PR shortly.
Author
Owner

@Sriram-PR commented on GitHub (Oct 15, 2026):

Fix is ready on Sriram-PR/rea fix/wasm-glue-directive-literals (directive literals collected, escapes decoded, regression test, checked with WABT 1.0.42). I'm at the 3 open PR limit here, so I'll open it as soon as one of #4019 / #4023 / #4024 is merged.

<!-- gh-comment-id:6187177863 --> @Sriram-PR commented on GitHub (Oct 15, 2026): Fix is ready on Sriram-PR/rea `fix/wasm-glue-directive-literals` (directive literals collected, escapes decoded, regression test, checked with WABT 1.0.42). I'm at the 3 open PR limit here, so I'll open it as soon as one of #4019 / #4023 / #4024 is merged.
Author
Owner

@XinwangTao commented on GitHub (Oct 15, 2026):

Plan looks solid. Decoding escapes in directive values is the important detail — Babel exposes directive values raw (with escape sequences intact), so decoding them keeps the collected reference value consistent with ordinary StringLiteral collection; otherwise "module\\x2ewasm" and "module.wasm" would surface different values for the same file. Adding the semicolon-prefixed control as a regression case also guards the column-offset path. Looks good to merge once a PR slot opens.

<!-- gh-comment-id:6187528696 --> @XinwangTao commented on GitHub (Oct 15, 2026): Plan looks solid. Decoding escapes in directive values is the important detail — Babel exposes directive values raw (with escape sequences intact), so decoding them keeps the collected reference value consistent with ordinary StringLiteral collection; otherwise `"module\\x2ewasm"` and `"module.wasm"` would surface different values for the same file. Adding the semicolon-prefixed control as a regression case also guards the column-offset path. Looks good to merge once a PR slot opens.
Author
Owner

@coygeek commented on GitHub (Oct 18, 2026):

Addressed on main by github.com/morluto/rea@4f87f02bb1. WASM glue analysis now retains leading JavaScript directive literals, uses their cooked values for escaped paths, and preserves source coordinates and selected-module candidate associations. The regression assertions cover the directive at column 0 and semicolon-prefixed control at column 1. Verified by reviewing the current source, regression assertions and commit ancestry; I have not rerun the reproduction. Closing as addressed on main.

<!-- gh-comment-id:6244125054 --> @coygeek commented on GitHub (Oct 18, 2026): Addressed on main by https://github.com/morluto/rea/commit/4f87f02bb19bf77349a683a5bcb2da2d1da427d0. WASM glue analysis now retains leading JavaScript directive literals, uses their cooked values for escaped paths, and preserves source coordinates and selected-module candidate associations. The regression assertions cover the directive at column 0 and semicolon-prefixed control at column 1. Verified by reviewing the current source, regression assertions and commit ancestry; I have not rerun the reproduction. Closing as addressed on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1589
No description provided.