From 9b6884e214beb93873f21dd76afe49e42f3f25df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Mon, 7 Sep 2026 19:44:19 +0200 Subject: [PATCH 1/2] perf: add receiver representation ledgers Instrument headerless receiver producers and dynamic receiver funnels behind the opt-in PERRY_RECEIVER_REPR_DIAG sink. Add explicit native return storage kinds while retaining the existing pointer-boxing lowering, plus checked provider inventory and fail-capable fixtures. Claude-Session: https://claude.ai/code/session_011dhBmdn4vGgNibjo3oZqTo --- .github/workflows/native-result-ledger.yml | 34 ++ crates/perry-codegen/src/lib.rs | 9 +- .../src/lower_call/native_module_dispatch.rs | 12 +- .../lower_call/native_table/async_decimal.rs | 34 +- .../src/lower_call/native_table/bun.rs | 8 +- .../src/lower_call/native_table/databases.rs | 174 +++--- .../src/lower_call/native_table/extras.rs | 2 +- .../src/lower_call/native_table/fastify.rs | 18 +- .../lower_call/native_table/http_client.rs | 46 +- .../src/lower_call/native_table/http_http2.rs | 10 +- .../lower_call/native_table/http_server.rs | 40 +- .../src/lower_call/native_table/media.rs | 104 ++-- .../src/lower_call/native_table/mod.rs | 25 +- .../native_table/net_classes_state.rs | 8 +- .../src/lower_call/native_table/net_events.rs | 106 ++-- .../native_table/node_core/dgram_fs_os.rs | 2 +- .../native_table/node_core/util_buffer.rs | 8 +- .../native_table/node_core_process.rs | 6 +- .../lower_call/native_table/node_domain.rs | 14 +- .../src/lower_call/native_table/node_misc.rs | 32 +- .../lower_call/native_table/thread_lodash.rs | 24 +- .../src/lower_call/native_table/tls_events.rs | 22 +- .../src/lower_call/native_table/tui.rs | 50 +- .../src/lower_call/native_table/undici.rs | 6 +- .../lower_call/native_table/utils_crypto.rs | 24 +- .../src/lower_call/native_table/ws_events.rs | 8 +- crates/perry-runtime/src/async_hooks.rs | 18 + crates/perry-runtime/src/buffer/header.rs | 15 + crates/perry-runtime/src/buffer/mod.rs | 10 +- crates/perry-runtime/src/hot_diag.rs | 16 +- .../src/hot_diag/receiver_repr.rs | 509 ++++++++++++++++++ .../field_get_set/get_field_by_name_tail.rs | 4 + .../src/object/field_get_set/ic_miss.rs | 3 + crates/perry-runtime/src/object/mod.rs | 2 +- .../src/object/native_call_method.rs | 62 +++ .../native_call_method/primitive_methods.rs | 3 + crates/perry-runtime/src/object/null_stub.rs | 10 + .../src/object/prototype_chain.rs | 3 + crates/perry-runtime/src/proxy.rs | 5 + crates/perry-runtime/src/shared_sab.rs | 3 + crates/perry-runtime/src/symbol.rs | 10 + .../perry-runtime/src/symbol/constructors.rs | 5 + crates/perry-runtime/src/text.rs | 6 + crates/perry-runtime/src/timer.rs | 3 + crates/perry-runtime/src/tui/hooks.rs | 16 + crates/perry-runtime/src/tui/mod.rs | 6 + crates/perry-runtime/src/tui/state.rs | 7 + crates/perry-runtime/src/tui/tree.rs | 7 + crates/perry-runtime/src/value/addr_class.rs | 15 + crates/perry-stdlib/src/common/handle.rs | 10 + crates/perry-stdlib/src/fetch/mod.rs | 5 + crates/perry-stdlib/src/zlib.rs | 5 + scripts/native_result_ledger.py | 235 ++++++++ scripts/native_result_ledger.tsv | 323 +++++++++++ 54 files changed, 1751 insertions(+), 391 deletions(-) create mode 100644 .github/workflows/native-result-ledger.yml create mode 100644 crates/perry-runtime/src/hot_diag/receiver_repr.rs create mode 100644 scripts/native_result_ledger.py create mode 100644 scripts/native_result_ledger.tsv diff --git a/.github/workflows/native-result-ledger.yml b/.github/workflows/native-result-ledger.yml new file mode 100644 index 0000000000..51c4ac2653 --- /dev/null +++ b/.github/workflows/native-result-ledger.yml @@ -0,0 +1,34 @@ +name: Native Result Ledger + +on: + pull_request: + paths: + - "crates/perry-codegen/src/lower_call/native_table/**" + - "scripts/native_result_ledger.py" + - "scripts/native_result_ledger.tsv" + - ".github/workflows/native-result-ledger.yml" + push: + branches: [main] + paths: + - "crates/perry-codegen/src/lower_call/native_table/**" + - "scripts/native_result_ledger.py" + - "scripts/native_result_ledger.tsv" + - ".github/workflows/native-result-ledger.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: native-result-ledger-${{ github.event_name }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Prove and run the typed-result inventory + run: | + python3 scripts/native_result_ledger.py --self-test + python3 scripts/native_result_ledger.py diff --git a/crates/perry-codegen/src/lib.rs b/crates/perry-codegen/src/lib.rs index 3e3ea4fd81..6cf9c09a6d 100644 --- a/crates/perry-codegen/src/lib.rs +++ b/crates/perry-codegen/src/lib.rs @@ -143,7 +143,7 @@ pub mod expr_shadow_layout { /// check (#463) miss a real implementation. /// /// Arg / return *kinds* are reported as opaque strings (`"NA_STR"`, -/// `"NR_PTR"`, ...) so the consistency test can compare against the +/// `"NR_GCPTR"`, ...) so the consistency test can compare against the /// manifest's `params` / `returns` types without `perry-api-manifest` /// having to depend on `perry-codegen`'s internal enums (#512). pub struct NativeMethodRef { @@ -162,8 +162,11 @@ pub struct NativeMethodRef { /// `"NA_VARARGS"`, `"NA_JSON"`. Used by `perry-api-manifest`'s /// param-count drift test (#512). pub arg_kinds: &'static [&'static str], - /// Return-kind tag. One of `"NR_PTR"`, `"NR_PROMISE"`, `"NR_STR"`, - /// `"NR_BIGINT"`, `"NR_F64"`, `"NR_I32"`, `"NR_VOID"`. + /// Return-kind tag. Pointer-boxed results explicitly distinguish + /// `"NR_GCPTR"`, `"NR_NULLABLE_GCPTR"`, `"NR_HANDLE_ID"`, + /// `"NR_FOREIGN_PTR"`, and `"NR_JS_VALUE"`; the existing + /// `"NR_PROMISE"`, `"NR_STR"`, `"NR_BIGINT"`, `"NR_F64"`, + /// `"NR_I32"`, and `"NR_VOID"` tags are unchanged. pub ret_kind: &'static str, } diff --git a/crates/perry-codegen/src/lower_call/native_module_dispatch.rs b/crates/perry-codegen/src/lower_call/native_module_dispatch.rs index d84dcccad0..4583fd834e 100644 --- a/crates/perry-codegen/src/lower_call/native_module_dispatch.rs +++ b/crates/perry-codegen/src/lower_call/native_module_dispatch.rs @@ -190,7 +190,11 @@ pub fn lower_native_module_dispatch( // Determine return type for the declare let ret_type = match sig.ret { - NativeRetKind::Ptr + NativeRetKind::GcPtr + | NativeRetKind::NullableGcPtr + | NativeRetKind::HandleId + | NativeRetKind::ForeignPtr + | NativeRetKind::JsValue | NativeRetKind::Promise | NativeRetKind::Str | NativeRetKind::ObjFromJsonStr @@ -207,7 +211,11 @@ pub fn lower_native_module_dispatch( llvm_args.iter().map(|(t, s)| (*t, s.as_str())).collect(); match sig.ret { - NativeRetKind::Ptr => { + NativeRetKind::GcPtr + | NativeRetKind::NullableGcPtr + | NativeRetKind::HandleId + | NativeRetKind::ForeignPtr + | NativeRetKind::JsValue => { let blk = ctx.block(); let raw = blk.call(I64, sig.runtime, &arg_slices); let lowered = LoweredValue::native_handle(raw.clone()); diff --git a/crates/perry-codegen/src/lower_call/native_table/async_decimal.rs b/crates/perry-codegen/src/lower_call/native_table/async_decimal.rs index e0fcea9442..c016b0967e 100644 --- a/crates/perry-codegen/src/lower_call/native_table/async_decimal.rs +++ b/crates/perry-codegen/src/lower_call/native_table/async_decimal.rs @@ -89,7 +89,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_async_hooks_create_hook", args: &[NA_F64], - ret: NR_PTR, + ret: NR_FOREIGN_PTR, }, NativeModSig { module: "async_hooks", @@ -125,7 +125,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: Some("AsyncHook"), runtime: "js_async_hook_enable", args: &[], - ret: NR_PTR, + ret: NR_FOREIGN_PTR, }, NativeModSig { module: "async_hooks", @@ -134,7 +134,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: Some("AsyncHook"), runtime: "js_async_hook_disable", args: &[], - ret: NR_PTR, + ret: NR_FOREIGN_PTR, }, NativeModSig { module: "async_hooks", @@ -161,7 +161,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: Some("AsyncResource"), runtime: "js_async_resource_emit_destroy", args: &[], - ret: NR_PTR, + ret: NR_FOREIGN_PTR, }, NativeModSig { module: "async_hooks", @@ -179,7 +179,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: Some("AsyncResource"), runtime: "js_async_resource_bind", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_NULLABLE_GCPTR, }, // ========== decimal.js (arbitrary-precision math) ========== // `new Decimal(value)` is dispatched by `lower_builtin_new` (calls @@ -194,7 +194,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_plus_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -203,7 +203,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_minus_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -212,7 +212,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_times_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -221,7 +221,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_div_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -230,7 +230,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_mod_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -239,7 +239,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_pow", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -248,7 +248,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_sqrt", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -257,7 +257,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_abs", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -266,7 +266,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_neg", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -275,7 +275,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_round", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -284,7 +284,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_floor", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "decimal.js", @@ -293,7 +293,7 @@ pub(super) const ASYNC_DECIMAL_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_decimal_ceil", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Formatting — return strings (NR_STR NaN-boxes the *StringHeader). NativeModSig { diff --git a/crates/perry-codegen/src/lower_call/native_table/bun.rs b/crates/perry-codegen/src/lower_call/native_table/bun.rs index 5ae17ea8c0..772555b0cb 100644 --- a/crates/perry-codegen/src/lower_call/native_table/bun.rs +++ b/crates/perry-codegen/src/lower_call/native_table/bun.rs @@ -43,7 +43,7 @@ pub(crate) const BUN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bun_transpiler_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun", @@ -52,7 +52,7 @@ pub(crate) const BUN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bun_tcp_listen", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun", @@ -63,7 +63,7 @@ pub(crate) const BUN_ROWS: &[NativeModSig] = &[ // handle, reusing the same event-loop pump as node:http. runtime: "js_bun_serve", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun", @@ -72,7 +72,7 @@ pub(crate) const BUN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bun_build", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun", diff --git a/crates/perry-codegen/src/lower_call/native_table/databases.rs b/crates/perry-codegen/src/lower_call/native_table/databases.rs index 5c169be374..ebad043faa 100644 --- a/crates/perry-codegen/src/lower_call/native_table/databases.rs +++ b/crates/perry-codegen/src/lower_call/native_table/databases.rs @@ -9,7 +9,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_create_connection", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -18,7 +18,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_create_pool", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "mysql2/promise", @@ -27,7 +27,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_create_connection", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -36,7 +36,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_create_pool", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // mysql2 Pool-specific methods (class_filter: Some("Pool")) NativeModSig { @@ -46,7 +46,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -55,7 +55,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -64,7 +64,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -73,7 +73,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -82,7 +82,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -91,7 +91,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_mysql2_pool_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // mysql2 PoolConnection-specific methods NativeModSig { @@ -101,7 +101,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("PoolConnection"), runtime: "js_mysql2_pool_connection_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -110,7 +110,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("PoolConnection"), runtime: "js_mysql2_pool_connection_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -119,7 +119,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("PoolConnection"), runtime: "js_mysql2_pool_connection_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -128,7 +128,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("PoolConnection"), runtime: "js_mysql2_pool_connection_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // mysql2 generic instance methods (Connection fallback, class_filter: None) NativeModSig { @@ -138,7 +138,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -147,7 +147,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -156,7 +156,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -165,7 +165,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_pool_get_connection", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -183,7 +183,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_begin_transaction", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -192,7 +192,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_commit", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2", @@ -201,7 +201,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_rollback", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -210,7 +210,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_query", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -219,7 +219,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_execute", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -228,7 +228,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -237,7 +237,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_pool_get_connection", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -255,7 +255,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_begin_transaction", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -264,7 +264,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_commit", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mysql2/promise", @@ -273,7 +273,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mysql2_connection_rollback", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== PostgreSQL (pg) ========== // `new Client(config)` and `new Pool(config)` are dispatched by @@ -287,7 +287,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_pg_connect", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "pg", @@ -296,7 +296,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_pg_create_pool", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // `client.connect()` — async, opens the TCP connection on a handle that // `new Client(config)` previously created in the pre-connect state. @@ -311,7 +311,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Client"), runtime: "js_pg_client_connect", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // Pool-specific query/end — different runtime fns from the Client paths. // Pre-existing dispatch was unfiltered and routed both Pool and Client @@ -327,7 +327,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_pg_pool_query", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "pg", @@ -336,7 +336,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Pool"), runtime: "js_pg_pool_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "pg", @@ -345,7 +345,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_pg_client_query", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "pg", @@ -354,7 +354,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_pg_client_end", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== ioredis ========== // NB: every row was previously emitting `js_redis_*` symbols which don't @@ -374,7 +374,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ // js_ioredis_new ignores its arg and reads env vars — same behavior. runtime: "js_ioredis_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "ioredis", @@ -383,7 +383,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_set", args: &[NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -392,7 +392,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_get", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -401,7 +401,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_del", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -410,7 +410,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_exists", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -419,7 +419,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_incr", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -428,7 +428,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_decr", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -437,7 +437,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_expire", args: &[NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ioredis", @@ -446,7 +446,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_quit", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // Issue #605 — npm `redis`'s `client.connect()` is async. ioredis // auto-connects in `new Redis()` and exposes `connect()` as a no-op @@ -471,7 +471,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ioredis_quit", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== MongoDB ========== // `new MongoClient(uri)` is dispatched by `lower_builtin_new` (sync ctor @@ -512,7 +512,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_client_db", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "mongodb", @@ -521,7 +521,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_db_collection", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `_value` wrapper variants — every collection method that accepts an // object/filter arg goes through a wrapper that JSON-stringifies the @@ -537,7 +537,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_insert_one_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -546,7 +546,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_insert_many_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -555,7 +555,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_find_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -564,7 +564,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_find_one_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -573,7 +573,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_update_one_value", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -582,7 +582,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_update_many_value", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -591,7 +591,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_delete_one_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -600,7 +600,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_delete_many_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "mongodb", @@ -609,7 +609,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_collection_count_value", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // aggregate / createIndex / toArray runtime functions don't exist in // perry-stdlib yet — listed as commented-out so the dispatch table @@ -627,7 +627,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_mongodb_client_close", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== better-sqlite3 ========== NativeModSig { @@ -637,7 +637,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sqlite_open", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "better-sqlite3", @@ -646,7 +646,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sqlite_prepare", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // stmt.run/get/all/iterate take JS-side variadic params. The runtime // consumes them as a single `*const ArrayHeader`, so VarArgsAsArray @@ -663,7 +663,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sqlite_stmt_run", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "better-sqlite3", @@ -681,7 +681,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sqlite_stmt_all", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, // `stmt.raw([toggle])` — flips the statement into raw mode and // returns the same handle so `stmt.raw().all(...)` chains. drizzle's @@ -697,7 +697,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sqlite_stmt_raw", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "better-sqlite3", @@ -725,7 +725,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bun_sqlite_database_call", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun:sqlite", @@ -734,7 +734,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Database"), runtime: "js_bun_sqlite_database_query", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun:sqlite", @@ -743,7 +743,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Database"), runtime: "js_bun_sqlite_database_query", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "bun:sqlite", @@ -752,7 +752,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Database"), runtime: "js_bun_sqlite_database_run", args: &[NA_F64, NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -770,7 +770,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Database"), runtime: "js_node_sqlite_database_sync_serialize", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -788,7 +788,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Database"), runtime: "js_bun_sqlite_database_transaction", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -797,7 +797,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Statement"), runtime: "js_node_sqlite_statement_sync_run", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -815,7 +815,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Statement"), runtime: "js_node_sqlite_statement_sync_all", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -824,7 +824,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Statement"), runtime: "js_bun_sqlite_statement_values", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bun:sqlite", @@ -852,7 +852,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_database_sync_call", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -861,7 +861,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_session_call", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -870,7 +870,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_statement_sync_call", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -933,7 +933,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_database_sync_prepare", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -942,7 +942,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_database_sync_serialize", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -996,7 +996,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("DatabaseSync"), runtime: "js_node_sqlite_database_sync_create_tag_store", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -1005,7 +1005,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("DatabaseSync"), runtime: "js_node_sqlite_database_sync_create_session", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -1068,7 +1068,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_database_sync_limits", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -1077,7 +1077,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Session"), runtime: "js_node_sqlite_session_changeset", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1086,7 +1086,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("Session"), runtime: "js_node_sqlite_session_patchset", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1122,7 +1122,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("SQLTagStore"), runtime: "js_node_sqlite_sql_tag_store_run", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1140,7 +1140,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("SQLTagStore"), runtime: "js_node_sqlite_sql_tag_store_all", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1185,7 +1185,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: Some("SQLTagStore"), runtime: "js_node_sqlite_sql_tag_store_db", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sqlite", @@ -1194,7 +1194,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_statement_sync_run", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1212,7 +1212,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_statement_sync_all", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", @@ -1230,7 +1230,7 @@ pub(super) const DATABASES_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_sqlite_statement_sync_columns", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sqlite", diff --git a/crates/perry-codegen/src/lower_call/native_table/extras.rs b/crates/perry-codegen/src/lower_call/native_table/extras.rs index 7445fa4fcd..e9d53bd11d 100644 --- a/crates/perry-codegen/src/lower_call/native_table/extras.rs +++ b/crates/perry-codegen/src/lower_call/native_table/extras.rs @@ -317,7 +317,7 @@ pub(super) const EXTRAS_ROWS: &[NativeModSig] = &[ class_filter: Some("Wallet"), runtime: "js_ethers_wallet_create_random", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, // ========== #2875 DisposableStack / AsyncDisposableStack ========== // `new DisposableStack()` / `new AsyncDisposableStack()` are dispatched diff --git a/crates/perry-codegen/src/lower_call/native_table/fastify.rs b/crates/perry-codegen/src/lower_call/native_table/fastify.rs index 1d65f6e26d..23980b36db 100644 --- a/crates/perry-codegen/src/lower_call/native_table/fastify.rs +++ b/crates/perry-codegen/src/lower_call/native_table/fastify.rs @@ -9,7 +9,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_create_with_opts", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "fastify", @@ -165,7 +165,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_app_server", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // #1113 — `app.server.on(event, cb)`. `app.server` returns the // FastifyApp handle (pointer-tagged), so `.on(…)` lowers as a @@ -250,7 +250,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_req_headers", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "fastify", @@ -287,7 +287,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_reply_status", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `reply.code(N)` is an alias for `reply.status(N)` in npm Fastify. Without // this row, `reply.code(201)` silently no-op'd and the HTTP status stayed 200. @@ -298,7 +298,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_reply_status", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "fastify", @@ -315,7 +315,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ // user code at it. CORS hooks, Cache-Control, and content-type // overrides all evaporated. // - // `ret: NR_PTR` is critical — the Rust impl returns `Handle` (i64). + // `ret: NR_HANDLE_ID` is critical — the Rust impl returns `Handle` (i64). // Previously `NR_F64` caused chained `.header(...).send(...)` to read // an uninitialized XMM0/D0 register as the receiver, producing // `(number).send is not a function` errors (#1048). @@ -331,11 +331,11 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: Some("Reply"), runtime: "js_fastify_reply_header", args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `reply.type(value)` — Fastify alias for setting `content-type`. // Routes to `js_fastify_reply_type` (thin wrapper over reply_header). - // `ret: NR_PTR` for the same reason as `reply.header` above (#1048). + // `ret: NR_HANDLE_ID` for the same reason as `reply.header` above (#1048). NativeModSig { module: "fastify", has_receiver: true, @@ -343,7 +343,7 @@ pub(super) const FASTIFY_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_fastify_reply_type", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Fastify context methods (Hono-style) NativeModSig { diff --git a/crates/perry-codegen/src/lower_call/native_table/http_client.rs b/crates/perry-codegen/src/lower_call/native_table/http_client.rs index eb43c085f1..b891376d5b 100644 --- a/crates/perry-codegen/src/lower_call/native_table/http_client.rs +++ b/crates/perry-codegen/src/lower_call/native_table/http_client.rs @@ -44,7 +44,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_http_request_overload", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -53,7 +53,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_http_get_overload", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -62,7 +62,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_https_request_overload", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -71,7 +71,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_https_get_overload", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // #3712 — module-level header-validation / parser-proxy helpers. Runtime // impls live in `crates/perry-runtime/src/object/native_module_dispatch.rs`. @@ -134,7 +134,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("ClientRequest"), runtime: "js_http_on", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -143,7 +143,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("ClientRequest"), runtime: "js_http_once", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -156,7 +156,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ // `(encoding?, callback?)` tail. runtime: "js_http_client_request_end_full", args: &[NA_F64, NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -180,7 +180,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("ClientRequest"), runtime: "js_http_set_header", args: &[NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -192,7 +192,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ // `req.setTimeout(n, cb)` on a never-responding server hung forever). runtime: "js_http_set_timeout_full", args: &[NA_F64, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -244,7 +244,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ "destroy", "js_http_client_request_destroy", &[NA_F64], - NR_PTR, + NR_HANDLE_ID, ), cr( "flushHeaders", @@ -373,7 +373,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_http_agent_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -382,7 +382,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_https_agent_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Agent instance methods. Most are chainable no-ops today — Perry // doesn't pool sockets, but Node's test suite asserts the methods @@ -407,7 +407,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_destroy", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -416,7 +416,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -425,7 +425,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Property accessors as `__get_` synthetic methods. The HIR // rewrites bare `agent.maxSockets` reads to `agent.__get_maxSockets()` @@ -583,7 +583,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_sockets", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -592,7 +592,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_sockets", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -601,7 +601,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_free_sockets", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -610,7 +610,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_free_sockets", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -619,7 +619,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_requests", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -628,7 +628,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_requests", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "http", @@ -718,7 +718,7 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_create_connection", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -727,6 +727,6 @@ pub(super) const HTTP_CLIENT_ROWS: &[NativeModSig] = &[ class_filter: Some("Agent"), runtime: "js_http_agent_create_socket", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, ]; diff --git a/crates/perry-codegen/src/lower_call/native_table/http_http2.rs b/crates/perry-codegen/src/lower_call/native_table/http_http2.rs index 78265e64dc..005232d6c3 100644 --- a/crates/perry-codegen/src/lower_call/native_table/http_http2.rs +++ b/crates/perry-codegen/src/lower_call/native_table/http_http2.rs @@ -9,7 +9,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_http2_create_server", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http2", @@ -18,7 +18,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_http2_create_secure_server", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http2", @@ -27,7 +27,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_http2_connect", args: &[NA_F64, NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http2", @@ -38,7 +38,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[ // Variadic listen() overloads — see the http `listen` row. Issue #2041. // Returns the server handle for chainability (#2129). args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http2", @@ -88,7 +88,7 @@ pub(super) const HTTP_HTTP2_ROWS: &[NativeModSig] = &[ // NA_JSV: pass the settings object's raw NaN-boxed bits (the runtime // JSON-stringifies it); NR_PTR: return value is a Buffer pointer. args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "http2", diff --git a/crates/perry-codegen/src/lower_call/native_table/http_server.rs b/crates/perry-codegen/src/lower_call/native_table/http_server.rs index dc044db30a..f32c3f8d47 100644 --- a/crates/perry-codegen/src/lower_call/native_table/http_server.rs +++ b/crates/perry-codegen/src/lower_call/native_table/http_server.rs @@ -14,7 +14,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_http_create_server_with_options", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `http.Server(handler)` is Node's callable-constructor alias for // `http.createServer` (works with or without `new`). #2132. @@ -26,7 +26,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_http_create_server_with_options", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // HttpServer instance methods (class_filter: HttpServer) NativeModSig { @@ -48,7 +48,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ // this was NR_VOID and chained sites broke at runtime with // `undefined.on is not a function`. args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -335,7 +335,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpServer"), runtime: "js_node_http_server_set_timeout_method", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `server.ref()` / `server.unref()` — EventEmitter chainables that // return `this`. Without these rows they fell through to a generic @@ -352,7 +352,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpServer"), runtime: "js_node_http_server_ref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -361,7 +361,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpServer"), runtime: "js_node_http_server_unref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // IncomingMessage instance methods NativeModSig { @@ -405,7 +405,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ // yielding `undefined`/a raw number. runtime: "js_node_http_im_pause_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -418,7 +418,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ // `(number|undefined).on`. runtime: "js_node_http_im_resume_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -445,7 +445,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("IncomingMessage"), runtime: "js_http_incoming_message_set_encoding", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -454,7 +454,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("IncomingMessage"), runtime: "js_node_http_im_set_timeout", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // ServerResponse instance methods NativeModSig { @@ -467,7 +467,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ // (e.g. Set-Cookie) are detected and emitted as one wire line per // element instead of a single comma-joined / JSON-stringified line. args: &[NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -521,7 +521,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("ServerResponse"), runtime: "js_node_http_res_append_header", args: &[NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -530,7 +530,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("ServerResponse"), runtime: "js_node_http_res_set_headers", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -616,7 +616,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("ServerResponse"), runtime: "js_node_http_res_set_timeout", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "http", @@ -1005,7 +1005,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_https_create_server", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `https.Server(options, handler)` is Node's callable-constructor // alias for `https.createServer` (works with or without `new`). #2132. @@ -1016,7 +1016,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_https_create_server", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -1027,7 +1027,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ // Variadic listen() overloads — see the http `listen` row. Issue #2041. // Returns the server handle for chainability (#2129). args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -1101,7 +1101,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpsServer"), runtime: "js_node_https_server_ref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -1110,7 +1110,7 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpsServer"), runtime: "js_node_https_server_unref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "https", @@ -1317,6 +1317,6 @@ pub(super) const HTTP_SERVER_ROWS: &[NativeModSig] = &[ class_filter: Some("HttpsServer"), runtime: "js_node_https_server_set_timeout_method", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, ]; diff --git a/crates/perry-codegen/src/lower_call/native_table/media.rs b/crates/perry-codegen/src/lower_call/native_table/media.rs index 44e1f12310..1853542479 100644 --- a/crates/perry-codegen/src/lower_call/native_table/media.rs +++ b/crates/perry-codegen/src/lower_call/native_table/media.rs @@ -15,7 +15,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_from_input", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -24,7 +24,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_from_input", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -33,7 +33,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_resize", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -42,7 +42,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_rotate", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -51,7 +51,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_flip", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -60,7 +60,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_flop", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -69,7 +69,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_grayscale", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -78,7 +78,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_blur", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -87,7 +87,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_sharpen", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `.extract({ left, top, width, height })` — the options object is passed // as a NaN-boxed value (NA_F64 slot); `js_sharp_extract` reads its fields. @@ -98,7 +98,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_extract", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -107,7 +107,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_auto_orient", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `.extend({ top, bottom, left, right, background })` — options object. NativeModSig { @@ -117,7 +117,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_extend", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -126,7 +126,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_trim", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `.composite([{ input, top, left }, …])` — array of layer objects, passed // as a NaN-boxed pointer (NA_F64 slot); `js_sharp_composite` walks it. @@ -137,7 +137,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_composite", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -146,7 +146,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_jpeg", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -155,7 +155,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_png", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -164,7 +164,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_webp", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -173,7 +173,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_avif", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "sharp", @@ -182,7 +182,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_to_file", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sharp", @@ -191,7 +191,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_to_buffer", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sharp", @@ -200,7 +200,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_sharp_metadata", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "sharp", @@ -229,7 +229,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_load", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -238,7 +238,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_select", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -283,7 +283,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_first", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -292,7 +292,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_last", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -301,7 +301,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_eq", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -310,7 +310,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_find", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -319,7 +319,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_children", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -328,7 +328,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cheerio_selection_parent", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cheerio", @@ -350,7 +350,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ // codec extracts the buffer/string pointer itself; the options object // carries `{ level }`. args: &[NA_JSV, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -361,7 +361,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ // #2935: data as raw NaN-box bits so the codec unboxes the buffer // pointer itself (a Buffer/string both decompress correctly). args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -371,7 +371,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ runtime: "js_zlib_deflate_sync", // #2935: see gzipSync above. args: &[NA_JSV, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -381,7 +381,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ runtime: "js_zlib_inflate_sync", // #2935: see gunzipSync above. args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -455,7 +455,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_deflate_raw_sync", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -464,7 +464,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_inflate_raw_sync", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -473,7 +473,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_unzip_sync", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -494,7 +494,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_brotli_compress_sync", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -503,7 +503,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_brotli_decompress_sync", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -530,7 +530,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_zstd_compress_sync", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -539,7 +539,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_zstd_decompress_sync", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "zlib", @@ -571,7 +571,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_gzip", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -580,7 +580,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_gunzip", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -589,7 +589,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_deflate", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -598,7 +598,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_inflate", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -607,7 +607,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_deflate_raw", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -616,7 +616,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_inflate_raw", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -625,7 +625,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_unzip", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -634,7 +634,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_brotli_compress", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `zlib.createBrotliDecompress(options?)` — now a real Transform-stream // handle (previously a feature-check Buffer stub; axios's @@ -646,7 +646,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_brotli_decompress", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -655,7 +655,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_zstd_compress", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "zlib", @@ -664,7 +664,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_zlib_create_zstd_decompress", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // ========== cron ========== // schedule() returns a Handle (i64) → NR_PTR. Instance methods take Handle (i64). @@ -690,7 +690,7 @@ pub(super) const MEDIA_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_cron_schedule", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "cron", diff --git a/crates/perry-codegen/src/lower_call/native_table/mod.rs b/crates/perry-codegen/src/lower_call/native_table/mod.rs index 55daa6711b..18cfadf122 100644 --- a/crates/perry-codegen/src/lower_call/native_table/mod.rs +++ b/crates/perry-codegen/src/lower_call/native_table/mod.rs @@ -80,8 +80,17 @@ pub(super) enum NativeArgKind { /// What the runtime function returns. #[derive(Copy, Clone, Debug)] pub(super) enum NativeRetKind { - /// Returns i64 handle → NaN-box as POINTER. - Ptr, + /// Returns a non-null Perry allocation with a readable `GcHeader`. + GcPtr, + /// Returns a Perry allocation, with zero carrying the provider's existing + /// null/failure policy. + NullableGcPtr, + /// Returns an integer registry id or provider sentinel. + HandleId, + /// Returns a headerless native address (for example an async-hook box). + ForeignPtr, + /// Returns raw NaN-boxed JS value bits in an integer ABI slot. + JsValue, /// Returns i64 promise handle → NaN-box as POINTER, but record the async /// boundary separately from generic native handles. Promise, @@ -136,7 +145,11 @@ pub(super) const NA_STR: NativeArgKind = NativeArgKind::StrPtr; pub(super) const NA_PTR: NativeArgKind = NativeArgKind::PtrI64; pub(super) const NA_JSV: NativeArgKind = NativeArgKind::JsvalI64; pub(super) const NA_VARARGS: NativeArgKind = NativeArgKind::VarArgsAsArray; -pub(super) const NR_PTR: NativeRetKind = NativeRetKind::Ptr; +pub(super) const NR_GCPTR: NativeRetKind = NativeRetKind::GcPtr; +pub(super) const NR_NULLABLE_GCPTR: NativeRetKind = NativeRetKind::NullableGcPtr; +pub(super) const NR_HANDLE_ID: NativeRetKind = NativeRetKind::HandleId; +pub(super) const NR_FOREIGN_PTR: NativeRetKind = NativeRetKind::ForeignPtr; +pub(super) const NR_JS_VALUE: NativeRetKind = NativeRetKind::JsValue; pub(super) const NR_PROMISE: NativeRetKind = NativeRetKind::Promise; pub(super) const NR_STR: NativeRetKind = NativeRetKind::Str; pub(super) const NR_OBJ_FROM_JSON_STR: NativeRetKind = NativeRetKind::ObjFromJsonStr; @@ -255,7 +268,11 @@ fn arg_kind_tag(a: &NativeArgKind) -> &'static str { fn ret_kind_tag(r: &NativeRetKind) -> &'static str { match r { - NativeRetKind::Ptr => "NR_PTR", + NativeRetKind::GcPtr => "NR_GCPTR", + NativeRetKind::NullableGcPtr => "NR_NULLABLE_GCPTR", + NativeRetKind::HandleId => "NR_HANDLE_ID", + NativeRetKind::ForeignPtr => "NR_FOREIGN_PTR", + NativeRetKind::JsValue => "NR_JS_VALUE", NativeRetKind::Promise => "NR_PROMISE", NativeRetKind::Str => "NR_STR", NativeRetKind::ObjFromJsonStr => "NR_OBJ_FROM_JSON_STR", diff --git a/crates/perry-codegen/src/lower_call/native_table/net_classes_state.rs b/crates/perry-codegen/src/lower_call/native_table/net_classes_state.rs index 06817aa5cc..d3c6148d3c 100644 --- a/crates/perry-codegen/src/lower_call/native_table/net_classes_state.rs +++ b/crates/perry-codegen/src/lower_call/native_table/net_classes_state.rs @@ -8,7 +8,7 @@ pub(super) const NET_CLASSES_STATE_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_net_block_list_new", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -17,7 +17,7 @@ pub(super) const NET_CLASSES_STATE_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_net_socket_address_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -53,7 +53,7 @@ pub(super) const NET_CLASSES_STATE_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_set_type_of_service", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -116,7 +116,7 @@ pub(super) const NET_CLASSES_STATE_ROWS: &[NativeModSig] = &[ class_filter: Some("BlockList"), runtime: "js_net_block_list_rules", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "net", diff --git a/crates/perry-codegen/src/lower_call/native_table/net_events.rs b/crates/perry-codegen/src/lower_call/native_table/net_events.rs index 07d6b9bd3e..c885104899 100644 --- a/crates/perry-codegen/src/lower_call/native_table/net_events.rs +++ b/crates/perry-codegen/src/lower_call/native_table/net_events.rs @@ -24,7 +24,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ext_net_socket_connect", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Factory alias: `net.connect(...)` is the spec'd alias for // `net.createConnection(...)`. Pre-issue-#422 only the @@ -39,7 +39,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ext_net_socket_connect", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `net.createServer` and callable `net.Server` are normally rewritten to // `Expr::NetCreateServer` so the one-arg listener shorthand is preserved. @@ -52,7 +52,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ext_net_create_server", args: &[NA_PTR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -61,7 +61,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ext_net_create_server", args: &[NA_PTR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Constructor: `new net.Socket()` allocates an unconnected socket // handle whose TCP connection is deferred until `sock.connect(port, @@ -78,7 +78,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_net_socket_alloc", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -236,7 +236,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -245,7 +245,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -256,7 +256,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ // callback is passed through but ignored. Returns the socket handle. runtime: "js_net_socket_set_timeout", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -266,7 +266,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ // #4973: real setEncoding — switches 'data' delivery to strings. runtime: "js_net_socket_set_encoding", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -275,7 +275,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -284,7 +284,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -293,7 +293,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_ref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -302,7 +302,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_unref", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -311,7 +311,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -320,7 +320,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -329,7 +329,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Issue #2131 — `socket.address()` returns the local bind address // (`{ address, family, port }`). Captured at connect/accept time and @@ -504,7 +504,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ // listeners on sockets owned by perry-ext-net. runtime: "js_ext_net_socket_once", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -522,7 +522,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_remove_listener", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -531,7 +531,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_remove_listener", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -540,7 +540,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_remove_all_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -575,7 +575,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "net", @@ -584,7 +584,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_raw_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, // Issue #2131 — `socket.resetAndDestroy()` is the "send RST then // destroy" variant; we alias to `destroy()` (FIN-then-close) for @@ -597,7 +597,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Socket"), runtime: "js_net_socket_reset_and_destroy", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // upgradeToTLS returns a Promise (handle pointer) — await it to wait // for the TLS handshake before sending anything over the upgraded stream. @@ -629,7 +629,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ext_tls_connect", args: &[NA_F64, NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // ========== net.Server (issue #1123 followup) ========== // Server-side TCP via `net.createServer(...).listen(port, cb)`. The @@ -701,7 +701,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -710,7 +710,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -719,7 +719,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_noop_self", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Issue #2131 — `net.Server` EventEmitter surface beyond // `on`/`addListener`. Same shape as the Socket entries above; the @@ -732,7 +732,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_once", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -741,7 +741,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_remove_listener", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -750,7 +750,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_remove_listener", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -759,7 +759,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_remove_all_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "net", @@ -789,7 +789,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "net", @@ -798,7 +798,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_net_server_raw_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== node:stream — Readable.from / Duplex.from (#631/#1532) ========== // The other stream constructors (`new Readable(opts)` etc.) are wired @@ -1514,7 +1514,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_stream_method_event_names", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "stream", @@ -1532,7 +1532,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_stream_method_listeners", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "stream", @@ -1541,7 +1541,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_stream_method_raw_listeners", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== Events ========== NativeModSig { @@ -1551,7 +1551,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_new", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1572,7 +1572,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ // The listener also stays NA_JSV so runtime validation can throw // ERR_INVALID_ARG_TYPE for non-functions (#3072). args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1591,7 +1591,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_remove_listener", // NA_JSV (#3072): validate the listener is callable before removal. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1600,7 +1600,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_remove_all_listeners", args: &[NA_VARARGS], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // EventEmitter additions (#850) — `once` / `addListener` (alias for // `on`) / `prependListener` / `prependOnceListener` / `listenerCount` @@ -1615,7 +1615,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_once", // NA_JSV (#3072): validate the listener is callable. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1625,7 +1625,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_on", // NA_JSV (#3072): validate the listener is callable. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1635,7 +1635,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_prepend_listener", // NA_JSV (#3072): validate the listener is callable. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1645,7 +1645,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_prepend_once_listener", // NA_JSV (#3072): validate the listener is callable. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1655,7 +1655,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ runtime: "js_event_emitter_remove_listener", // NA_JSV (#3072): validate the listener is callable. args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1673,7 +1673,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_listeners", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1682,7 +1682,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_raw_listeners", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1691,7 +1691,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_event_names", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1700,7 +1700,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_event_emitter_set_max_listeners", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "events", @@ -1767,7 +1767,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_events_once", args: &[NA_F64, NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1776,7 +1776,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_events_on", args: &[NA_F64, NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1785,7 +1785,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_events_add_abort_listener", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", @@ -1794,7 +1794,7 @@ pub(super) const NET_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_events_get_event_listeners", args: &[NA_F64, NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "events", diff --git a/crates/perry-codegen/src/lower_call/native_table/node_core/dgram_fs_os.rs b/crates/perry-codegen/src/lower_call/native_table/node_core/dgram_fs_os.rs index c21ed41d2e..9a895cf532 100644 --- a/crates/perry-codegen/src/lower_call/native_table/node_core/dgram_fs_os.rs +++ b/crates/perry-codegen/src/lower_call/native_table/node_core/dgram_fs_os.rs @@ -396,6 +396,6 @@ pub(crate) const NODE_CORE_DGRAM_FS_OS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_os_user_info_options", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, ]; diff --git a/crates/perry-codegen/src/lower_call/native_table/node_core/util_buffer.rs b/crates/perry-codegen/src/lower_call/native_table/node_core/util_buffer.rs index 2bc34f1653..d3096fe38b 100644 --- a/crates/perry-codegen/src/lower_call/native_table/node_core/util_buffer.rs +++ b/crates/perry-codegen/src/lower_call/native_table/node_core/util_buffer.rs @@ -616,7 +616,7 @@ pub(crate) const NODE_CORE_UTIL_BUFFER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_buffer_copy_bytes_from", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // #2901: TC39 `Uint8Array.fromBase64(str, opts)` / `fromHex(str)`. // Routed via the buffer module (Uint8Array ≡ Buffer in Perry); the @@ -628,7 +628,7 @@ pub(crate) const NODE_CORE_UTIL_BUFFER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_u8_from_base64", args: &[NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "buffer", @@ -637,7 +637,7 @@ pub(crate) const NODE_CORE_UTIL_BUFFER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_u8_from_hex", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "buffer", @@ -689,7 +689,7 @@ pub(crate) const NODE_CORE_UTIL_BUFFER_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_buffer_transcode", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // Issue #1211: `import { resolveObjectURL } from "node:buffer"`. NativeModSig { diff --git a/crates/perry-codegen/src/lower_call/native_table/node_core_process.rs b/crates/perry-codegen/src/lower_call/native_table/node_core_process.rs index 8a6ddce928..08d8ac5919 100644 --- a/crates/perry-codegen/src/lower_call/native_table/node_core_process.rs +++ b/crates/perry-codegen/src/lower_call/native_table/node_core_process.rs @@ -382,7 +382,7 @@ pub(super) const NODE_CORE_PROCESS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_process_listeners", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "process", @@ -391,7 +391,7 @@ pub(super) const NODE_CORE_PROCESS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_process_raw_listeners", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "process", @@ -400,7 +400,7 @@ pub(super) const NODE_CORE_PROCESS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_process_event_names", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "process", diff --git a/crates/perry-codegen/src/lower_call/native_table/node_domain.rs b/crates/perry-codegen/src/lower_call/native_table/node_domain.rs index bdb4a87a2a..5643009c54 100644 --- a/crates/perry-codegen/src/lower_call/native_table/node_domain.rs +++ b/crates/perry-codegen/src/lower_call/native_table/node_domain.rs @@ -8,7 +8,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_create", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -17,7 +17,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_create", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -26,7 +26,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_create", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -35,7 +35,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_on", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -44,7 +44,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_on", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -89,7 +89,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_add", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", @@ -98,7 +98,7 @@ pub(super) const NODE_DOMAIN_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_domain_remove", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "domain", diff --git a/crates/perry-codegen/src/lower_call/native_table/node_misc.rs b/crates/perry-codegen/src/lower_call/native_table/node_misc.rs index dfdfb02be5..e51fd585f9 100644 --- a/crates/perry-codegen/src/lower_call/native_table/node_misc.rs +++ b/crates/perry-codegen/src/lower_call/native_table/node_misc.rs @@ -243,7 +243,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_querystring_unescape_buffer", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "querystring", @@ -252,7 +252,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_querystring_parse", args: &[NA_F64, NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "querystring", @@ -261,7 +261,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_querystring_parse", args: &[NA_F64, NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "querystring", @@ -289,7 +289,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lru_cache_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "lru-cache", @@ -307,7 +307,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lru_cache_set", args: &[NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "lru-cache", @@ -366,7 +366,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_name", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -375,7 +375,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_description", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -384,7 +384,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_version", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -393,7 +393,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_command", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -402,7 +402,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_option", args: &[NA_STR, NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -411,7 +411,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_required_option", args: &[NA_STR, NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // .action(cb) — NA_PTR coerces the NaN-boxed closure to its raw i64 // pointer so the runtime can call back through `js_closure_call1`. @@ -422,7 +422,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_action", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // .parse(argv) — runtime reads std::env::args() directly; user-provided // argv expression evaluates for side effects but is not forwarded. @@ -435,7 +435,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_parse", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "commander", @@ -444,7 +444,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_opts", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `.argument("")` declares a positional; returns the same handle so // the fluent chain continues (#5137). @@ -455,7 +455,7 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_argument", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `program.args` — a bare member read lowers to this 0-arg getter, which // returns a JS array of the parsed positional arguments (#5137). @@ -466,6 +466,6 @@ pub(super) const NODE_MISC_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_commander_args_array", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, ]; diff --git a/crates/perry-codegen/src/lower_call/native_table/thread_lodash.rs b/crates/perry-codegen/src/lower_call/native_table/thread_lodash.rs index 74eb491d95..a57c0d2908 100644 --- a/crates/perry-codegen/src/lower_call/native_table/thread_lodash.rs +++ b/crates/perry-codegen/src/lower_call/native_table/thread_lodash.rs @@ -12,7 +12,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_read_embedded", args: &[NA_F64], - ret: NR_PTR, + ret: NR_NULLABLE_GCPTR, }, // `embeddedFiles()` — zero-arg, returns a fresh `*mut ArrayHeader` of // `{ name, size, type }` objects (NaN-boxed POINTER by NR_PTR). @@ -23,7 +23,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_embedded_files", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== perry/thread (parallelMap, parallelFilter, spawn) ========== // Runtime expects both args as NaN-boxed f64 values and returns the same @@ -99,7 +99,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_chunk", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -108,7 +108,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_compact", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -117,7 +117,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_drop", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -153,7 +153,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_flatten", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -162,7 +162,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_uniq", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -171,7 +171,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_reverse", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -180,7 +180,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_take", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -225,7 +225,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_range", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -234,7 +234,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_times", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", @@ -252,7 +252,7 @@ pub(super) const THREAD_LODASH_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_lodash_tail", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "lodash", diff --git a/crates/perry-codegen/src/lower_call/native_table/tls_events.rs b/crates/perry-codegen/src/lower_call/native_table/tls_events.rs index b7a210488a..5068cfb70b 100644 --- a/crates/perry-codegen/src/lower_call/native_table/tls_events.rs +++ b/crates/perry-codegen/src/lower_call/native_table/tls_events.rs @@ -15,7 +15,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_tls_create_server", args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -24,7 +24,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_tls_create_server", args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -33,7 +33,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_tls_tlssocket_constructor", args: &[NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -42,7 +42,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_listen", args: &[NA_F64, NA_JSV, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -51,7 +51,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_close", args: &[NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -69,7 +69,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_on", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -78,7 +78,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_on", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -87,7 +87,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_once", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -96,7 +96,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_remove_listener", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -105,7 +105,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_remove_listener", args: &[NA_STR, NA_JSV], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", @@ -114,7 +114,7 @@ pub(super) const TLS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Server"), runtime: "js_tls_server_remove_all_listeners", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "tls", diff --git a/crates/perry-codegen/src/lower_call/native_table/tui.rs b/crates/perry-codegen/src/lower_call/native_table/tui.rs index fc4fe5d875..704aa3bb4e 100644 --- a/crates/perry-codegen/src/lower_call/native_table/tui.rs +++ b/crates/perry-codegen/src/lower_call/native_table/tui.rs @@ -13,7 +13,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_text", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -22,7 +22,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_box", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -50,7 +50,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_state_alloc", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // state.get() — receiver call, dispatches against class "State" // registered by destructuring.rs. @@ -241,7 +241,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_text_styled", args: &[NA_STR, NA_STR, NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // perry/tui Phase 4 — Spacer + ProgressBar widgets. NativeModSig { @@ -251,7 +251,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_spacer", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -260,7 +260,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_progress_bar", args: &[NA_F64, NA_F64, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // perry/tui Phase 4.5 — Spinner / Input / List / Select / TextArea. NativeModSig { @@ -270,7 +270,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_spinner", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -279,7 +279,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_input", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -288,7 +288,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_list", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -297,7 +297,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_select", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -306,7 +306,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_text_area", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // perry/tui Phase 4.6 — Table + Tabs widgets. Direct-FFI shapes // (positional args); object-literal `Table({headers, rows, selected})` @@ -319,7 +319,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_table", args: &[NA_PTR, NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -328,7 +328,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_tabs", args: &[NA_PTR, NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // perry/tui Phase 4.7 — Input(value, cursor). Direct-call shape; // codegen also dispatches to this from the 2-arg form so the @@ -340,7 +340,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_input_at", args: &[NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // perry/tui Phase 4.7 — AnimatedSpinner. Bare `AnimatedSpinner()` // hits this row with both args defaulted; object-literal opts @@ -352,7 +352,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_animated_spinner", args: &[NA_F64, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // ========== perry/tui Phase 1 — ink-API ergonomics hooks (#679) ========== // useState(initial) — call-site-indexed state cell. Returns the @@ -391,7 +391,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_use_state_tuple", args: &[NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // useEffect(fn, deps?). Runs fn() on first call or when deps change. // fn is an unboxed closure pointer (NA_PTR); deps is an unboxed @@ -428,7 +428,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_use_ref", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -456,7 +456,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_use_app", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // app.exit() / app.waitUntilExit() — class_filter routes only when // the receiver was registered as a "TuiApp" instance (see @@ -487,7 +487,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_use_stdout", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // stdout.write(s) / stdout.columns() / stdout.rows(). NativeModSig { @@ -575,7 +575,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_perry_tui_use_focus_manager", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "perry/tui", @@ -615,7 +615,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_readline_create_interface", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "readline", @@ -699,7 +699,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_readline_iterator", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "readline", @@ -708,7 +708,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_readline_pause", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "readline", @@ -717,7 +717,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_readline_resume", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "readline", @@ -762,7 +762,7 @@ pub(super) const TUI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_readline_get_cursor_pos", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "readline", diff --git a/crates/perry-codegen/src/lower_call/native_table/undici.rs b/crates/perry-codegen/src/lower_call/native_table/undici.rs index 19b998512e..56c00c169d 100644 --- a/crates/perry-codegen/src/lower_call/native_table/undici.rs +++ b/crates/perry-codegen/src/lower_call/native_table/undici.rs @@ -25,7 +25,7 @@ pub(super) const UNDICI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_undici_proxy_agent_new", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "undici", @@ -34,7 +34,7 @@ pub(super) const UNDICI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_undici_agent_new", args: &[NA_STR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // ── module-level functions ───────────────────────────────────── NativeModSig { @@ -53,7 +53,7 @@ pub(super) const UNDICI_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_undici_get_global_dispatcher", args: &[], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // `request(url, options?)` — rejects with a "not implemented, use // fetch" error; the row exists so users get that clear message at diff --git a/crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs b/crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs index 18a86f86a3..880a733ee1 100644 --- a/crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs +++ b/crates/perry-codegen/src/lower_call/native_table/utils_crypto.rs @@ -110,7 +110,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_nodemailer_send_mail", args: &[NA_PTR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "nodemailer", @@ -119,7 +119,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_nodemailer_verify", args: &[], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== dotenv ========== NativeModSig { @@ -211,7 +211,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "backOff", args: &[NA_PTR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== argon2 ========== // Runtime FFI signatures take `*const StringHeader`, NOT NaN-boxed f64. @@ -225,7 +225,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_argon2_hash", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "argon2", @@ -234,7 +234,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_argon2_verify", args: &[NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== bcrypt ========== // Same ABI rule as argon2 above: password / hash args are @@ -247,7 +247,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bcrypt_hash", args: &[NA_STR, NA_F64], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "bcrypt", @@ -256,7 +256,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_bcrypt_compare", args: &[NA_STR, NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, // ========== node-forge (PKI subset — perry-ext-node-forge) ========== // Namespaced statics (`forge.pki.rsa.generateKeyPair`, @@ -275,7 +275,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_forge_generate_key_pair", args: &[NA_F64], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "node-forge", @@ -284,7 +284,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_forge_create_certificate", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "node-forge", @@ -293,7 +293,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_forge_certificate_from_pem", args: &[NA_STR], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "node-forge", @@ -311,7 +311,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_forge_private_key_from_pem", args: &[NA_STR], - ret: NR_PTR, + ret: NR_JS_VALUE, }, NativeModSig { module: "node-forge", @@ -339,7 +339,7 @@ pub(super) const UTILS_CRYPTO_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_node_forge_md_sha256_create", args: &[], - ret: NR_PTR, + ret: NR_JS_VALUE, }, // Certificate builder instance methods. The receiver (the JS cert // object) is NaN-unboxed to an `i64` `*mut ObjectHeader` and passed diff --git a/crates/perry-codegen/src/lower_call/native_table/ws_events.rs b/crates/perry-codegen/src/lower_call/native_table/ws_events.rs index 7cdadc04c1..aaea329463 100644 --- a/crates/perry-codegen/src/lower_call/native_table/ws_events.rs +++ b/crates/perry-codegen/src/lower_call/native_table/ws_events.rs @@ -16,7 +16,7 @@ pub(super) const WS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ws_server_new", args: &[NA_F64], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "ws", @@ -25,7 +25,7 @@ pub(super) const WS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: None, runtime: "js_ws_connect", args: &[NA_STR], - ret: NR_PTR, + ret: NR_GCPTR, }, NativeModSig { module: "ws", @@ -137,7 +137,7 @@ pub(super) const WS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Client"), runtime: "js_ws_on_client_i64", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, NativeModSig { module: "ws", @@ -146,7 +146,7 @@ pub(super) const WS_EVENTS_ROWS: &[NativeModSig] = &[ class_filter: Some("Client"), runtime: "js_ws_on_client_i64", args: &[NA_STR, NA_PTR], - ret: NR_PTR, + ret: NR_HANDLE_ID, }, // Server-side helpers — the user receives a client handle as a plain // f64 number from `wss.on('connection', (handle) => …)`, then passes diff --git a/crates/perry-runtime/src/async_hooks.rs b/crates/perry-runtime/src/async_hooks.rs index e05f322da0..54ba59d03a 100644 --- a/crates/perry-runtime/src/async_hooks.rs +++ b/crates/perry-runtime/src/async_hooks.rs @@ -218,6 +218,14 @@ pub(crate) fn is_async_resource_handle(handle: i64) -> bool { && ASYNC_RESOURCE_HANDLES.lock().unwrap().contains(&handle) } +/// Diagnostic-only exact membership check for the old raw-box hook handle. +#[inline] +pub(crate) fn is_async_hook_handle(handle: i64) -> bool { + ASYNC_HOOK_HANDLE_COUNT.load(Ordering::Relaxed) != 0 + && handle != 0 + && ASYNC_HOOK_HANDLES.lock().unwrap().contains(&handle) +} + /// Resolve either a native `AsyncResource` handle or the ordinary object used /// for a source-compiled subclass to its native backing allocation. pub(crate) fn resolve_async_resource_handle(receiver: i64) -> Option { @@ -560,6 +568,11 @@ pub extern "C" fn js_async_hooks_create_hook(options: f64) -> i64 { let handle = Box::into_raw(Box::new(AsyncHookHandle { index })) as i64; ASYNC_HOOK_HANDLES.lock().unwrap().insert(handle); ASYNC_HOOK_HANDLE_COUNT.fetch_add(1, Ordering::Relaxed); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::AsyncHook, + ); + } handle } @@ -1234,6 +1247,11 @@ fn new_async_resource_with_public_value( })) as i64; ASYNC_RESOURCE_HANDLES.lock().unwrap().insert(handle); ASYNC_RESOURCE_HANDLE_COUNT.fetch_add(1, Ordering::Relaxed); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::AsyncResource, + ); + } let resource_value = public_resource.unwrap_or_else(|| crate::value::js_nanbox_pointer(handle)); let ids = init_resource_with_trigger(&type_name, resource_value, true, trigger_async_id); unsafe { (*(handle as *mut AsyncResourceHandle)).ids = ids }; diff --git a/crates/perry-runtime/src/buffer/header.rs b/crates/perry-runtime/src/buffer/header.rs index d1224faefc..b7a42a48b0 100644 --- a/crates/perry-runtime/src/buffer/header.rs +++ b/crates/perry-runtime/src/buffer/header.rs @@ -49,6 +49,16 @@ fn external_buffers() -> &'static Mutex> { EXTERNAL_BUFFER_REGISTRY.get_or_init(|| Mutex::new(HashSet::new())) } +/// Diagnostic-only exact membership check for the legacy external-buffer ABI. +#[inline] +pub fn is_external_buffer(addr: usize) -> bool { + EXTERNAL_BUFFERS_NONEMPTY.load(std::sync::atomic::Ordering::Acquire) + && external_buffers() + .lock() + .map(|r| r.contains(&addr)) + .unwrap_or(false) +} + fn external_uint8arrays() -> &'static Mutex> { EXTERNAL_UINT8ARRAY_REGISTRY.get_or_init(|| Mutex::new(HashSet::new())) } @@ -603,6 +613,11 @@ pub extern "C" fn js_buffer_register_external(addr: usize) { if let Ok(mut r) = external_buffers().lock() { r.insert(addr); } + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::ExternalBuffer, + ); + } } #[no_mangle] diff --git a/crates/perry-runtime/src/buffer/mod.rs b/crates/perry-runtime/src/buffer/mod.rs index 1a93fd3f93..10b495cc81 100644 --- a/crates/perry-runtime/src/buffer/mod.rs +++ b/crates/perry-runtime/src/buffer/mod.rs @@ -56,8 +56,8 @@ pub(crate) use header::note_buffer_like_registered; pub use header::{ asymmetric_key_meta, buffer_ab_alias, buffer_alloc, buffer_backing_array_buffer, buffer_byte_offset, buffer_data, buffer_data_mut, crypto_key_meta, ensure_buffer_ab_alias, - is_any_array_buffer, is_array_buffer, is_data_view, is_registered_buffer, is_secret_key, - is_shared_array_buffer, is_uint8array_buffer, js_set_crypto_key_death_hook, + is_any_array_buffer, is_array_buffer, is_data_view, is_external_buffer, is_registered_buffer, + is_secret_key, is_shared_array_buffer, is_uint8array_buffer, js_set_crypto_key_death_hook, mark_as_array_buffer, mark_as_asymmetric_key, mark_as_crypto_key, mark_as_data_view, mark_as_secret_key, mark_as_shared_array_buffer, mark_as_uint8array, register_buffer, resolve_buffer_ab_alias, set_buffer_ab_alias, CryptoKeyDeathHookFn, @@ -71,9 +71,9 @@ pub(crate) use header::{ pub(crate) use header::rebind_foreign_buffer; #[cfg(test)] pub(crate) use header::{ - test_buffer_addr_window_bounds, test_buffer_registry_probe_count, test_data_view_registry_len, - test_shared_array_buffer_registry_len, test_uint8array_addr_window_bounds, - test_uint8array_registry_probe_count, + js_buffer_register_external, test_buffer_addr_window_bounds, test_buffer_registry_probe_count, + test_data_view_registry_len, test_shared_array_buffer_registry_len, + test_uint8array_addr_window_bounds, test_uint8array_registry_probe_count, }; // ---- Re-exports: ArrayBuffer detach / transfer (ES2024) ---- diff --git a/crates/perry-runtime/src/hot_diag.rs b/crates/perry-runtime/src/hot_diag.rs index 51615783ca..4695e6743b 100644 --- a/crates/perry-runtime/src/hot_diag.rs +++ b/crates/perry-runtime/src/hot_diag.rs @@ -22,12 +22,12 @@ use std::time::Instant; /// How the diag output is delivered. #[derive(Clone)] -enum Sink { +pub(crate) enum Sink { Stderr, File(String), } -fn sink_from_env(name: &str) -> Option { +pub(crate) fn sink_from_env(name: &str) -> Option { let raw = std::env::var(name).ok()?; let raw = raw.trim(); match raw { @@ -44,7 +44,7 @@ fn sink_from_env(name: &str) -> Option { /// missing-exit-line trap in a second form, and it cost a lane a measurement /// run. Report the first failure on stderr, naming the path and the error, /// and keep writing there. -fn write_sink(sink: &Sink, text: &str) { +pub(crate) fn write_sink(sink: &Sink, text: &str) { match sink { Sink::Stderr => eprint!("{text}"), Sink::File(path) => { @@ -65,6 +65,16 @@ fn write_sink(sink: &Sink, text: &str) { const TICK_EVERY: u32 = 256; const DUMP_INTERVAL_MS: u128 = 1000; +mod receiver_repr; +pub use receiver_repr::{ + receiver_repr_note_constructed, receiver_repr_note_decoded_pointer, receiver_repr_note_value, + receiver_repr_note_wrapped, receiver_repr_on, ReceiverReprFamily, +}; +#[cfg(test)] +pub(crate) use receiver_repr::{ + receiver_repr_test_arm, receiver_repr_test_classification_entries, receiver_repr_test_reset, +}; + // --------------------------------------------------------------------------- // RegExp // --------------------------------------------------------------------------- diff --git a/crates/perry-runtime/src/hot_diag/receiver_repr.rs b/crates/perry-runtime/src/hot_diag/receiver_repr.rs new file mode 100644 index 0000000000..d00cce363a --- /dev/null +++ b/crates/perry-runtime/src/hot_diag/receiver_repr.rs @@ -0,0 +1,509 @@ +//! Receiver-representation migration ledger. +//! +//! The classifiers in this module are deliberately diagnostics-only. Every +//! caller first tests [`receiver_repr_on`], so an unarmed process pays one +//! relaxed load and enters none of the range, registry, or ownership probes. + +use super::{sink_from_env, write_sink, Sink}; +use std::fmt::Write as _; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::{Mutex, OnceLock}; +use std::time::{Duration, Instant}; + +const FAMILY_COUNT: usize = 13; +const POINTER_TAG: u64 = 0x7FFD_0000_0000_0000; +const TAG_MASK: u64 = 0xFFFF_0000_0000_0000; +const POINTER_MASK: u64 = 0x0000_FFFF_FFFF_FFFF; +const SNAPSHOT_EVERY: u64 = 4096; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u8)] +pub enum ReceiverReprFamily { + Common, + Fetch, + Zlib, + Proxy, + Timer, + Text, + Tui, + AsyncHook, + AsyncResource, + SymbolGlobal, + ExternalBuffer, + Sab, + NullStub, +} + +impl ReceiverReprFamily { + #[cfg(test)] + const ALL: [Self; FAMILY_COUNT] = [ + Self::Common, + Self::Fetch, + Self::Zlib, + Self::Proxy, + Self::Timer, + Self::Text, + Self::Tui, + Self::AsyncHook, + Self::AsyncResource, + Self::SymbolGlobal, + Self::ExternalBuffer, + Self::Sab, + Self::NullStub, + ]; + + const NAMES: [&'static str; FAMILY_COUNT] = [ + "common", + "fetch", + "zlib", + "proxy", + "timer", + "text", + "tui", + "async_hook", + "async_resource", + "symbol_global", + "external_buffer", + "sab", + "null_stub", + ]; + + #[inline] + const fn index(self) -> usize { + self as usize + } +} + +struct FamilyCounters { + constructed: [AtomicU64; FAMILY_COUNT], + observed_old: [AtomicU64; FAMILY_COUNT], + observed_wrapped: [AtomicU64; FAMILY_COUNT], +} + +impl FamilyCounters { + const fn new() -> Self { + Self { + constructed: [const { AtomicU64::new(0) }; FAMILY_COUNT], + observed_old: [const { AtomicU64::new(0) }; FAMILY_COUNT], + observed_wrapped: [const { AtomicU64::new(0) }; FAMILY_COUNT], + } + } +} + +static COUNTERS: FamilyCounters = FamilyCounters::new(); +static BARE_MANAGED: AtomicU64 = AtomicU64::new(0); +static INVALID_POINTER_ZERO: AtomicU64 = AtomicU64::new(0); +static DIRECT_MISMATCH: AtomicU64 = AtomicU64::new(0); +static EVENTS: AtomicU64 = AtomicU64::new(0); +static RECEIVER_REPR_SINK: OnceLock> = OnceLock::new(); +static RECEIVER_REPR_ON: AtomicBool = AtomicBool::new(false); +static LAST_DUMP: Mutex> = Mutex::new(None); + +#[cfg(test)] +static TEST_FORCE_ON: AtomicBool = AtomicBool::new(false); +#[cfg(test)] +static TEST_CLASSIFICATION_ENTRIES: AtomicU64 = AtomicU64::new(0); + +fn receiver_repr_sink() -> &'static Option { + RECEIVER_REPR_SINK.get_or_init(|| { + let sink = sink_from_env("PERRY_RECEIVER_REPR_DIAG"); + RECEIVER_REPR_ON.store(sink.is_some(), Ordering::Relaxed); + sink + }) +} + +/// One relaxed load after the environment has been parsed once. +#[inline] +pub fn receiver_repr_on() -> bool { + if RECEIVER_REPR_SINK.get().is_none() { + receiver_repr_sink(); + } + let armed = RECEIVER_REPR_ON.load(Ordering::Relaxed); + #[cfg(test)] + let armed = armed || TEST_FORCE_ON.load(Ordering::Relaxed); + armed +} + +#[inline] +pub fn receiver_repr_note_constructed(family: ReceiverReprFamily) { + COUNTERS.constructed[family.index()].fetch_add(1, Ordering::Relaxed); + maybe_dump(); +} + +/// Reserved for the later wrapper PRs; PR 1 records the zero baseline. +#[inline] +pub fn receiver_repr_note_wrapped(family: ReceiverReprFamily) { + COUNTERS.observed_wrapped[family.index()].fetch_add(1, Ordering::Relaxed); + maybe_dump(); +} + +/// Observe a dynamic receiver before a NaN-box tag has been stripped. +/// +/// This function intentionally does not repeat the armed test. Its callers are +/// the audited funnels, each with exactly one [`receiver_repr_on`] guard. +#[inline] +pub fn receiver_repr_note_value(value: f64) { + test_note_classification_entry(); + let bits = value.to_bits(); + if bits & TAG_MASK == POINTER_TAG { + let addr = (bits & POINTER_MASK) as usize; + if addr == 0 { + INVALID_POINTER_ZERO.fetch_add(1, Ordering::Relaxed); + } else { + observe_pointer(addr); + } + } else if bits >> 48 == 0 && bits != 0 { + // This is the compatibility shape PR 10 removes: an allocator-owned + // address bitcast directly to f64 with no pointer tag. + if unsafe { crate::value::addr_class::try_read_tracked_gc_header(bits as usize) }.is_some() + { + BARE_MANAGED.fetch_add(1, Ordering::Relaxed); + } + } + maybe_dump(); +} + +/// Observe a funnel which has already stripped `POINTER_TAG` by contract. +#[inline] +pub fn receiver_repr_note_decoded_pointer(addr: usize) { + test_note_classification_entry(); + if addr == 0 { + INVALID_POINTER_ZERO.fetch_add(1, Ordering::Relaxed); + } else { + observe_pointer(addr); + } + maybe_dump(); +} + +#[inline] +fn mark_old(family: ReceiverReprFamily) { + COUNTERS.observed_old[family.index()].fetch_add(1, Ordering::Relaxed); +} + +fn observe_pointer(addr: usize) { + // The small bands are disjoint, except that timer/text/TUI registries use + // small ids too. Count every matching semantic family: the old encoding + // contains no provenance bit with which to choose one of colliding id 1s. + if crate::value::addr_class::is_common_handle_band(addr) { + mark_old(ReceiverReprFamily::Common); + } + if crate::value::addr_class::is_fetch_handle_band(addr) { + mark_old(ReceiverReprFamily::Fetch); + } + if crate::value::addr_class::is_zlib_handle_band(addr) { + mark_old(ReceiverReprFamily::Zlib); + } + if crate::value::addr_class::is_proxy_id_band(addr) { + let boxed = f64::from_bits(POINTER_TAG | addr as u64); + if crate::proxy::js_proxy_is_proxy(boxed) != 0 { + mark_old(ReceiverReprFamily::Proxy); + } + } + if crate::timer::is_known_timer_id(addr as i64) { + mark_old(ReceiverReprFamily::Timer); + } + if addr as i64 == crate::text::TEXT_ENCODER_SENTINEL_ID + || crate::text::is_known_text_decoder_id(addr as i64) + { + mark_old(ReceiverReprFamily::Text); + } + if crate::tui::is_known_handle(addr as i64) { + mark_old(ReceiverReprFamily::Tui); + } + if crate::async_hooks::is_async_hook_handle(addr as i64) { + mark_old(ReceiverReprFamily::AsyncHook); + } + if crate::async_hooks::is_async_resource_handle(addr as i64) { + mark_old(ReceiverReprFamily::AsyncResource); + } + if crate::object::is_null_stub_address(addr) { + mark_old(ReceiverReprFamily::NullStub); + } + if crate::shared_sab::is_shared_sab(addr) { + mark_old(ReceiverReprFamily::Sab); + } + + let tracked = unsafe { crate::value::addr_class::try_read_tracked_gc_header(addr) }; + if tracked.is_none() { + if crate::symbol::is_registered_symbol(addr) { + mark_old(ReceiverReprFamily::SymbolGlobal); + } + if crate::buffer::is_external_buffer(addr) { + mark_old(ReceiverReprFamily::ExternalBuffer); + } + return; + } + + // Debug-only trust-the-tag audit. The ownership-derived header makes the + // direct byte readable; release builds carry no direct-load probe at all. + #[cfg(debug_assertions)] + unsafe { + let derived = tracked.unwrap(); + let derived_ptr = derived.as_ptr() as *const crate::gc::GcHeader; + let direct = + (addr as *const u8).sub(crate::gc::GC_HEADER_SIZE) as *const crate::gc::GcHeader; + if direct != derived_ptr || (*direct).obj_type != (*derived_ptr).obj_type { + DIRECT_MISMATCH.fetch_add(1, Ordering::Relaxed); + } + } +} + +#[inline] +fn maybe_dump() { + let event = EVENTS.fetch_add(1, Ordering::Relaxed); + if event != 0 && event % SNAPSHOT_EVERY != 0 { + return; + } + let mut last = LAST_DUMP.lock().unwrap(); + if last.is_some_and(|instant| instant.elapsed() < Duration::from_secs(1)) { + return; + } + *last = Some(Instant::now()); + if let Some(sink) = receiver_repr_sink() { + write_sink(sink, &render()); + } +} + +fn append_family_counts(out: &mut String, values: &[AtomicU64; FAMILY_COUNT]) { + for (index, name) in ReceiverReprFamily::NAMES.iter().enumerate() { + if index != 0 { + out.push(' '); + } + let _ = write!(out, "{name}={}", values[index].load(Ordering::Relaxed)); + } +} + +fn render() -> String { + let mut out = String::with_capacity(768); + out.push_str("[receiver-repr-diag] constructed "); + append_family_counts(&mut out, &COUNTERS.constructed); + out.push_str("; observed_old "); + append_family_counts(&mut out, &COUNTERS.observed_old); + out.push_str("; observed_wrapped "); + append_family_counts(&mut out, &COUNTERS.observed_wrapped); + let _ = writeln!( + out, + "; bare_managed={}; invalid_pointer_zero={}; direct_mismatch={}", + BARE_MANAGED.load(Ordering::Relaxed), + INVALID_POINTER_ZERO.load(Ordering::Relaxed), + DIRECT_MISMATCH.load(Ordering::Relaxed), + ); + out +} + +#[cfg(test)] +#[inline] +fn test_note_classification_entry() { + TEST_CLASSIFICATION_ENTRIES.fetch_add(1, Ordering::Relaxed); +} + +#[cfg(not(test))] +#[inline] +fn test_note_classification_entry() {} + +#[cfg(test)] +pub(crate) fn receiver_repr_test_arm(armed: bool) { + receiver_repr_sink(); + RECEIVER_REPR_ON.store(armed, Ordering::Relaxed); + TEST_FORCE_ON.store(armed, Ordering::Relaxed); +} + +#[cfg(test)] +pub(crate) fn receiver_repr_test_classification_entries() -> u64 { + TEST_CLASSIFICATION_ENTRIES.load(Ordering::Relaxed) +} + +#[cfg(test)] +pub(crate) fn receiver_repr_test_reset() { + for family in ReceiverReprFamily::ALL { + COUNTERS.constructed[family.index()].store(0, Ordering::Relaxed); + COUNTERS.observed_old[family.index()].store(0, Ordering::Relaxed); + COUNTERS.observed_wrapped[family.index()].store(0, Ordering::Relaxed); + } + BARE_MANAGED.store(0, Ordering::Relaxed); + INVALID_POINTER_ZERO.store(0, Ordering::Relaxed); + DIRECT_MISMATCH.store(0, Ordering::Relaxed); + EVENTS.store(0, Ordering::Relaxed); + TEST_CLASSIFICATION_ENTRIES.store(0, Ordering::Relaxed); + *LAST_DUMP.lock().unwrap() = None; +} + +#[cfg(test)] +pub(crate) fn receiver_repr_test_snapshot(family: ReceiverReprFamily) -> (u64, u64, u64) { + let index = family.index(); + ( + COUNTERS.constructed[index].load(Ordering::Relaxed), + COUNTERS.observed_old[index].load(Ordering::Relaxed), + COUNTERS.observed_wrapped[index].load(Ordering::Relaxed), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::path::Path; + + fn assert_fixture(family: ReceiverReprFamily, construct: impl FnOnce() -> (usize, bool)) { + receiver_repr_test_reset(); + receiver_repr_test_arm(true); + let (value, already_nanboxed) = construct(); + if already_nanboxed { + receiver_repr_note_value(f64::from_bits(value as u64)); + } else { + receiver_repr_note_decoded_pointer(value); + } + let (constructed, observed, wrapped) = receiver_repr_test_snapshot(family); + assert!( + constructed > 0, + "{family:?} constructor did not move its bucket" + ); + assert!( + observed > 0, + "{family:?} receiver did not move observed_old" + ); + assert_eq!(wrapped, 0, "PR 1 must not create wrappers"); + } + + #[test] + fn receiver_repr_family_fixtures_move_constructed_and_observed_old() { + // These three producers live in perry-stdlib, below perry-runtime in + // the dependency graph. Their exact producer calls are pinned by the + // source-witness test below; the fixtures exercise their audited bands. + assert_fixture(ReceiverReprFamily::Common, || { + receiver_repr_note_constructed(ReceiverReprFamily::Common); + (2, false) + }); + assert_fixture(ReceiverReprFamily::Fetch, || { + receiver_repr_note_constructed(ReceiverReprFamily::Fetch); + (crate::value::addr_class::FETCH_HANDLE_BAND_START, false) + }); + assert_fixture(ReceiverReprFamily::Zlib, || { + receiver_repr_note_constructed(ReceiverReprFamily::Zlib); + (crate::value::addr_class::ZLIB_HANDLE_BAND_START, false) + }); + assert_fixture(ReceiverReprFamily::Proxy, || { + let object = || { + let ptr = crate::object::js_object_alloc(0, 0); + f64::from_bits(crate::value::JSValue::pointer(ptr.cast()).bits()) + }; + ( + crate::proxy::js_proxy_new(object(), object()).to_bits() as usize, + true, + ) + }); + assert_fixture(ReceiverReprFamily::Timer, || { + ( + crate::timer::js_set_timeout_callback(0, 60_000.0) as usize, + false, + ) + }); + assert_fixture(ReceiverReprFamily::Text, || { + (crate::text::js_text_encoder_new() as usize, false) + }); + assert_fixture(ReceiverReprFamily::Tui, || { + let mut handle = crate::tui::state::js_perry_tui_state_alloc(0.0); + if handle == 0 { + handle = crate::tui::state::js_perry_tui_state_alloc(0.0); + } + (handle as usize, false) + }); + assert_fixture(ReceiverReprFamily::AsyncHook, || { + let options = crate::object::js_object_alloc(0, 0); + let value = f64::from_bits(crate::value::JSValue::pointer(options.cast()).bits()); + ( + crate::async_hooks::js_async_hooks_create_hook(value) as usize, + false, + ) + }); + assert_fixture(ReceiverReprFamily::AsyncResource, || { + let name = crate::string::js_string_from_bytes(b"receiver-repr".as_ptr(), 13); + let type_value = f64::from_bits(crate::value::js_nanbox_string(name as i64).to_bits()); + let options = f64::from_bits(crate::value::TAG_UNDEFINED); + ( + crate::async_hooks::js_async_resource_new(type_value, options) as usize, + false, + ) + }); + assert_fixture(ReceiverReprFamily::SymbolGlobal, || { + ( + crate::symbol::well_known_symbol("receiverReprFixture") as usize, + false, + ) + }); + assert_fixture(ReceiverReprFamily::ExternalBuffer, || { + let buffer = Box::into_raw(Box::new(crate::buffer::BufferHeader { + length: 0, + capacity: 0, + })); + crate::buffer::js_buffer_register_external(buffer as usize); + (buffer as usize, false) + }); + assert_fixture(ReceiverReprFamily::Sab, || { + (crate::shared_sab::alloc_shared_sab(1) as usize, false) + }); + assert_fixture(ReceiverReprFamily::NullStub, || { + ( + crate::object::js_unresolved_namespace_stub().to_bits() as usize, + true, + ) + }); + + let line = render(); + assert!(line.starts_with("[receiver-repr-diag] constructed common=0")); + assert!(line.contains("null_stub=1; observed_old")); + assert!(line.contains("null_stub=1; observed_wrapped")); + assert!(line.ends_with("bare_managed=0; invalid_pointer_zero=0; direct_mismatch=0\n")); + receiver_repr_test_arm(false); + } + + /// Source witnesses bind the fixture above to every audited producer. If a + /// producer-side bump is dropped, its exact occurrence floor fails here. + #[test] + fn receiver_repr_every_family_producer_keeps_its_constructed_bump() { + let manifest = Path::new(env!("CARGO_MANIFEST_DIR")); + let workspace = manifest.parent().and_then(Path::parent).unwrap(); + let witnesses = [ + ("crates/perry-stdlib/src/common/handle.rs", "Common", 2), + ("crates/perry-stdlib/src/fetch/mod.rs", "Fetch", 1), + ("crates/perry-stdlib/src/zlib.rs", "Zlib", 1), + ("crates/perry-runtime/src/proxy.rs", "Proxy", 1), + ("crates/perry-runtime/src/timer.rs", "Timer", 1), + ("crates/perry-runtime/src/text.rs", "Text", 2), + ("crates/perry-runtime/src/tui/tree.rs", "Tui", 1), + ("crates/perry-runtime/src/tui/state.rs", "Tui", 1), + ("crates/perry-runtime/src/tui/hooks.rs", "Tui", 4), + ("crates/perry-runtime/src/async_hooks.rs", "AsyncHook", 1), + ( + "crates/perry-runtime/src/async_hooks.rs", + "AsyncResource", + 1, + ), + ("crates/perry-runtime/src/symbol.rs", "SymbolGlobal", 2), + ( + "crates/perry-runtime/src/symbol/constructors.rs", + "SymbolGlobal", + 1, + ), + ( + "crates/perry-runtime/src/buffer/header.rs", + "ExternalBuffer", + 1, + ), + ("crates/perry-runtime/src/shared_sab.rs", "Sab", 1), + ( + "crates/perry-runtime/src/object/null_stub.rs", + "NullStub", + 1, + ), + ]; + for (relative, family, expected) in witnesses { + let text = std::fs::read_to_string(workspace.join(relative)).unwrap(); + let needle = format!("ReceiverReprFamily::{family}"); + assert_eq!( + text.matches(&needle).count(), + expected, + "producer-side diagnostic bump changed in {relative}" + ); + } + } +} diff --git a/crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs b/crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs index dfa7a37746..0eb3ea84d0 100644 --- a/crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs +++ b/crates/perry-runtime/src/object/field_get_set/get_field_by_name_tail.rs @@ -8,6 +8,10 @@ pub(crate) fn get_field_by_name_object_tail( obj: *const ObjectHeader, key: *const crate::StringHeader, ) -> JSValue { + if crate::hot_diag::receiver_repr_on() { + let addr = (obj as u64 & 0x0000_FFFF_FFFF_FFFF) as usize; + crate::hot_diag::receiver_repr_note_decoded_pointer(addr); + } // An elements-backed Array-subclass instance answers its indices and // `length` from its store; an absent index falls through to the ordinary // lookup, which reaches the prototype chain (the shape has no index keys). diff --git a/crates/perry-runtime/src/object/field_get_set/ic_miss.rs b/crates/perry-runtime/src/object/field_get_set/ic_miss.rs index 5df83c2564..a288bae136 100644 --- a/crates/perry-runtime/src/object/field_get_set/ic_miss.rs +++ b/crates/perry-runtime/src/object/field_get_set/ic_miss.rs @@ -538,6 +538,9 @@ pub extern "C" fn js_object_get_field_ic_miss( cache_slot: *mut PicCacheSlot, ) -> f64 { use crate::hot_diag::IcMissReason as R; + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_decoded_pointer(obj as usize); + } let diag = crate::hot_diag::ic_on(); // SSO receiver — never cacheable. Route through the SSO-aware // `js_object_get_field_by_name` which handles `.length` inline diff --git a/crates/perry-runtime/src/object/mod.rs b/crates/perry-runtime/src/object/mod.rs index 77a02c25a4..4d247a88a9 100644 --- a/crates/perry-runtime/src/object/mod.rs +++ b/crates/perry-runtime/src/object/mod.rs @@ -108,8 +108,8 @@ pub(crate) use live_slots::set_object_live_slot_count; pub use live_slots::{ js_object_live_slot_count, object_live_slot_count, perry_object_header_abi_revision, }; +pub(crate) use null_stub::{is_null_stub_address, NullObjectBytes, NULL_OBJECT_BYTES}; pub use null_stub::{js_unresolved_default_call, js_unresolved_namespace_stub}; -pub(crate) use null_stub::{NullObjectBytes, NULL_OBJECT_BYTES}; #[cfg(test)] pub(crate) use side_table_roots::test_transition_cache_insert; pub(crate) use side_table_roots::{ diff --git a/crates/perry-runtime/src/object/native_call_method.rs b/crates/perry-runtime/src/object/native_call_method.rs index c7452709a7..175adf6fd4 100644 --- a/crates/perry-runtime/src/object/native_call_method.rs +++ b/crates/perry-runtime/src/object/native_call_method.rs @@ -1022,6 +1022,9 @@ fn throw_object_to_string_not_function() -> ! { #[inline] unsafe fn gc_pointer_and_type_from_value(value: f64) -> Option<(*const u8, u8)> { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_value(value); + } let jsval = JSValue::from_bits(value.to_bits()); let ptr = if jsval.is_pointer() { jsval.as_pointer::() @@ -2761,3 +2764,62 @@ mod primitive_dataprop_recovery_tests { ); } } + +#[cfg(test)] +mod receiver_repr_guard_tests { + use super::*; + + /// An unarmed ledger must stop at each funnel's single guard. The + /// diagnostic helper increments a test-only entry counter before doing any + /// classification, so removing any guard below makes this test fail. + #[test] + fn receiver_repr_unarmed_funnels_never_enter_classification() { + crate::hot_diag::receiver_repr_test_reset(); + crate::hot_diag::receiver_repr_test_arm(false); + + unsafe { + assert!(gc_pointer_and_type_from_value(1.25).is_none()); + let scope = crate::gc::RuntimeHandleScope::new(); + let object = scope.root_nanbox_f64(1.25); + assert!(primitive_methods::dispatch_primitive( + &scope, + &object, + &[], + 1.25, + "receiver_repr_miss", + std::ptr::null(), + 0, + std::ptr::null(), + 0, + ) + .is_none()); + } + assert_eq!( + crate::object::prototype_chain::object_static_prototype(1), + None + ); + assert_eq!( + crate::object::field_get_set::get_field_by_name_object_tail( + std::ptr::null(), + std::ptr::null(), + ) + .bits(), + crate::value::TAG_UNDEFINED, + ); + assert_eq!( + crate::object::field_get_set::js_object_get_field_ic_miss( + std::ptr::null(), + std::ptr::null(), + std::ptr::null_mut(), + ) + .to_bits(), + crate::value::TAG_UNDEFINED, + ); + + assert_eq!( + crate::hot_diag::receiver_repr_test_classification_entries(), + 0, + "an unarmed funnel entered receiver-representation classification" + ); + } +} diff --git a/crates/perry-runtime/src/object/native_call_method/primitive_methods.rs b/crates/perry-runtime/src/object/native_call_method/primitive_methods.rs index 47ac13f0c5..25f6984852 100644 --- a/crates/perry-runtime/src/object/native_call_method/primitive_methods.rs +++ b/crates/perry-runtime/src/object/native_call_method/primitive_methods.rs @@ -12,6 +12,9 @@ pub(super) unsafe fn dispatch_primitive( args_ptr: *const f64, args_len: usize, ) -> Option { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_value(object); + } let jsval = JSValue::from_bits(object.to_bits()); let raw_bits = object.to_bits(); let refreshed_args = || crate::gc::RuntimeHandleScope::refreshed_nanbox_f64_slice(arg_handles); diff --git a/crates/perry-runtime/src/object/null_stub.rs b/crates/perry-runtime/src/object/null_stub.rs index e2c6cb0d84..ce8ef3476c 100644 --- a/crates/perry-runtime/src/object/null_stub.rs +++ b/crates/perry-runtime/src/object/null_stub.rs @@ -36,6 +36,11 @@ const _: () = #[no_mangle] pub extern "C" fn js_unresolved_namespace_stub() -> f64 { let null_obj_ptr = &NULL_OBJECT_BYTES as *const NullObjectBytes as *mut u8; + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::NullStub, + ); + } f64::from_bits(crate::JSValue::pointer(null_obj_ptr).bits()) } @@ -69,3 +74,8 @@ pub(crate) static NULL_OBJECT_BYTES: NullObjectBytes = NullObjectBytes { parent_class_id: 0, meta_and_padding: 0, }; + +#[inline] +pub(crate) fn is_null_stub_address(addr: usize) -> bool { + addr == &NULL_OBJECT_BYTES as *const NullObjectBytes as usize +} diff --git a/crates/perry-runtime/src/object/prototype_chain.rs b/crates/perry-runtime/src/object/prototype_chain.rs index 29a9ce8084..f5ee37dffa 100644 --- a/crates/perry-runtime/src/object/prototype_chain.rs +++ b/crates/perry-runtime/src/object/prototype_chain.rs @@ -302,6 +302,9 @@ fn object_set_static_prototype_impl(obj_ptr: usize, proto_bits: u64, link_kind: /// when no explicit prototype has been recorded (the object still has its /// default prototype); `Some(TAG_NULL)` when it was explicitly set to `null`. pub fn object_static_prototype(obj_ptr: usize) -> Option { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_decoded_pointer(obj_ptr); + } // #6759 Phase B: a shaped object answers from its own meta record — two // dependent loads, no global latch, no mutex — and NEVER has a residual // registry entry (the write path classifies identically), so a meta diff --git a/crates/perry-runtime/src/proxy.rs b/crates/perry-runtime/src/proxy.rs index 849c0c32d4..bf7b2e2757 100644 --- a/crates/perry-runtime/src/proxy.rs +++ b/crates/perry-runtime/src/proxy.rs @@ -479,6 +479,11 @@ pub extern "C" fn js_proxy_new(target: f64, handler: f64) -> f64 { PROXY_FULL_TRACE_ACTIVE.with(|active| active.set(true)); } let encoded = encode_proxy_id(id) as u64; + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::Proxy, + ); + } f64::from_bits(POINTER_TAG | (encoded & POINTER_MASK)) }) } diff --git a/crates/perry-runtime/src/shared_sab.rs b/crates/perry-runtime/src/shared_sab.rs index 60a4ac6c64..bf584c9649 100644 --- a/crates/perry-runtime/src/shared_sab.rs +++ b/crates/perry-runtime/src/shared_sab.rs @@ -84,6 +84,9 @@ pub fn alloc_shared_sab(size: u32) -> *mut BufferHeader { .lock() .unwrap_or_else(|e| e.into_inner()) .insert(buf as usize); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Sab); + } buf } diff --git a/crates/perry-runtime/src/symbol.rs b/crates/perry-runtime/src/symbol.rs index 3abb55867f..6725d3a010 100644 --- a/crates/perry-runtime/src/symbol.rs +++ b/crates/perry-runtime/src/symbol.rs @@ -332,6 +332,11 @@ pub fn well_known_symbol(short_name: &str) -> *mut SymbolHeader { id: next_id(), }); let sym_ptr = Box::into_raw(boxed); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::SymbolGlobal, + ); + } // Fully initialize the symbol's side tables BEFORE publishing it in // the cache. A concurrent reader that observes the pointer via the // cache must already see a complete view (description present, @@ -650,6 +655,11 @@ pub fn intl_legacy_constructed_symbol() -> f64 { id: next_id(), }); let sym_ptr = Box::into_raw(boxed) as usize; + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::SymbolGlobal, + ); + } record_registered_symbol_description(sym_ptr, "IntlLegacyConstructedSymbol"); register_symbol_pointer(sym_ptr); *guard = Some(sym_ptr); diff --git a/crates/perry-runtime/src/symbol/constructors.rs b/crates/perry-runtime/src/symbol/constructors.rs index 34c8fa7026..e071523a34 100644 --- a/crates/perry-runtime/src/symbol/constructors.rs +++ b/crates/perry-runtime/src/symbol/constructors.rs @@ -107,6 +107,11 @@ pub unsafe extern "C" fn js_symbol_for(key_f64: f64) -> f64 { id: next_id(), }); let sym_ptr = Box::into_raw(boxed); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed( + crate::hot_diag::ReceiverReprFamily::SymbolGlobal, + ); + } // Fully initialize the side tables BEFORE publishing the pointer in // the registry. Otherwise a concurrent `Symbol.for("same_key")` on // another thread can see the pointer via the registry but get None diff --git a/crates/perry-runtime/src/text.rs b/crates/perry-runtime/src/text.rs index cb1b098a79..98fb16f1ae 100644 --- a/crates/perry-runtime/src/text.rs +++ b/crates/perry-runtime/src/text.rs @@ -104,6 +104,9 @@ pub(crate) fn text_encoder_string_ptr(value: f64) -> *const StringHeader { /// decoder sentinel purely for debuggability. #[no_mangle] pub extern "C" fn js_text_encoder_new() -> i64 { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Text); + } TEXT_ENCODER_SENTINEL_ID } @@ -172,6 +175,9 @@ fn register_decoder( id }; DECODER_REGISTRY.lock().unwrap().insert(id, state); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Text); + } id } diff --git a/crates/perry-runtime/src/timer.rs b/crates/perry-runtime/src/timer.rs index d0bd6ce00b..e07fb14677 100644 --- a/crates/perry-runtime/src/timer.rs +++ b/crates/perry-runtime/src/timer.rs @@ -530,6 +530,9 @@ fn next_timer_id() -> i64 { let mut next = NEXT_TIMER_ID.lock().unwrap(); let current = *next; *next += 1; + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Timer); + } current } diff --git a/crates/perry-runtime/src/tui/hooks.rs b/crates/perry-runtime/src/tui/hooks.rs index 7d9f8ebdc9..8e660ac249 100644 --- a/crates/perry-runtime/src/tui/hooks.rs +++ b/crates/perry-runtime/src/tui/hooks.rs @@ -71,6 +71,10 @@ enum HookSlot { } static SLOTS: Mutex> = Mutex::new(Vec::new()); + +pub(crate) fn contains_handle(handle: i64) -> bool { + handle > 0 && (handle as usize) <= crate::gc::lock_gc_root_registry(&SLOTS).len() +} /// Per-frame hook index, reset by the run loop before each component call. static NEXT_HOOK_IDX: AtomicUsize = AtomicUsize::new(0); @@ -547,6 +551,9 @@ pub extern "C" fn js_perry_tui_use_ref(initial: f64) -> i64 { value_bits: initial.to_bits(), }; } + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } (idx as i64) + 1 } @@ -593,6 +600,9 @@ const APP_HANDLE: i64 = 1; /// class_filter: Some("App") rows. #[no_mangle] pub extern "C" fn js_perry_tui_use_app() -> i64 { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } APP_HANDLE } @@ -630,6 +640,9 @@ const STDOUT_HANDLE: i64 = 2; /// Some("Stdout") rows. #[no_mangle] pub extern "C" fn js_perry_tui_use_stdout() -> i64 { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } STDOUT_HANDLE } @@ -813,6 +826,9 @@ const FOCUS_MANAGER_HANDLE: i64 = 3; #[no_mangle] pub extern "C" fn js_perry_tui_use_focus_manager() -> i64 { + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } FOCUS_MANAGER_HANDLE } diff --git a/crates/perry-runtime/src/tui/mod.rs b/crates/perry-runtime/src/tui/mod.rs index 88aa7d8fb1..963a233728 100644 --- a/crates/perry-runtime/src/tui/mod.rs +++ b/crates/perry-runtime/src/tui/mod.rs @@ -43,3 +43,9 @@ pub mod run; pub mod state; pub mod style; pub mod tree; + +pub(crate) fn is_known_handle(handle: i64) -> bool { + tree::contains_handle(handle) + || state::contains_handle(handle) + || hooks::contains_handle(handle) +} diff --git a/crates/perry-runtime/src/tui/state.rs b/crates/perry-runtime/src/tui/state.rs index c61158191b..9cf3a3e563 100644 --- a/crates/perry-runtime/src/tui/state.rs +++ b/crates/perry-runtime/src/tui/state.rs @@ -101,9 +101,16 @@ pub extern "C" fn js_perry_tui_state_alloc(initial: f64) -> i64 { let mut s = crate::gc::lock_gc_root_registry(&SLOTS); let h = s.len() as i64; s.push(initial.to_bits()); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } h } +pub(crate) fn contains_handle(handle: i64) -> bool { + handle >= 0 && (handle as usize) < crate::gc::lock_gc_root_registry(&SLOTS).len() +} + /// Read a state slot. Returns the stored NaN-boxed value. Out-of-range /// handles return undefined. #[no_mangle] diff --git a/crates/perry-runtime/src/tui/tree.rs b/crates/perry-runtime/src/tui/tree.rs index 59c5ef508e..2d71c0ad9d 100644 --- a/crates/perry-runtime/src/tui/tree.rs +++ b/crates/perry-runtime/src/tui/tree.rs @@ -51,6 +51,9 @@ per_test_global! { pub fn register(node: Node) -> i64 { let h = NEXT_HANDLE.fetch_add(1, Ordering::AcqRel); REGISTRY.lock().unwrap().push((h, node)); + if crate::hot_diag::receiver_repr_on() { + crate::hot_diag::receiver_repr_note_constructed(crate::hot_diag::ReceiverReprFamily::Tui); + } h } @@ -62,6 +65,10 @@ pub fn lookup(handle: i64) -> Option { .find_map(|(h, n)| if *h == handle { Some(n.clone()) } else { None }) } +pub(crate) fn contains_handle(handle: i64) -> bool { + REGISTRY.lock().unwrap().iter().any(|(h, _)| *h == handle) +} + /// Append a child handle to a Box node. No-op if the handle isn't a /// Box (silently ignored — matches the "we accept anything, you check /// at the call site" convention from the rest of Perry's FFI). diff --git a/crates/perry-runtime/src/value/addr_class.rs b/crates/perry-runtime/src/value/addr_class.rs index b128e48802..dd5796d312 100644 --- a/crates/perry-runtime/src/value/addr_class.rs +++ b/crates/perry-runtime/src/value/addr_class.rs @@ -91,6 +91,21 @@ pub fn is_small_handle(addr: usize) -> bool { (1..HANDLE_BAND_MAX).contains(&addr) } +#[inline(always)] +pub fn is_common_handle_band(addr: usize) -> bool { + (1..COMMON_HANDLE_BAND_END).contains(&addr) +} + +#[inline(always)] +pub fn is_fetch_handle_band(addr: usize) -> bool { + (FETCH_HANDLE_BAND_START..FETCH_HANDLE_BAND_END).contains(&addr) +} + +#[inline(always)] +pub fn is_zlib_handle_band(addr: usize) -> bool { + (ZLIB_HANDLE_BAND_START..ZLIB_HANDLE_BAND_END).contains(&addr) +} + /// Complement of [`is_handle_band`]: the payload is above the handle band and /// may be treated as a candidate heap address (subject to /// [`is_valid_obj_ptr`] / registry checks as the call site requires). Note diff --git a/crates/perry-stdlib/src/common/handle.rs b/crates/perry-stdlib/src/common/handle.rs index 254b03f015..62fd3ddd15 100644 --- a/crates/perry-stdlib/src/common/handle.rs +++ b/crates/perry-stdlib/src/common/handle.rs @@ -43,12 +43,22 @@ fn next_handle_id() -> Handle { pub fn register_handle(value: T) -> Handle { let handle = next_handle_id(); HANDLES.insert(handle, Box::new(value)); + if perry_runtime::hot_diag::receiver_repr_on() { + perry_runtime::hot_diag::receiver_repr_note_constructed( + perry_runtime::hot_diag::ReceiverReprFamily::Common, + ); + } handle } /// Register an object with a specific ID pub fn register_handle_with_id(value: T, handle: Handle) -> Handle { HANDLES.insert(handle, Box::new(value)); + if perry_runtime::hot_diag::receiver_repr_on() { + perry_runtime::hot_diag::receiver_repr_note_constructed( + perry_runtime::hot_diag::ReceiverReprFamily::Common, + ); + } handle } diff --git a/crates/perry-stdlib/src/fetch/mod.rs b/crates/perry-stdlib/src/fetch/mod.rs index a467c21ffb..20af346cb9 100644 --- a/crates/perry-stdlib/src/fetch/mod.rs +++ b/crates/perry-stdlib/src/fetch/mod.rs @@ -227,6 +227,11 @@ fn alloc_fetch_handle_id() -> usize { panic!("Web Fetch handle id range exhausted"); } *id_guard += 1; + if perry_runtime::hot_diag::receiver_repr_on() { + perry_runtime::hot_diag::receiver_repr_note_constructed( + perry_runtime::hot_diag::ReceiverReprFamily::Fetch, + ); + } id } diff --git a/crates/perry-stdlib/src/zlib.rs b/crates/perry-stdlib/src/zlib.rs index 14e4aac6e6..b254838b3f 100644 --- a/crates/perry-stdlib/src/zlib.rs +++ b/crates/perry-stdlib/src/zlib.rs @@ -726,6 +726,11 @@ fn next_zlib_id() -> i64 { panic!("zlib stream handle id range exhausted"); } *g += 1; + if perry_runtime::hot_diag::receiver_repr_on() { + perry_runtime::hot_diag::receiver_repr_note_constructed( + perry_runtime::hot_diag::ReceiverReprFamily::Zlib, + ); + } id } diff --git a/scripts/native_result_ledger.py b/scripts/native_result_ledger.py new file mode 100644 index 0000000000..5b3e166c1a --- /dev/null +++ b/scripts/native_result_ledger.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +"""Check the typed ledger for the native-table rows formerly named NR_PTR. + +The Rust table is the executable declaration. The TSV is the provider-side +inventory: it pins each runtime symbol to the result class and to the source +file whose implementation was read. Keeping both sides checked prevents a +new row from silently inheriting the old, storage-free `NR_PTR` contract. +""" + +from __future__ import annotations + +import argparse +import re +import tempfile +from dataclasses import dataclass +from pathlib import Path + + +REPO = Path(__file__).resolve().parents[1] +TABLE_DIR = Path("crates/perry-codegen/src/lower_call/native_table") +LEDGER = Path("scripts/native_result_ledger.tsv") +# The campaign's textual census reported 372 `ret: NR_PTR` hits. Two were +# prose comments in fastify.rs, while one real row uses the positional `cr(...)` +# helper, leaving 371 executable declarations. The scanner parses declarations, +# not comments, and includes that helper row. +EXPECTED_ROWS = 371 +EXPECTED_PROVIDERS = 322 +KINDS = { + "NR_GCPTR", + "NR_NULLABLE_GCPTR", + "NR_HANDLE_ID", + "NR_FOREIGN_PTR", + "NR_JS_VALUE", +} +RET_RE = re.compile(r"\bret:\s*(NR_[A-Z0-9_]+)\b") +RUNTIME_RE = re.compile(r'\bruntime:\s*"([^"]+)"') + + +class LedgerError(RuntimeError): + pass + + +@dataclass(frozen=True) +class Row: + source: Path + line: int + runtime: str + kind: str + + +@dataclass(frozen=True) +class Provider: + kind: str + source: Path + rust_return: str + + +def scan_rows(root: Path, table_dir: Path) -> list[Row]: + rows: list[Row] = [] + for source in sorted((root / table_dir).rglob("*.rs")): + lines = source.read_text().splitlines() + for index, line in enumerate(lines): + if line.lstrip().startswith("//"): + continue + ret = RET_RE.search(line) + positional = re.fullmatch(r"\s*(NR_[A-Z0-9_]+),\s*", line) + if not ret and not positional: + continue + kind = (ret or positional).group(1) + if kind == "NR_PTR": + raise LedgerError( + f"{source.relative_to(root)}:{index + 1}: legacy NR_PTR row" + ) + if kind not in KINDS: + continue + runtime = None + if ret: + for previous in reversed(lines[:index]): + match = RUNTIME_RE.search(previous) + if match: + runtime = match.group(1) + break + if "NativeModSig {" in previous: + break + else: + strings: list[str] = [] + for previous in reversed(lines[:index]): + strings.extend(re.findall(r'"([^"]+)"', previous)) + if re.search(r"\bcr\s*\(", previous): + break + if len(strings) >= 2: + runtime = strings[-2] + if runtime is None: + raise LedgerError( + f"{source.relative_to(root)}:{index + 1}: typed row has no runtime symbol" + ) + rows.append(Row(source.relative_to(root), index + 1, runtime, kind)) + return rows + + +def read_providers(root: Path, ledger_path: Path) -> dict[str, Provider]: + path = root / ledger_path + providers: dict[str, Provider] = {} + for line_number, line in enumerate(path.read_text().splitlines(), 1): + if not line or line.startswith("#"): + continue + fields = line.split("\t") + if len(fields) != 4: + raise LedgerError(f"{ledger_path}:{line_number}: expected four TSV fields") + symbol, kind, source_text, rust_return = fields + if symbol in providers: + raise LedgerError(f"{ledger_path}:{line_number}: duplicate provider {symbol}") + if kind not in KINDS: + raise LedgerError( + f"{ledger_path}:{line_number}: provider {symbol} lacks a result class" + ) + source = Path(source_text) + provider_path = root / source + if not provider_path.is_file(): + raise LedgerError( + f"{ledger_path}:{line_number}: provider source does not exist: {source}" + ) + definition = re.compile(rf"\bfn\s+{re.escape(symbol)}\s*\(") + if not definition.search(provider_path.read_text()): + raise LedgerError( + f"{ledger_path}:{line_number}: {source} does not declare {symbol}" + ) + providers[symbol] = Provider(kind, source, rust_return) + return providers + + +def check( + root: Path, + table_dir: Path = TABLE_DIR, + ledger_path: Path = LEDGER, + expected_rows: int = EXPECTED_ROWS, + expected_providers: int = EXPECTED_PROVIDERS, +) -> dict[str, int]: + rows = scan_rows(root, table_dir) + providers = read_providers(root, ledger_path) + if len(rows) != expected_rows: + raise LedgerError(f"expected {expected_rows} classified rows, found {len(rows)}") + if len(providers) != expected_providers: + raise LedgerError( + f"expected {expected_providers} classified providers, found {len(providers)}" + ) + + used: set[str] = set() + counts = {kind: 0 for kind in sorted(KINDS)} + for row in rows: + provider = providers.get(row.runtime) + if provider is None: + raise LedgerError( + f"{row.source}:{row.line}: provider {row.runtime} lacks a class" + ) + if provider.kind != row.kind: + raise LedgerError( + f"{row.source}:{row.line}: {row.runtime} is {row.kind}, " + f"provider ledger says {provider.kind}" + ) + used.add(row.runtime) + counts[row.kind] += 1 + + stale = sorted(set(providers) - used) + if stale: + raise LedgerError(f"stale provider ledger entries: {', '.join(stale)}") + return {kind: count for kind, count in counts.items() if count} + + +def self_test() -> None: + with tempfile.TemporaryDirectory(prefix="native-result-ledger-") as tmp: + root = Path(tmp) + tables = root / "tables" + providers = root / "providers" + tables.mkdir() + providers.mkdir() + provider = providers / "fixture.rs" + provider.write_text('pub extern "C" fn fixture_provider() -> *mut u8 { panic!() }\n') + ledger = root / "ledger.tsv" + ledger.write_text( + "# runtime_symbol\tresult_kind\tprovider_source\tprovider_return\n" + "fixture_provider\tNR_GCPTR\tproviders/fixture.rs\t*mut u8\n" + ) + good = ( + 'NativeModSig {\n runtime: "fixture_provider",\n' + " ret: NR_GCPTR,\n}\n" + ) + table = tables / "fixture.rs" + table.write_text(good) + check(root, Path("tables"), Path("ledger.tsv"), 1, 1) + + # Sabotage: restoring the erased result kind must turn the gate red. + table.write_text(good.replace("NR_GCPTR", "NR_PTR")) + try: + check(root, Path("tables"), Path("ledger.tsv"), 1, 1) + except LedgerError as error: + if "legacy NR_PTR" not in str(error): + raise + else: + raise LedgerError("self-test accepted a planted NR_PTR row") + + # Sabotage: a table/provider disagreement must also turn it red. + table.write_text(good.replace("NR_GCPTR", "NR_HANDLE_ID")) + try: + check(root, Path("tables"), Path("ledger.tsv"), 1, 1) + except LedgerError as error: + if "provider ledger says" not in str(error): + raise + else: + raise LedgerError("self-test accepted an unclassified provider declaration") + print("native_result_ledger self-test passed (NR_PTR and provider-class sabotages rejected)") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--self-test", action="store_true") + args = parser.parse_args() + try: + if args.self_test: + self_test() + else: + counts = check(REPO) + rendered = " ".join(f"{kind}={count}" for kind, count in sorted(counts.items())) + print( + "native_result_ledger passed: " + f"{EXPECTED_ROWS} rows, {EXPECTED_PROVIDERS} providers; {rendered}" + ) + except (LedgerError, OSError) as error: + print(f"native_result_ledger FAILED: {error}") + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/native_result_ledger.tsv b/scripts/native_result_ledger.tsv new file mode 100644 index 0000000000..45bcc5c586 --- /dev/null +++ b/scripts/native_result_ledger.tsv @@ -0,0 +1,323 @@ +# runtime_symbol result_kind provider_source provider_return +backOff NR_GCPTR crates/perry-ext-exponential-backoff/src/lib.rs *mut Promise +js_argon2_hash NR_GCPTR crates/perry-ext-argon2/src/lib.rs *mut Promise +js_argon2_verify NR_GCPTR crates/perry-ext-argon2/src/lib.rs *mut Promise +js_async_hook_disable NR_FOREIGN_PTR crates/perry-runtime/src/async_hooks.rs i64 +js_async_hook_enable NR_FOREIGN_PTR crates/perry-runtime/src/async_hooks.rs i64 +js_async_hooks_create_hook NR_FOREIGN_PTR crates/perry-runtime/src/async_hooks.rs i64 +js_async_resource_bind NR_NULLABLE_GCPTR crates/perry-runtime/src/async_hooks.rs i64 +js_async_resource_emit_destroy NR_FOREIGN_PTR crates/perry-runtime/src/async_hooks.rs i64 +js_bcrypt_compare NR_GCPTR crates/perry-ext-bcrypt/src/lib.rs *mut Promise +js_bcrypt_hash NR_GCPTR crates/perry-ext-bcrypt/src/lib.rs *mut Promise +js_buffer_copy_bytes_from NR_GCPTR crates/perry-runtime/src/buffer/copy_bytes.rs *mut BufferHeader +js_buffer_transcode NR_GCPTR crates/perry-runtime/src/buffer/transcode.rs *mut BufferHeader +js_bun_build NR_GCPTR crates/perry-ext-typescript/src/bun.rs *mut Promise +js_bun_serve NR_HANDLE_ID crates/perry-ext-http/src/server/bun_server.rs i64 +js_bun_sqlite_database_call NR_HANDLE_ID crates/perry-stdlib/src/sqlite/bun.rs Handle +js_bun_sqlite_database_query NR_HANDLE_ID crates/perry-stdlib/src/sqlite/bun.rs Handle +js_bun_sqlite_database_run NR_GCPTR crates/perry-stdlib/src/sqlite/bun.rs *mut ObjectHeader +js_bun_sqlite_database_transaction NR_GCPTR crates/perry-stdlib/src/sqlite/bun.rs *mut ClosureHeader +js_bun_sqlite_statement_values NR_GCPTR crates/perry-stdlib/src/sqlite/bun.rs *mut ArrayHeader +js_bun_tcp_listen NR_HANDLE_ID crates/perry-ext-net/src/bun_tcp.rs i64 +js_bun_transpiler_new NR_HANDLE_ID crates/perry-ext-typescript/src/bun.rs Handle +js_cheerio_load NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_select NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_children NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_eq NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_find NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_first NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_last NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_cheerio_selection_parent NR_HANDLE_ID crates/perry-ext-cheerio/src/lib.rs Handle +js_commander_action NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_args_array NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_argument NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_command NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_description NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_name NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_option NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_opts NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_parse NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_required_option NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_commander_version NR_HANDLE_ID crates/perry-ext-commander/src/lib.rs Handle +js_cron_schedule NR_HANDLE_ID crates/perry-ext-cron/src/lib.rs Handle +js_decimal_abs NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_ceil NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_div_value NR_HANDLE_ID crates/perry-stdlib/src/decimal.rs Handle +js_decimal_floor NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_minus_value NR_HANDLE_ID crates/perry-stdlib/src/decimal.rs Handle +js_decimal_mod_value NR_HANDLE_ID crates/perry-stdlib/src/decimal.rs Handle +js_decimal_neg NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_plus_value NR_HANDLE_ID crates/perry-stdlib/src/decimal.rs Handle +js_decimal_pow NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_round NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_sqrt NR_HANDLE_ID crates/perry-ext-decimal/src/lib.rs Handle +js_decimal_times_value NR_HANDLE_ID crates/perry-stdlib/src/decimal.rs Handle +js_domain_add NR_HANDLE_ID crates/perry-stdlib/src/domain.rs Handle +js_domain_create NR_HANDLE_ID crates/perry-stdlib/src/domain.rs Handle +js_domain_on NR_HANDLE_ID crates/perry-stdlib/src/domain.rs Handle +js_domain_remove NR_HANDLE_ID crates/perry-stdlib/src/domain.rs Handle +js_ethers_wallet_create_random NR_JS_VALUE crates/perry-ext-ethers/src/lib.rs JsValue +js_event_emitter_event_names NR_GCPTR crates/perry-ext-events/src/lib.rs *mut ArrayHeader +js_event_emitter_listeners NR_GCPTR crates/perry-ext-events/src/lib.rs *mut ArrayHeader +js_event_emitter_new NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_on NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_once NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_prepend_listener NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_prepend_once_listener NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_raw_listeners NR_GCPTR crates/perry-ext-events/src/lib.rs *mut ArrayHeader +js_event_emitter_remove_all_listeners NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_remove_listener NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_event_emitter_set_max_listeners NR_HANDLE_ID crates/perry-ext-events/src/lib.rs Handle +js_events_add_abort_listener NR_GCPTR crates/perry-ext-events/src/module_on.rs i64 +js_events_get_event_listeners NR_GCPTR crates/perry-ext-events/src/module_helpers.rs *mut ArrayHeader +js_events_on NR_GCPTR crates/perry-ext-events/src/module_on.rs *mut ArrayHeader +js_events_once NR_GCPTR crates/perry-ext-events/src/lib.rs *mut Promise +js_ext_net_create_server NR_HANDLE_ID crates/perry-ext-net/src/lib.rs i64 +js_ext_net_socket_connect NR_HANDLE_ID crates/perry-ext-net/src/lib.rs i64 +js_ext_net_socket_once NR_HANDLE_ID crates/perry-ext-net/src/handle_exports.rs i64 +js_ext_tls_connect NR_HANDLE_ID crates/perry-ext-net/src/tls.rs i64 +js_fastify_app_server NR_HANDLE_ID crates/perry-ext-fastify/src/app.rs Handle +js_fastify_create_with_opts NR_HANDLE_ID crates/perry-ext-fastify/src/app.rs Handle +js_fastify_reply_header NR_HANDLE_ID crates/perry-ext-fastify/src/context.rs Handle +js_fastify_reply_status NR_HANDLE_ID crates/perry-ext-fastify/src/context.rs Handle +js_fastify_reply_type NR_HANDLE_ID crates/perry-ext-fastify/src/context.rs Handle +js_fastify_req_headers NR_JS_VALUE crates/perry-ext-fastify/src/context.rs i64 +js_http_agent_create_connection NR_HANDLE_ID crates/perry-ext-http/src/agent.rs i64 +js_http_agent_create_socket NR_HANDLE_ID crates/perry-ext-http/src/agent.rs i64 +js_http_agent_destroy NR_HANDLE_ID crates/perry-ext-http/src/agent.rs Handle +js_http_agent_free_sockets NR_JS_VALUE crates/perry-ext-http/src/agent.rs f64 +js_http_agent_new NR_HANDLE_ID crates/perry-ext-http/src/agent.rs Handle +js_http_agent_noop_self NR_HANDLE_ID crates/perry-ext-http/src/agent.rs Handle +js_http_agent_requests NR_JS_VALUE crates/perry-ext-http/src/agent.rs f64 +js_http_agent_sockets NR_JS_VALUE crates/perry-ext-http/src/agent.rs f64 +js_http_client_request_destroy NR_HANDLE_ID crates/perry-ext-http/src/client_request_surface.rs Handle +js_http_client_request_end_full NR_HANDLE_ID crates/perry-ext-http/src/client_outgoing.rs Handle +js_http_get_overload NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_http_incoming_message_set_encoding NR_HANDLE_ID crates/perry-ext-http/src/client_surface.rs Handle +js_http_on NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_http_once NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_http_request_overload NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_http_set_header NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_http_set_timeout_full NR_HANDLE_ID crates/perry-ext-http/src/client_outgoing.rs Handle +js_https_agent_new NR_HANDLE_ID crates/perry-ext-http/src/agent.rs Handle +js_https_get_overload NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_https_request_overload NR_HANDLE_ID crates/perry-ext-http/src/lib.rs Handle +js_ioredis_decr NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_del NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_exists NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_expire NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_get NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_incr NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_new NR_HANDLE_ID crates/perry-ext-ioredis/src/lib.rs Handle +js_ioredis_quit NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_ioredis_set NR_GCPTR crates/perry-ext-ioredis/src/lib.rs *mut Promise +js_lodash_chunk NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_compact NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_drop NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_flatten NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_range NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_reverse NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_tail NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_take NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_times NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lodash_uniq NR_GCPTR crates/perry-stdlib/src/lodash.rs *mut ArrayHeader +js_lru_cache_new NR_HANDLE_ID crates/perry-ext-lru-cache/src/lib.rs Handle +js_lru_cache_set NR_HANDLE_ID crates/perry-ext-lru-cache/src/lib.rs Handle +js_mongodb_client_close NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_client_db NR_HANDLE_ID crates/perry-ext-mongodb/src/lib.rs Handle +js_mongodb_collection_count_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_delete_many_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_delete_one_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_find_one_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_find_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_insert_many_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_insert_one_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_update_many_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_collection_update_one_value NR_GCPTR crates/perry-ext-mongodb/src/lib.rs *mut Promise +js_mongodb_db_collection NR_HANDLE_ID crates/perry-ext-mongodb/src/lib.rs Handle +js_mysql2_connection_begin_transaction NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_connection_commit NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_connection_end NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_connection_execute NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_connection_query NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_connection_rollback NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_create_connection NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_create_pool NR_HANDLE_ID crates/perry-ext-mysql2/src/lib.rs Handle +js_mysql2_pool_connection_execute NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_pool_connection_query NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_pool_end NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_pool_execute NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_pool_get_connection NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_mysql2_pool_query NR_GCPTR crates/perry-ext-mysql2/src/lib.rs *mut Promise +js_net_block_list_new NR_HANDLE_ID crates/perry-ext-net/src/classes.rs i64 +js_net_block_list_rules NR_GCPTR crates/perry-ext-net/src/classes.rs *mut ArrayHeader +js_net_server_listeners NR_GCPTR crates/perry-ext-net/src/lifecycle.rs i64 +js_net_server_noop_self NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_server_once NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_server_raw_listeners NR_GCPTR crates/perry-ext-net/src/lifecycle.rs i64 +js_net_server_remove_all_listeners NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_server_remove_listener NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_address_new NR_HANDLE_ID crates/perry-ext-net/src/classes.rs i64 +js_net_socket_alloc NR_HANDLE_ID crates/perry-ext-net/src/lib.rs i64 +js_net_socket_listeners NR_GCPTR crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_noop_self NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_socket_raw_listeners NR_GCPTR crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_ref NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_socket_remove_all_listeners NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_remove_listener NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_reset_and_destroy NR_HANDLE_ID crates/perry-ext-net/src/lifecycle.rs i64 +js_net_socket_set_encoding NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_socket_set_timeout NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_socket_set_type_of_service NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_net_socket_unref NR_HANDLE_ID crates/perry-ext-net/src/option_setters.rs i64 +js_node_forge_certificate_from_pem NR_JS_VALUE crates/perry-ext-node-forge/src/lib.rs JsValue +js_node_forge_create_certificate NR_JS_VALUE crates/perry-ext-node-forge/src/lib.rs JsValue +js_node_forge_generate_key_pair NR_JS_VALUE crates/perry-ext-node-forge/src/lib.rs JsValue +js_node_forge_md_sha256_create NR_JS_VALUE crates/perry-ext-node-forge/src/lib.rs JsValue +js_node_forge_private_key_from_pem NR_JS_VALUE crates/perry-ext-node-forge/src/lib.rs JsValue +js_node_http2_connect NR_HANDLE_ID crates/perry-ext-http/src/server/http2_server/session.rs i64 +js_node_http2_create_secure_server NR_HANDLE_ID crates/perry-ext-http/src/server/http2_server.rs i64 +js_node_http2_create_server NR_HANDLE_ID crates/perry-ext-http/src/server/http2_server.rs i64 +js_node_http2_get_packed_settings NR_GCPTR crates/perry-ext-http/src/server/http2_settings.rs *mut BufferHeader +js_node_http2_server_listen NR_HANDLE_ID crates/perry-ext-http/src/server/http2_server.rs i64 +js_node_http_create_server_with_options NR_HANDLE_ID crates/perry-ext-http/src/server/server.rs i64 +js_node_http_im_pause_self NR_HANDLE_ID crates/perry-ext-http/src/server/request.rs i64 +js_node_http_im_resume_self NR_HANDLE_ID crates/perry-ext-http/src/server/request.rs i64 +js_node_http_im_set_timeout NR_HANDLE_ID crates/perry-ext-http/src/server/request.rs i64 +js_node_http_res_append_header NR_HANDLE_ID crates/perry-ext-http/src/server/response.rs i64 +js_node_http_res_set_header_self NR_HANDLE_ID crates/perry-ext-http/src/server/response.rs i64 +js_node_http_res_set_headers NR_HANDLE_ID crates/perry-ext-http/src/server/response.rs i64 +js_node_http_res_set_timeout NR_HANDLE_ID crates/perry-ext-http/src/server/response.rs i64 +js_node_http_server_listen NR_HANDLE_ID crates/perry-ext-http/src/server/server.rs i64 +js_node_http_server_ref NR_HANDLE_ID crates/perry-ext-http/src/server/server.rs i64 +js_node_http_server_set_timeout_method NR_HANDLE_ID crates/perry-ext-http/src/server/server.rs i64 +js_node_http_server_unref NR_HANDLE_ID crates/perry-ext-http/src/server/server.rs i64 +js_node_https_create_server NR_HANDLE_ID crates/perry-ext-http/src/server/https_server.rs i64 +js_node_https_server_listen NR_HANDLE_ID crates/perry-ext-http/src/server/https_server.rs i64 +js_node_https_server_ref NR_HANDLE_ID crates/perry-ext-http/src/server/https_server.rs i64 +js_node_https_server_set_timeout_method NR_HANDLE_ID crates/perry-ext-http/src/server/https_server.rs i64 +js_node_https_server_unref NR_HANDLE_ID crates/perry-ext-http/src/server/https_server.rs i64 +js_node_sqlite_database_sync_call NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_db.rs Handle +js_node_sqlite_database_sync_create_session NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_stmt_session.rs Handle +js_node_sqlite_database_sync_create_tag_store NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_tag_store.rs Handle +js_node_sqlite_database_sync_limits NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_stmt_session.rs Handle +js_node_sqlite_database_sync_prepare NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_db.rs Handle +js_node_sqlite_database_sync_serialize NR_GCPTR crates/perry-stdlib/src/sqlite/node_db.rs *mut BufferHeader +js_node_sqlite_session_call NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_stmt_session.rs Handle +js_node_sqlite_session_changeset NR_GCPTR crates/perry-stdlib/src/sqlite/node_stmt_session.rs *mut BufferHeader +js_node_sqlite_session_patchset NR_GCPTR crates/perry-stdlib/src/sqlite/node_stmt_session.rs *mut BufferHeader +js_node_sqlite_sql_tag_store_all NR_GCPTR crates/perry-stdlib/src/sqlite/node_tag_store.rs *mut ArrayHeader +js_node_sqlite_sql_tag_store_db NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_tag_store.rs Handle +js_node_sqlite_sql_tag_store_run NR_GCPTR crates/perry-stdlib/src/sqlite/node_tag_store.rs *mut ObjectHeader +js_node_sqlite_statement_sync_all NR_GCPTR crates/perry-stdlib/src/sqlite/node_stmt_session.rs *mut ArrayHeader +js_node_sqlite_statement_sync_call NR_HANDLE_ID crates/perry-stdlib/src/sqlite/node_stmt_session.rs Handle +js_node_sqlite_statement_sync_columns NR_GCPTR crates/perry-stdlib/src/sqlite/node_stmt_session.rs *mut ArrayHeader +js_node_sqlite_statement_sync_run NR_GCPTR crates/perry-stdlib/src/sqlite/node_stmt_session.rs *mut ObjectHeader +js_node_stream_method_event_names NR_GCPTR crates/perry-runtime/src/node_stream_event_emitter.rs i64 +js_node_stream_method_listeners NR_GCPTR crates/perry-runtime/src/node_stream_event_emitter.rs i64 +js_node_stream_method_raw_listeners NR_GCPTR crates/perry-runtime/src/node_stream_event_emitter.rs i64 +js_nodemailer_send_mail NR_GCPTR crates/perry-ext-nodemailer/src/lib.rs *mut Promise +js_nodemailer_verify NR_GCPTR crates/perry-ext-nodemailer/src/lib.rs *mut Promise +js_os_user_info_options NR_GCPTR crates/perry-runtime/src/os.rs *mut ObjectHeader +js_perry_embedded_files NR_GCPTR crates/perry-runtime/src/embedded.rs *mut crate::array::ArrayHeader +js_perry_read_embedded NR_NULLABLE_GCPTR crates/perry-runtime/src/embedded.rs *mut crate::buffer::BufferHeader +js_perry_tui_animated_spinner NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_box NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_input NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_input_at NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_list NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_progress_bar NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_select NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_spacer NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_spinner NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_state_alloc NR_HANDLE_ID crates/perry-runtime/src/tui/state.rs i64 +js_perry_tui_table NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_tabs NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_text NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_text_area NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_text_styled NR_HANDLE_ID crates/perry-runtime/src/tui/ffi.rs i64 +js_perry_tui_use_app NR_HANDLE_ID crates/perry-runtime/src/tui/hooks.rs i64 +js_perry_tui_use_focus_manager NR_HANDLE_ID crates/perry-runtime/src/tui/hooks.rs i64 +js_perry_tui_use_ref NR_HANDLE_ID crates/perry-runtime/src/tui/hooks.rs i64 +js_perry_tui_use_state_tuple NR_GCPTR crates/perry-runtime/src/tui/hooks.rs i64 +js_perry_tui_use_stdout NR_HANDLE_ID crates/perry-runtime/src/tui/hooks.rs i64 +js_pg_client_connect NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_client_end NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_client_query NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_connect NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_create_pool NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_pool_end NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_pg_pool_query NR_GCPTR crates/perry-ext-pg/src/lib.rs *mut Promise +js_process_event_names NR_GCPTR crates/perry-runtime/src/os/os_process_emitter.rs *mut ArrayHeader +js_process_listeners NR_GCPTR crates/perry-runtime/src/os/os_process_emitter.rs *mut ArrayHeader +js_process_raw_listeners NR_GCPTR crates/perry-runtime/src/os/os_process_emitter.rs *mut ArrayHeader +js_querystring_parse NR_GCPTR crates/perry-stdlib/src/querystring.rs *mut ObjectHeader +js_querystring_unescape_buffer NR_GCPTR crates/perry-stdlib/src/querystring.rs *mut BufferHeader +js_readline_create_interface NR_HANDLE_ID crates/perry-stdlib/src/readline/mod.rs i64 +js_readline_get_cursor_pos NR_GCPTR crates/perry-stdlib/src/readline/mod.rs i64 +js_readline_iterator NR_HANDLE_ID crates/perry-stdlib/src/readline/mod.rs i64 +js_readline_pause NR_HANDLE_ID crates/perry-stdlib/src/readline/mod.rs i64 +js_readline_resume NR_HANDLE_ID crates/perry-stdlib/src/readline/mod.rs i64 +js_sharp_auto_orient NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_avif NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_blur NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_composite NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_extend NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_extract NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_flip NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_flop NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_from_input NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_grayscale NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_jpeg NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_metadata NR_GCPTR crates/perry-ext-sharp/src/lib.rs *mut Promise +js_sharp_png NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_resize NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_rotate NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_sharpen NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_to_buffer NR_GCPTR crates/perry-ext-sharp/src/lib.rs *mut Promise +js_sharp_to_file NR_GCPTR crates/perry-ext-sharp/src/lib.rs *mut Promise +js_sharp_trim NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sharp_webp NR_HANDLE_ID crates/perry-ext-sharp/src/lib.rs Handle +js_sqlite_open NR_HANDLE_ID crates/perry-ext-better-sqlite3/src/lib.rs Handle +js_sqlite_prepare NR_HANDLE_ID crates/perry-ext-better-sqlite3/src/lib.rs Handle +js_sqlite_stmt_all NR_GCPTR crates/perry-ext-better-sqlite3/src/lib.rs *mut ArrayHeader +js_sqlite_stmt_raw NR_HANDLE_ID crates/perry-ext-better-sqlite3/src/lib.rs Handle +js_sqlite_stmt_run NR_GCPTR crates/perry-ext-better-sqlite3/src/lib.rs *mut ObjectHeader +js_tls_create_server NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_close NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_listen NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_on NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_once NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_remove_all_listeners NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_server_remove_listener NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_tls_tlssocket_constructor NR_HANDLE_ID crates/perry-stdlib/src/tls.rs i64 +js_u8_from_base64 NR_GCPTR crates/perry-runtime/src/buffer/u8_codec.rs *mut BufferHeader +js_u8_from_hex NR_GCPTR crates/perry-runtime/src/buffer/u8_codec.rs *mut BufferHeader +js_undici_agent_new NR_HANDLE_ID crates/perry-ext-undici/src/lib.rs Handle +js_undici_get_global_dispatcher NR_HANDLE_ID crates/perry-ext-undici/src/lib.rs Handle +js_undici_proxy_agent_new NR_HANDLE_ID crates/perry-ext-undici/src/lib.rs Handle +js_ws_connect NR_GCPTR crates/perry-ext-ws/src/lib.rs *mut perry_ffi::Promise +js_ws_on_client_i64 NR_HANDLE_ID crates/perry-ext-ws/src/lib.rs i64 +js_ws_server_new NR_HANDLE_ID crates/perry-ext-ws/src/server.rs Handle +js_zlib_brotli_compress_sync NR_GCPTR crates/perry-ext-zlib/src/stream.rs *mut BufferHeader +js_zlib_brotli_decompress_sync NR_GCPTR crates/perry-ext-zlib/src/stream.rs *mut BufferHeader +js_zlib_create_brotli_compress NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_brotli_decompress NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_deflate NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_deflate_raw NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_gunzip NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_gzip NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_inflate NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_inflate_raw NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_unzip NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_zstd_compress NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_create_zstd_decompress NR_HANDLE_ID crates/perry-stdlib/src/zlib.rs i64 +js_zlib_deflate_raw_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_deflate_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_gunzip_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_gzip_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_inflate_raw_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_inflate_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_unzip_sync NR_GCPTR crates/perry-ext-zlib/src/lib.rs *mut BufferHeader +js_zlib_zstd_compress_sync NR_GCPTR crates/perry-ext-zlib/src/stream.rs *mut BufferHeader +js_zlib_zstd_decompress_sync NR_GCPTR crates/perry-ext-zlib/src/stream.rs *mut BufferHeader From ecbfba30af0dbde3539ce5db7e57a31186b91437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Mon, 7 Sep 2026 19:47:42 +0200 Subject: [PATCH 2/2] docs: report receiver representation ledger Record the producer map, corrected executable-row census, sabotage proofs, gate results, and the perrymaster measurement request for campaign PR 1. Claude-Session: https://claude.ai/code/session_011dhBmdn4vGgNibjo3oZqTo --- .../codex/REPORT_receiver_repr_ledger.md | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 cc-perf-campaign/codex/REPORT_receiver_repr_ledger.md diff --git a/cc-perf-campaign/codex/REPORT_receiver_repr_ledger.md b/cc-perf-campaign/codex/REPORT_receiver_repr_ledger.md new file mode 100644 index 0000000000..09f121772e --- /dev/null +++ b/cc-perf-campaign/codex/REPORT_receiver_repr_ledger.md @@ -0,0 +1,178 @@ +# Receiver-representation campaign PR 1: diagnostics and typed ledger + +Date: 2026-09-07 CEST + +Branch: `perf/receiver-repr-ledger` + +## Revisions + +- base `origin/main`: `8b7dc3342b22fe6270739c8d51585c3d2cdfa618` +- implementation: `9b6884e214beb93873f21dd76afe49e42f3f25df` +- report: this final branch commit (the pushed head named in the handoff) + +The merge-base is exactly the base SHA above. No #9937 commit or tree was used. + +## Result + +PR 1 adds measurement and metadata only. It does not change a JS-visible +representation, a release-path classifier, a wrapper, or native-result boxing. +All five new pointer-result classes enter the same `LoweredValue::native_handle` +branch used by the removed `NativeRetKind::Ptr`, so materialization is byte-for- +byte the existing pointer-tag path. `observed_wrapped` is therefore intentionally +zero in this PR. + +`PERRY_RECEIVER_REPR_DIAG=` reuses `hot_diag`'s sink parser and atomic +temporary-file rename. The first event publishes a snapshot; later events test +every 4,096 events and replace the file after at least one second. The line is: + +```text +[receiver-repr-diag] constructed common=… fetch=… zlib=… proxy=… timer=… text=… tui=… async_hook=… async_resource=… symbol_global=… external_buffer=… sab=… null_stub=…; observed_old common=… fetch=… zlib=… proxy=… timer=… text=… tui=… async_hook=… async_resource=… symbol_global=… external_buffer=… sab=… null_stub=…; observed_wrapped common=… fetch=… zlib=… proxy=… timer=… text=… tui=… async_hook=… async_resource=… symbol_global=… external_buffer=… sab=… null_stub=…; bare_managed=…; invalid_pointer_zero=…; direct_mismatch=… +``` + +Every producer and funnel has one `receiver_repr_on()` guard. After one-time +environment parsing, the test is a relaxed atomic load. When unarmed, no range, +registry, ownership, mutex, header, counter, or snapshot work runs. The only +release-path cost is that single guard. `direct_mismatch`'s direct header-byte +probe is compiled only with `debug_assertions`; even there it runs only when the +sink is armed. + +## Instrumented producers + +The current branch locations are: + +| Family | Producer(s) and diagnostic bump | +| --- | --- | +| common | `register_handle` at `crates/perry-stdlib/src/common/handle.rs:43` (bump `:47`); `register_handle_with_id` at `:55` (bump `:58`) | +| fetch | `alloc_fetch_handle_id` at `crates/perry-stdlib/src/fetch/mod.rs:223` (bump `:231`) | +| zlib | `next_zlib_id` at `crates/perry-stdlib/src/zlib.rs:722` (bump `:730`) | +| proxy | `js_proxy_new` at `crates/perry-runtime/src/proxy.rs:451` (bump `:483`) | +| timer | `next_timer_id` at `crates/perry-runtime/src/timer.rs:529` (bump `:534`) | +| text | `js_text_encoder_new` at `crates/perry-runtime/src/text.rs:106` (bump `:108`); decoder `register_decoder` at `:159` (bump `:179`) | +| tui | tree `register` at `crates/perry-runtime/src/tui/tree.rs:51` (bump `:55`); `js_perry_tui_state_alloc` at `tui/state.rs:100` (bump `:105`); `use_ref`, `use_app`, `use_stdout`, and `use_focus_manager` at `tui/hooks.rs:541,602,642,828` (bumps `:555,604,644,830`) | +| async_hook | `js_async_hooks_create_hook` at `crates/perry-runtime/src/async_hooks.rs:558` (bump `:572`) | +| async_resource | `new_async_resource_with_public_value` at `crates/perry-runtime/src/async_hooks.rs:1222` (bump `:1251`) | +| symbol_global | `well_known_symbol` at `crates/perry-runtime/src/symbol.rs:313` (bump `:336`); `intl_legacy_constructed_symbol` at `:642` (bump `:659`); `js_symbol_for` at `symbol/constructors.rs:44` (bump `:111`) | +| external_buffer | `js_buffer_register_external` at `crates/perry-runtime/src/buffer/header.rs:607` (bump `:617`) | +| sab | `alloc_shared_sab` at `crates/perry-runtime/src/shared_sab.rs:60` (bump `:88`) | +| null_stub | `js_unresolved_namespace_stub` at `crates/perry-runtime/src/object/null_stub.rs:37` (bump `:40`) | + +The five receiver/property observations are guarded at +`gc_pointer_and_type_from_value` (`object/native_call_method.rs:1025`), +`dispatch_primitive` (`object/native_call_method/primitive_methods.rs:15`), +`object_static_prototype` (`object/prototype_chain.rs:305`), the object field +tail (`object/field_get_set/get_field_by_name_tail.rs:11`), and `ic_miss` +(`object/field_get_set/ic_miss.rs:541`). + +Common/fetch/zlib use their audited reserved bands. Proxy, timer, decoder, TUI, +async hook/resource, symbol, external-buffer, SAB, and null-stub classification +uses authoritative registries or exact singleton identity. Because the old +encoding has no provenance and small integer registries overlap, one payload +may increment every semantic family whose registry/range claims it. That is an +intentional measurement of the old representation's ambiguity, not a new +release classifier. + +## Typed native-result ledger + +The executable declaration census on current `origin/main` is: + +| Kind | Rows | Meaning | +| --- | ---: | --- | +| `NR_GCPTR` | 131 | non-null managed Perry allocation with `GcHeader` | +| `NR_NULLABLE_GCPTR` | 2 | managed allocation, with zero retaining the provider's current null/failure behavior | +| `NR_HANDLE_ID` | 221 | integer registry id or sentinel | +| `NR_FOREIGN_PTR` | 4 | headerless native `Box` address (AsyncHook/AsyncResource backing) | +| `NR_JS_VALUE` | 13 | raw NaN-boxed JS bits in the integer ABI slot | +| **total** | **371** | every executable declaration formerly using the erased pointer kind | + +The campaign's quoted “372 rows” came from a textual `ret: NR_PTR` census. On +this base that text consists of 370 executable `NativeModSig.ret` fields and +two Fastify prose comments. Conversely, `http_client.rs` has one real result +kind in the positional `cr(...)` helper that the textual census missed. +Therefore the executable total is 371, not 372: 370 fields plus the helper. +Both comments were corrected and the missed helper is explicitly +`NR_HANDLE_ID`. No executable `NR_PTR` remains. + +`scripts/native_result_ledger.tsv` records 322 distinct runtime symbols, their +class, provider source, and provider Rust return type. The 81 symbols/rows that +the design's earlier signature census left unresolved were checked against +their provider implementations while constructing this inventory: **81/81 +resolved, zero unknown**. The checked provider set spans runtime, stdlib, and +the in-tree `perry-ext-*` implementations (rather than Android stubs or +force-link declarations). + +`scripts/native_result_ledger.py` checks both sides: every typed executable row +must agree with one provider ledger entry, every provider source must exist and +declare the symbol, no provider entry may be stale or classless, and a legacy +`NR_PTR` declaration is an immediate failure. A dedicated path-filtered CI +workflow runs `--self-test` and the real inventory. + +## Fail-capable tests and sabotage + +- `receiver_repr_family_fixtures_move_constructed_and_observed_old` constructs + real runtime proxy, timer, text, TUI, AsyncHook, AsyncResource, global-symbol, + external-buffer, SAB, and null-stub values, then sends each through the armed + receiver classifier. Common/fetch/zlib are dependency-lower producers, so + the fixture exercises their exact reserved bands and the companion source + witness binds them to their real producer bumps. Every family asserts + `constructed > 0`, `observed_old > 0`, and `observed_wrapped == 0`. +- `receiver_repr_every_family_producer_keeps_its_constructed_bump` pins the + exact number of bump sites in every audited producer file. Sabotage actually + performed: changed the first common producer's family token to `Fetch` and + ran the already-built release test. It failed exit 101 with `left: 1, + right: 2`; restoring the token returned the test to green. Dropping the bump + has the same failing count. +- `receiver_repr_unarmed_funnels_never_enter_classification` invokes all five + real funnels with the sink forced off and asserts the test-only classifier + entry count stays zero. Sabotage: delete any funnel guard; that funnel calls + `receiver_repr_note_*`, the entry counter becomes nonzero, and the equality + fails. +- `native_result_ledger.py --self-test` plants a legacy `NR_PTR` row and sees + the checker reject it, then plants a table/provider class disagreement and + sees that rejected too. Sabotage: re-add any erased row or remove/change its + provider class; the CI command exits 1. + +## Gates + +Each Cargo command used the campaign build lock and had `df -g /` checked +immediately before launch. Available space was 23 GB (runtime release test), +17 GB (codegen test), 17 GB (wasm-host build), and 14 GB (CLI build), all above +the required 12 GB launch floor. + +- `cargo test -p perry-runtime --release --lib -j6 -- --test-threads=1`: + PASS in 8m11s build + 7.02s tests; 3,262 passed, 4 ignored, 0 failed. +- `cargo test -p perry-codegen --lib -j6`: PASS; 1,450 passed, 1 ignored, + 0 failed (latest incremental build 16.49s, tests 2.83s). +- `python3 scripts/native_result_ledger.py --self-test`: PASS; planted erased + row and provider mismatch both rejected. +- `python3 scripts/native_result_ledger.py`: PASS; 371 rows, 322 providers, + counts exactly as above. +- `python3 scripts/gc_runtime_root_holders.py`: PASS; 1,363 declarations, + 1,160 identity-ratcheted, 593 scanner-reached, 350 inventory-classified, + 415 frontier-pinned, 152 registered scanners. +- `python3 scripts/check_thread_locals.py`: PASS; 405 hot declarations, 273 + cold declarations in 83 recorded files, capacity 768. No new TLS was added. +- `cargo build --release -p perry-runtime --features wasm-host -j6`: PASS in + 2m32s. +- `cargo build --release -p perry -j6`: PASS in 11m33s. Seven pre-existing + feature-dependent dead-code warnings were emitted from GC barrier/regexp + code; none names a changed diagnostic or ledger item. +- direct `rustfmt` over every touched Rust file: PASS. +- `git diff --check`: PASS. +- `scripts/check_file_size.sh`: PASS, “no Rust source files exceed 2000 + lines.” The touched field tail is 1,997 lines. + +## Perrymaster measurement request + +Relink the best cc bundle against implementation +`9b6884e214beb93873f21dd76afe49e42f3f25df`'s runtime. Run exactly one 3,300 +reply with `PERRY_RECEIVER_REPR_DIAG=stderr`, and report the final complete +`[receiver-repr-diag]` line together with the bundle SHA/build identity. Do not +average or omit zero buckets. + +That single line is the PR 2 pricing input: `constructed` gives wrapper +creations per reply by family, `observed_old` shows which families reach the +dynamic receiver/property paths, and the zero/nonzero relationship settles +the design's open question 1 for the best cc workload. It also provides the +required baselines for `observed_wrapped`, `bare_managed`, +`invalid_pointer_zero`, and debug-only `direct_mismatch` before any +representation change.