From f181ae3b1c52e2a2c4a9d2dfa26a5310bcafb185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Sun, 14 Jun 2026 12:22:34 +0200 Subject: [PATCH] fix(runtime): restore js_node_system_error_value dropped by #5112 PR #5112's error.rs refactor deleted the #[no_mangle] js_node_system_error_value (added by #5078) and its #[used] retention static, but perry-ffi/src/error.rs still declares it extern and calls it from system_error_value(). Any build that links perry-ffi's system_error_value (libperry_ext_http.a) fails to link: undefined reference to `js_node_system_error_value' Error: Linking failed This breaks ALL auto-optimize (default) http/https/http2 compilation at HEAD. It was masked by warm auto-opt caches and never linked in CI, so it merged green; a fresh --no-cache http compile reproduces it. Restored verbatim (no #5112 replacement exists) next to the sibling keepalive anchors; all helper signatures it calls (js_error_value_with_code, js_string_from_bytes, js_nanbox_string, js_object_set_field_by_name) are unchanged post-#5112. --- crates/perry-runtime/src/error.rs | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/crates/perry-runtime/src/error.rs b/crates/perry-runtime/src/error.rs index 6edd5adfd6..b53be3bfcf 100644 --- a/crates/perry-runtime/src/error.rs +++ b/crates/perry-runtime/src/error.rs @@ -352,6 +352,51 @@ static KEEP_JS_THROW_ERROR_WITH_CODE: unsafe extern "C" fn( i32, ) -> ! = js_throw_error_with_code; +/// Build a Node-style system `Error`: `.message` + `.code` (the message→code +/// side table the `.code` getter reads) plus `.syscall` (string) and `.errno` +/// (number) own properties. `perry-ext-http` calls this to surface client +/// transport failures (`ECONNREFUSED`, `ENOTFOUND`, `ECONNRESET`, …) as the +/// real coded `Error` objects Node hands to `request.on('error')`. +/// +/// # Safety +/// `msg_ptr`/`code_ptr`/`syscall_ptr` must each point to their stated number of +/// valid bytes, or be null with the matching length `0`. +#[no_mangle] +pub unsafe extern "C" fn js_node_system_error_value( + msg_ptr: *const u8, + msg_len: usize, + code_ptr: *const u8, + code_len: usize, + syscall_ptr: *const u8, + syscall_len: usize, + errno: f64, +) -> f64 { + let err_val = js_error_value_with_code(msg_ptr, msg_len, code_ptr, code_len, 0); + let obj = err_val.to_bits() as *mut crate::object::ObjectHeader; + if !syscall_ptr.is_null() && syscall_len > 0 { + let key = js_string_from_bytes(b"syscall".as_ptr(), 7) as *const StringHeader; + let sval_str = js_string_from_bytes(syscall_ptr, syscall_len as u32); + let sval = crate::value::js_nanbox_string(sval_str as i64); + crate::object::js_object_set_field_by_name(obj, key, sval); + } + { + let key = js_string_from_bytes(b"errno".as_ptr(), 5) as *const StringHeader; + crate::object::js_object_set_field_by_name(obj, key, errno); + } + err_val +} + +#[used] +static KEEP_JS_NODE_SYSTEM_ERROR_VALUE: unsafe extern "C" fn( + *const u8, + usize, + *const u8, + usize, + *const u8, + usize, + f64, +) -> f64 = js_node_system_error_value; + /// Throw `ERR_PERRY_UNIMPLEMENTED` for a registered-but-stub API. Used /// by the stub-elimination epic's strict mode (#4918/#4919): a runtime /// stub calls [`crate::stub_diag::perry_runtime_stub`] to warn, then —