Skip to content

feat(immutable-arraybuffer,pass-style): passable byte arrays (freezable TypedArray emulation + byteArray brand check) - #3311

Open
kriskowal wants to merge 4 commits into
masterfrom
feat/passable-byte-arrays
Open

feat(immutable-arraybuffer,pass-style): passable byte arrays (freezable TypedArray emulation + byteArray brand check)#3311
kriskowal wants to merge 4 commits into
masterfrom
feat/passable-byte-arrays

Conversation

@kriskowal

@kriskowal kriskowal commented Jun 22, 2026

Copy link
Copy Markdown
Member

Introduces passable byte arrays. Ferried from bot fork endojs/endo-but-for-bots#503, rebased onto current master.

The feature now spans four commits:

1. Freezable TypedArray emulation (@endo/immutable-arraybuffer)

After loading @endo/immutable-arraybuffer/shim.js, constructing a TypedArray from an emulated immutable ArrayBuffer yields an emulated freezable wrapper instead of the previous 0-byte fallback:

  • Mutator methods (copyWithin, fill, reverse, set, sort) throw TypeError; the buffer getter returns the immutable wrapper; Object.freeze works on the view.
  • The wrapper inherits directly from T.prototype with no intermediate prototype; emulation covers all eleven concrete TypedArray constructors via a single install on %TypedArrayPrototype%.
  • Construction from a genuine mutable ArrayBuffer is unchanged.
  • Symbol.iterator installed (for...of/spread); subarray() returns a wrapped sub-view; BYTES_PER_ELEMENT forwarded so post-lockdown reads are correct.

2. byteArray brand check for plain frozen Uint8Array (@endo/pass-style)

A plain frozen Uint8Array backed by a plain frozen immutable ArrayBuffer is now recognized as a passable byteArray, alongside the raw immutable ArrayBuffer shape. The plain-wrapper definition distinguishes the emulated path (zero own indexed properties) from a future native TC39 integer-indexed-exotic path (exactly length-many own enumerable data properties each agreeing with the backing byte), rejecting any other shape. passStyleOf also reports a clear Cannot pass mutable typed arrays diagnostic rather than the generic non-remotable error under LOCKDOWN_HARDEN_TAMING=unsafe.

3. @endo/bytes ponyfills tolerate the emulated wrapper (new)

A Uint8Array over an emulated immutable ArrayBuffer is a plain object that ArrayBuffer.isView rejects — integer indexing reads undefined, and TextDecoder.decode / TypedArray.prototype.set throw or silently read zeros. bytesToText, bytesEqual, and concatBytes now copy such an emulated wrapper to a genuine Uint8Array (via the wrapper's native slice, which memcopies from the hidden genuine TypedArray it amplifies to) before any platform call or indexing. Genuine views pass through uncopied, so the common path is unaffected.

4. ses permits (test)

The ses permits walk accepts the shim-installed %TypedArrayPrototype% slots with no new permit rows; covered by a regression test.

Changesets

@endo/immutable-arraybuffer minor, @endo/pass-style minor, ses patch (in freezable-typedarray-emulation.md); @endo/bytes patch (in bytes-tolerate-emulated-frozen-uint8array.md).

Testing

On top of current master: @endo/immutable-arraybuffer 217, @endo/pass-style 41, @endo/bytes 38, ses 513 — all passing; lint clean.

@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: acf062a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@endo/bytes Patch
@endo/immutable-arraybuffer Minor
@endo/pass-style Minor
ses Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

endolinbot added 4 commits June 25, 2026 15:34
Constructing a TypedArray over an emulated immutable ArrayBuffer now
yields a freezable wrapper whose mutators throw, whose buffer getter
returns the immutable wrapper, and which Object.freeze accepts. The
genuine-buffer path is unchanged. The changeset bumps
immutable-arraybuffer and pass-style minor and ses patch.
…byteArray

A plain frozen Uint8Array backed by an immutable ArrayBuffer is now a
passable byteArray, alongside an immutable ArrayBuffer itself.
passStyleOf reports a clear "Cannot pass mutable typed arrays"
diagnostic for a mutable TypedArray instead of the generic
non-remotable error.
bytesToText, bytesEqual, and concatBytes now copy an emulated immutable
ArrayBuffer-backed Uint8Array to a genuine Uint8Array before any
platform call or indexing. The copy uses the wrapper's native slice
memcopy rather than result.set(wrapper), which would read zeros because
the wrapper exposes no integer-indexed own properties. Genuine views
pass through uncopied.
The permits walk accepts the shim-installed %TypedArrayPrototype% slots
without complaint; no new permit rows are required. Adds the regression
test covering this.
@kriskowal
kriskowal force-pushed the feat/passable-byte-arrays branch from c166199 to acf062a Compare June 25, 2026 22:35
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