Skip to content

fix(node:buffer): honor concat total length#2271

Merged
proggeramlug merged 2 commits into
PerryTS:mainfrom
andrewtdiz:codex/node-compat-buffer-concat-total-length
May 29, 2026
Merged

fix(node:buffer): honor concat total length#2271
proggeramlug merged 2 commits into
PerryTS:mainfrom
andrewtdiz:codex/node-compat-buffer-concat-total-length

Conversation

@andrewtdiz
Copy link
Copy Markdown
Contributor

Summary:

  • Honor explicit Buffer.concat(list, totalLength) truncation and zero-padding.
  • Validate concat list entries as Buffer/Uint8Array-backed values and throw TypeError with ERR_INVALID_ARG_TYPE for invalid entries.
  • Preserve the one-arg concat fast path and route two-arg concat through a totalLength-aware runtime helper.

Part of #793.

Evidence:

  • Baseline exact ./run_parity_tests.sh --suite node-suite --filter node-suite/buffer/concat/edge-lengths: FAIL, report test-parity/reports/parity_report_20260528_103403.json.
  • Final exact ./run_parity_tests.sh --suite node-suite --filter node-suite/buffer/concat/edge-lengths: PASS, report test-parity/reports/parity_report_20260528_104126.json.
  • Full concat subgroup ./run_parity_tests.sh --suite node-suite --module buffer/concat: PASS 4/4, report test-parity/reports/parity_report_20260528_104218.json.
  • Full granular ./run_parity_tests.sh --suite node-suite --module buffer: 104 PASS / 11 parity FAIL / 1 compile FAIL, report test-parity/reports/parity_report_20260528_104226.json; all concat cases are green. Residuals remain in allocation, byteLength edge encodings, compare bounds, fill/write coercions, Buffer.from coercions/errors, inspect limits, iterator, range-error edge cases, and ucs2 search compile behavior.
  • cargo check -p perry-hir -p perry-codegen -p perry-runtime -p perry-stdlib: PASS with existing warnings.
  • cargo fmt --check: PASS.
  • jq empty test-parity/known_failures.json: PASS.
  • git diff --check: PASS.

DeepWiki:

  • Local-only reference: reference/deepwiki/nodejs-node-buffer-concat-total-length-2026-05-28.md.

Non-goals:

  • No Buffer.concat list-argument array validation.
  • No exact ToUint32 edge semantics for exotic totalLength values.
  • No Buffer.from/write/fill coercion cleanup.
  • No broad node:buffer inventory cleanup claim.

# Conflicts:
#	crates/perry-runtime/src/buffer/mod.rs
@proggeramlug proggeramlug merged commit 3b9284a into PerryTS:main May 29, 2026
10 of 11 checks passed
proggeramlug pushed a commit that referenced this pull request May 29, 2026
origin/main's buffer/mod.rs import block drifted out of rustfmt-1.9.0
formatting (last touched by #2271), so `cargo fmt --all --check` — the
lint gate — fails for every PR branched on current main, including this
one. Apply the import reordering. No functional change.
proggeramlug pushed a commit that referenced this pull request May 29, 2026
…age on main)

The import block at buffer/mod.rs:40 landed unformatted via #2271, which
fails the required `cargo fmt --all -- --check` lint on every PR. Apply
the formatting rustfmt emits so this branch's lint check goes green.
proggeramlug added a commit that referenced this pull request May 29, 2026
…string coercion (#2374) (#2390)

* fix(symbols): invoke [Symbol.toPrimitive] on class instances for + / string coercion (#2374)

`[Symbol.toPrimitive]` defined as a computed method on a class
(`class T { [Symbol.toPrimitive](hint) {...} }`) was dropped entirely
during HIR lowering — the well-known-symbol method handler in
`lower_decl/class_decl.rs` fell through to a `continue` for any
well-known symbol other than iterator/asyncIterator/hasInstance/
toStringTag/dispose. As a result the method was never registered in the
class vtable, so unary `+` (numeric coercion) returned `NaN` and
template-literal / `String()` (string coercion) returned
`[object Object]` for class instances.

The runtime side already handles `@@toPrimitive`: `js_to_primitive`
(consulted by `js_number_coerce` and `js_jsvalue_to_string`) resolves
`instance[Symbol.toPrimitive]` via `js_object_get_symbol_property`,
which maps the well-known symbol to the synthetic `@@toPrimitive`
vtable key (`well_known_symbol_method_key`) and binds it to the
instance. The only gap was lowering dropping the method.

Register `[Symbol.toPrimitive]` instance methods under `@@toPrimitive`,
mirroring the existing `@@iterator` / `@@asyncIterator` path. Object
literals already worked (own symbol property); this closes the
class-instance case.

Added a class-instance case to test_gap_symbols.ts; output is
byte-identical to `node --experimental-strip-types`.

* style: rustfmt buffer/mod.rs re-export block (pre-existing lint breakage on main)

The import block at buffer/mod.rs:40 landed unformatted via #2271, which
fails the required `cargo fmt --all -- --check` lint on every PR. Apply
the formatting rustfmt emits so this branch's lint check goes green.

* docs: regenerate API reference + .d.ts (util/types predicate drift)

The util/types isFloat32Array/isInt8Array/… predicates were added to the
API manifest without regenerating docs, leaving docs/ at 1491 entries vs
the manifest's 1496 — failing the required api-docs-drift check. Run
./scripts/regen_api_docs.sh to resync. Unrelated to the toPrimitive fix
but required to land this branch (pre-existing drift on main).

---------

Co-authored-by: Ralph Küpper <ralph@skelpo.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants