Skip to content

bug: link valid stream insertion of function return values #74

Description

@kbuffardi

Problem

Compiling a defined, streamable function return value can fail during WASM linking. Example that must compile and run:

#include <iostream>

int val() { return 5; }

int main() {
  std::cout << val();
}

Observed diagnostics include:

wasm-ld: error: /tmp/main-*.o: undefined symbol: __cxa_allocate_exception
wasm-ld: error: /tmp/main-*.o: undefined symbol: __cxa_throw

This points to the browser compiler worker's direct Clang/LLD invocation and C++ exception/runtime library linkage, rather than to the source expression itself.

Proposed plan

  1. Reproduce the failure through the real extension worker pipeline before choosing a fix. Capture the clang++ -### output, parsed plan.linkStep.args, and the existence of every driver-selected startup object, archive, and -L path in the fresh LLD virtual filesystem immediately before invoking wasm-ld.
  2. Determine whether the cause is driver-discovery stubs, parsed/forwarded argv, static-library ordering, or a virtual-path mismatch. Do not assume the sysroot is absent: the worker already extracts it into both compiler and linker instances.
  3. Add an artifact-aware E2E regression harness that executes the real clang++ -### -> -cc1 -> wasm-ld pipeline. Because the packaged compiler modules cannot be loaded directly in Node without a loader adaptation, use a browser/Worker-based harness, a deliberate loader shim, or extracted reusable worker logic; do not duplicate the worker pipeline in a mock-only test.
  4. Cover defined int and std::string return values streamed through std::cout; require successful compile, link, execution, and expected terminal output with no undefined __cxa_* diagnostics.
  5. Retain an undefined-function linker-failure control to prove diagnostics name the user symbol rather than a C++ runtime symbol.
  6. Apply the smallest confirmed fix to the worker or compile-plan execution, preserving all driver-selected linker arguments.
  7. Extend browser smoke coverage to replace the editor content with the defined int val(){ return 5; } stream-insertion program and compile/run it through the real extension path. Start with Chromium, then run the equivalent smoke on each supported browser target if the shared compiler path is unchanged.

Acceptance criteria

  • A defined int val(){ return 5; } used in std::cout << val(); compiles, links, runs, and prints 5.
  • A defined function returning std::string can be streamed successfully.
  • Successful valid cases have no undefined __cxa_* diagnostics.
  • An undefined declared function continues to report a linker failure naming the user symbol.
  • The new artifact-aware E2E test and Chromium browser smoke exercise real stream insertion through the compiler worker.
  • Lint, build, E2E suite, and required browser smoke tests pass.

Likely files

  • src/workers/compiler.worker.js
  • src/workers/compile-plan.mjs (only if plan parsing loses driver argv)
  • a new real-toolchain E2E test under scripts/
  • scripts/smoke-browser.mjs

Evidence

The sysroot contains libc++.a, libc++abi.a, and compiler builtins, while the worker separately discovers driver commands and invokes wasm-ld in a fresh virtual filesystem. The investigation must confirm that the selected linker inputs remain available and correctly ordered there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions