fix(runtime): define js_node_system_error_value (unbreak cargo-test link)#5124
Conversation
…ink) PR #5078 added an extern declaration + caller for js_node_system_error_value (perry-ffi: system_error_value → perry-ext-http client_events) but never shipped the runtime #[no_mangle] definition, so any program/test linking perry-ext-http failed at link time: undefined reference to `js_node_system_error_value' This broke cargo-test on main (e.g. issue_4903_listen_callback_deferred's late_listening_listener_fires and listen_callback_is_deferred_and_this_bound). Define the symbol in perry-runtime mirroring js_error_value_with_code: build the Error from the message, then register .code/.syscall/.errno into the message-keyed side tables that the existing object::field_get_set getters read back (register_error_code_pub / register_error_syscall / register_error_errno). code/syscall are interned to &'static str. A #[used] anchor pins the symbol against the auto-optimize LTO dead-strip, matching the sibling KEEP_JS_ERROR_VALUE_WITH_CODE. Verified: the two listener tests now pass (2 passed; 0 failed). https://claude.ai/code/session_01HKXzNHuniuu33SAUrLSN2f
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds ChangesNode System Error FFI Export
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Bumps to 0.5.1167 to ship the js_node_system_error_value link-regression fix (#5124) that the broken v0.5.1166 tag predates. See CHANGELOG.
… main merge The merge of main (#5124, which independently defined js_node_system_error_value) left two definitions in error.rs and lib.rs over the 2000-line cap. Drop this PR's duplicate runtime definition (keep main's registry-based one) and move arm_expect_continue from lib.rs into continue_client.rs.
* fix(http): node:http 100-continue handshake end-to-end (#5080) Wires the `Expect: 100-continue` flow on both the client and the server so the interim `100 Continue` exchange completes (previously produced no output where Node completes the request). Client (perry-ext-http): - New `continue_client` raw-socket path. reqwest swallows interim 1xx responses, so a request carrying `Expect: 100-continue` (plain http) flushes its head up front (body withheld), reads the interim `100 Continue`, and emits a new `PendingHttpEvent::Continue` that drives the request's `'continue'` listeners. `req.end(body)` then hands the withheld body to the in-flight exchange over a oneshot, which sends it (chunked) and parses the final response. Delivery reuses the normal streaming path (`ResponseHead`/`ResponseChunk`/`ResponseEnd`). Server (perry-ext-http-server): - `Expect: 100-continue` with a `'checkContinue'` listener now dispatches that listener instead of `'request'`/the handler (Node's semantics). hyper auto-emits the interim `100 Continue` when the body is first polled, so `res.writeContinue()` is a confirmation no-op. Wired for both http and https; http2 defaults to the normal path. Runtime (perry-runtime): - Define `js_node_system_error_value`, the runtime entry the #5078 transport-error path declared in perry-ffi but never implemented (a fresh ext-http link otherwise fails with an undefined reference). Builds a Node-style system Error carrying `.code`/`.syscall`/`.errno`. Verified byte-for-byte against Node v22 (continue event / body continue:payload / closed), both directions (perry client ↔ node server), and the transport-error path now reports ECONNREFUSED/connect. * fix(http): rustfmt + deadline-bound continue-client writes (#5080 review) - cargo fmt (lint check was cargo fmt --check). - Wrap the continue-exchange head/body `write_all`s in `tokio::time::timeout` so a stalled peer can't hang the request when `timeout` is set (the reads were already bounded). CodeRabbit review on #5123. * fix(http): resolve js_node_system_error_value dup + lib.rs size after main merge The merge of main (#5124, which independently defined js_node_system_error_value) left two definitions in error.rs and lib.rs over the 2000-line cap. Drop this PR's duplicate runtime definition (keep main's registry-based one) and move arm_expect_continue from lib.rs into continue_client.rs. * fix(http): defer 100-continue head flush to next tick (#5080 review) CodeRabbit review: arming the Expect:100-continue raw-socket exchange at construction froze the header snapshot too early, so a post-construction `req.setHeader('Expect','100-continue')` never armed the continue path and other late setHeader() calls were dropped from the on-wire head. Match Node's nextTick head flush: - `http.request`/overload now queue a `DeferredArmContinue` event instead of arming synchronously; it drains on the next event-loop tick, after the synchronous setHeader()/`.on('continue')` setup has run. - `end()` and `flushHeaders()` arm too (synchronous send boundaries), so a request ended synchronously still engages the handshake. `arm_expect_continue` is idempotent, so the first boundary wins. Verified: original repro still matches Node, and a late `setHeader('Expect','100-continue')` now fires the continue handshake (continue event / body continue:payload / closed). * fix(http): add test_async_shims so perry-ext-http lib test links (cargo-test) cargo-test (debug) failed to link the perry-ext-http lib test: undefined symbol: perry_ffi_spawn_blocking_with_reactor The crate uses perry-ffi's spawn_blocking_with_reactor, whose real impl lives in perry-stdlib (only linked into the final user program, not the lib test). perry-ext-net and perry-ext-http-server already carry a #[cfg(test)] test_async_shims.rs supplying synchronous shims for the perry_ffi_* async bridge; perry-ext-http was missing one (release builds dead-stripped the reference, hiding it locally — debug retains it). Add the same shim. --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
main'scargo-testis failing with a linker error, unrelated to any one feature:Root cause
PR #5078 (
1c9e3c6, "node:http client transport errors → real coded Error") added an extern declaration forjs_node_system_error_valueinperry-ffi/src/error.rsand a caller (system_error_value()→perry-ext-http'sclient_events.rs), but the runtime#[no_mangle]definition was never shipped. Any program/test that linksperry-ext-httptherefore fails at link time. This takes downcargo-test— e.g.issue_4903_listen_callback_deferred'slate_listening_listener_firesandlisten_callback_is_deferred_and_this_bound.Fix
Define
js_node_system_error_valueinperry-runtime/src/error.rs, mirroring the siblingjs_error_value_with_code:Errorfrom the message..code/.syscall/.errnointo the message-keyed side tables that the existingobject::field_get_setgetters already read back (register_error_code_pub/register_error_syscall/register_error_errno— the same mechanismfs/dns/processerrors use).code/syscallare interned to&'static str(reusingintern_error_code).#[used]anchor pins the symbol against the auto-optimize LTO dead-strip, matching the siblingKEEP_JS_ERROR_VALUE_WITH_CODE.No behavior change beyond making the already-intended
system_error_valuepath link and produce a Node-shaped system error (.message/.code/.syscall/.errno).Verification
cargo build -p perry-runtime -p perry-stdlib -p perry— clean.cargo test -p perry --test issue_4903_listen_callback_deferred— 2 passed; 0 failed (both previously failed at the link step).Context
Surfaced while babysitting CI on #5118 (perry/ui
toggleSetState); the failure was unrelated to that PR. This is the focused fix for themainregression.https://claude.ai/code/session_01HKXzNHuniuu33SAUrLSN2f
Generated by Claude Code
Summary by CodeRabbit