Skip to content

feat(runtime+jsruntime): Object.prototype methods on Buffer + require() namespace#983

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-agent-a527c40190146a500
May 18, 2026
Merged

feat(runtime+jsruntime): Object.prototype methods on Buffer + require() namespace#983
proggeramlug merged 1 commit into
mainfrom
worktree-agent-a527c40190146a500

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Summary

  • Add hasOwnProperty / propertyIsEnumerable / valueOf / toLocaleString / isPrototypeOf arms to dispatch_buffer_method so safer-buffer's for (key in buf) { if (!buf.hasOwnProperty(key)) ... } probe resolves on Buffer instances.
  • Plain-object-copy ESM module namespaces returned via __perry_require_namespace so require('buffer').hasOwnProperty(...) works (the actual safer-buffer crash site — the receiver is the module, not a Buffer instance).
  • Extend is_buffer_method_name so method-as-value reads (typeof buf.hasOwnProperty === 'function') return a bound-method closure that dispatches back through the new arms.

Index-key probes for hasOwnProperty(idx) / propertyIsEnumerable(idx) check the numeric / int32 / numeric-string key against (*buf_ptr).length, matching Node (indexed bytes are own enumerable; length is on the prototype).

Direct follow-up to PR #973 (Date/Array/Object .constructor) and PR #978 (ramda prototype methods).

Test plan

  • test-files/test_buffer_prototype_methods.ts byte-for-byte matches node --experimental-strip-types:
    false
    false
    function
    hello
    function
    false
    
  • /tmp/perry-express smoke (import express from 'express') — pre-fix crashed at safer-buffer/safer.js:36:15 with buffer.hasOwnProperty is not a function; post-fix safer-buffer load succeeds (downstream send hits an unrelated util.inherits stub gap, tracked separately).
  • cargo build --release -p perry-runtime -p perry-stdlib -p perry -p perry-jsruntime clean.

…stances

safer-buffer (and any transitive consumer via express) opens with
`for (key in buffer) { if (!buffer.hasOwnProperty(key)) continue; ... }`.
Two distinct gaps both surfaced as `buffer.hasOwnProperty is not a function`:

1. `dispatch_buffer_method` (perry-runtime) had no Object.prototype fallbacks
   on Buffer instances. Add `hasOwnProperty`, `propertyIsEnumerable`,
   `valueOf`, `toLocaleString`, `isPrototypeOf` arms before the
   `_ => undefined` fallback. Index-key probes check `(*buf_ptr).length`
   (Node spec: indexed bytes are own enumerable, `length` is inherited).
   `is_buffer_method_name` is extended so a method-as-value read returns
   a bound-method closure that routes back through the new arms.

2. `__perry_require_namespace` (perry-jsruntime) returned an ESM
   module-namespace object with a null prototype, so `nsObj.hasOwnProperty`
   threw. When the namespace has no prototype, copy enumerable own
   properties into a plain `{}` so Object.prototype.* is reachable. Class
   / function values are copied by reference, so static members and
   `.prototype` survive.

test-files/test_buffer_prototype_methods.ts matches Node byte-for-byte.
Express smoke test no longer hits the safer-buffer crash (downstream
send/util.inherits stub gap is tracked separately).
@proggeramlug proggeramlug force-pushed the worktree-agent-a527c40190146a500 branch from 6608ba1 to 8b664b8 Compare May 18, 2026 03:02
@proggeramlug proggeramlug merged commit 8ace283 into main May 18, 2026
@proggeramlug proggeramlug deleted the worktree-agent-a527c40190146a500 branch May 18, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant