Skip to content

fix: #835/#846 followup — feed codegen FFI provenance into auto-optimize stdlib features#884

Merged
proggeramlug merged 1 commit into
mainfrom
fix/835-846-followup-stdlib-feature-gate
May 17, 2026
Merged

fix: #835/#846 followup — feed codegen FFI provenance into auto-optimize stdlib features#884
proggeramlug merged 1 commit into
mainfrom
fix/835-846-followup-stdlib-feature-gate

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Summary

  • Codegen-side FFI registry now records the perry-stdlib Cargo feature each Stdlib-resident symbol needs. The compile driver drains those into ctx.extra_stdlib_features, and build_optimized_libs unions them into the feature set BEFORE rebuilding libperry_stdlib.a. Closes the Link failure: needs_stdlib not set when compiled-package code (Effect) references ReadableStream FFIs #835/express link-fails: js_node_http_create_server codegen'd but perry-ext-http-server not linked #846 follow-up where Effect's Stream lowering link-failed with Undefined symbols: _js_readable_stream_new because the auto-optimize stdlib was built without bundled-streams.
  • OwnerKind::Stdlib becomes OwnerKind::Stdlib { feature: Option<&'static str> }. All 35 stream entries in the registry now declare feature: Some("bundled-streams"). The http path (OwnerKind::WellKnown("http")) already worked via the existing well-known flow and is unchanged.
  • Smoke test test-files/test_issue_835_846_b_stream_ffi_link.ts exercises new ReadableStream(...) without import "streams" plus createServer(...) from node:http, guarding the regression where the auto-optimize stdlib drops these features.

Test plan

  • cargo build --release -p perry-runtime -p perry-stdlib -p perry
  • cargo test --release --workspace --exclude perry-ui-* --exclude perry-jsruntime clean (no failures)
  • cargo test --release -p perry-codegen updated registry test passes
  • Smoke test compiles + runs: prints stream r1 done: false, stream r1 value: hello, server created: true
  • Effect repro from issue now reaches a runtime stage instead of failing at link with _js_readable_stream_* undefined

Closes the #835/#846 follow-up. Refs #835, #846.

…optimize stdlib feature set

Effect's `Stream` lowering and similar compiled-package code emits
`js_readable_stream_*` FFI calls without any `import "streams"` in the
user TS. The codegen-side FFI registry (`ext_registry.rs`) tagged those
as `OwnerKind::Stdlib` and the drain flipped `ctx.needs_stdlib`, but
the auto-optimize layer (`build_optimized_libs`) rebuilds perry-stdlib
with only the Cargo features `compute_required_features` derived from
`ctx.native_module_imports` — which is empty when there's no explicit
`import "streams"`. So `bundled-streams` was dropped, `pub mod streams`
was `#[cfg]`-gated out of the .a, and the link failed with
"Undefined symbols: _js_readable_stream_new" etc. — even though the CLI
said "Linking (with stdlib)...".

Fix: extend `OwnerKind::Stdlib` to carry `feature: Option<&'static str>`
(the perry-stdlib Cargo feature gate for the FFI's providing module),
add `CompilationContext::extra_stdlib_features: BTreeSet<&'static str>`
that the registry drain populates from each Stdlib entry, and union
that set into the feature list `build_optimized_libs` passes to cargo.
Every existing stream FFI in the registry now declares
`feature: Some("bundled-streams")`.

The http path (`OwnerKind::WellKnown("http")`) already worked: the
drain inserts "http" into `native_module_imports`, the well-known
table routes to perry-ext-http, and the link resolves. No change there.

Smoke test `test-files/test_issue_835_846_b_stream_ffi_link.ts` exercises
`new ReadableStream(...)` (without `import "streams"`) AND
`createServer(handler)` from `node:http`. The Effect repro now links
and advances past the symbol-resolution stage to a runtime TypeError
from a different code path (separate, pre-existing bug).
@proggeramlug proggeramlug force-pushed the fix/835-846-followup-stdlib-feature-gate branch from 1434e8b to 9444781 Compare May 16, 2026 23:44
@proggeramlug proggeramlug merged commit 465b2eb into main May 17, 2026
9 checks passed
@proggeramlug proggeramlug deleted the fix/835-846-followup-stdlib-feature-gate branch May 17, 2026 00:19
proggeramlug added a commit that referenced this pull request May 17, 2026
…sruntime arm of build_and_run_link (#887)

Express (perry.compilePackages: ["express"]) link-failed on
_js_node_http_create_server / _js_node_http_res_end because
build_and_run_link's `if let Some(ref jsruntime) = jsruntime_lib {...}`
arm appended only jsruntime + runtime — the parallel
`else if ctx.needs_stdlib` arm that emits well_known_libs +
stdlib_lib was unreachable. The codegen-side FFI provenance
registry (#884) correctly drained OwnerKind::WellKnown("http") into
ctx.native_module_imports, and the auto-optimize layer built
libperry_ext_http.a + pushed it onto well_known_libs — but the
link command then silently dropped it.

Fix mirrors the well-known emission into the jsruntime arm:
after jsruntime + runtime, when ctx.needs_stdlib is true,
append stdlib_lib (if Some) + every well_known_libs entry.
Mach-O / ELF archive scan is first-definition-wins, so
jsruntime's bundled-stdlib copies still win for duplicate js_*
symbols (the documented duplicate-symbol warnings); the
perry-ext-* libs cover symbols neither jsruntime nor its
bundled stdlib carries.

Validation: express repro links cleanly (advances to a separate
runtime TypeError from the Proxy/callable shape — out of scope
per the issue). New regression test exercises both halves
standalone: static-import a .js fixture (forces ctx.needs_js_runtime)
+ http.createServer (forces well_known_libs to contain
perry-ext-http). cargo test --release --workspace clean (1098
passed, 0 failed).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant