feat(immutable-arraybuffer): transferToImmutable ponyfill and shim#2399
Merged
Conversation
d40f56f to
d610950
Compare
d610950 to
e4be967
Compare
b71e84c to
c1d8ab4
Compare
3 tasks
c1d8ab4 to
f531bc8
Compare
Contributor
Author
|
OCapN meeting coming up on Tuesday. So if there's no problem with this, I'd like to make progress before then. Ping ;) |
kriskowal
approved these changes
Aug 12, 2024
gibson042
approved these changes
Aug 13, 2024
gibson042
left a comment
Member
There was a problem hiding this comment.
The code looks reasonable, but I feel pretty strongly that we should not have a polyfill at all... liveslots will need to use a new endo to take advantage of this anyway, and it IMO should explicitly propagate transferBufferToImmutable and isBufferImmutable as globals into all descendant compartments rather than manipulating a built-in prototype and creating compatibility concerns.
f531bc8 to
262bcf0
Compare
7 tasks
3 tasks
erights
added a commit
that referenced
this pull request
Jun 18, 2025
Closes: #XXXX Refs: #2785 #2399 ## Description The Immutable ArrayBuffers shim can only emulate `transferToImmutable` on platforms with either `structuredClone` or `ArrayBuffer.prototype.transfer`. Otherwise, the shim would refuse to initialize. Without Immutable ArrayBuffers, we cannot initialize `ses`, and `pass-style` cannot implement the new `byteArray` Passable type, which `marshal` and `patterns` now depends on. Unfortunately, it turns out that some platforms we want to support do not have `structuredClone` or `ArrayBuffer.prototype.transfer`. The first we encountered was Hermes, that also does not have classes with private fields. #2785 makes all these work on Hermes, by supporting `sliceToImmutable` instead, and using WeakMaps rather than private fields. On the theory that Hermes was a one-off, #2785 sniffed to see if it was on Hermes, only only then used the alternate shim. In turns out Hermes was not a one-off. Some version of JSC of concern (TODO which ones?) also have neither `structuredClone` or `ArrayBuffer.prototype.transfer`. So this PR unifies the two shim strategies into one which uses the WeakMap technique, which works everywhere, and emulating `sliceToImmutable`, which we can do everywhere. It still sniffs for `structuredClone` or `ArrayBuffer.prototype.transfer`, and only emulates `transferToImmutable` if one is present. Thus, we sniff only for features not platforms, and emulate `sliceToImmutable` on all platforms. Other PRs (TODO: which ones?) already ensure that `pass-style`, `marshal`, and `patterns` are fine with the absence of `transferToImmutable`. ### Security Considerations A singe piece of code with small feature detects is simpler, and thus more secure, than maintaining two alternate pieces of code, each for a different set of platforms. ### Scaling Considerations On most platforms, a class with private fields is probably more efficient than a WeakMap. This PR sacrifices that optimization in exchange for unification. ### Documentation Considerations Less to document. ### Testing Considerations The "unified" tests are just the union of the old tests, and so have two problems - [ ] redundancy, which needs to be removed - [ ] contains unconditional `transferToImmutable` tests that won't work on some platforms. These specific tests need to be made conditional, probably using the same `test.skip` trick some tests use for `Array.prototype.transfer`. ### Compatibility Considerations The goal is to make the shim compat with more platforms. On platforms that worked before this PR, this PR should be a pure refactor, and so without any compat hazards. ### Upgrade Considerations - [x] Update `NEWS.md` for user-facing changes. --------- Co-authored-by: Christopher Hiller <boneskull@boneskull.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #XXXX
Refs: #1538 #1331 #2309 #2311
Description
Introduces the
@endo/immutable-arraybufferpackage, the ponyfill exports of@endo/immutable-arraybuffer, and the shim obtained by importing@endo/immutable-arraybuffer/shim.js.Alternative to #2309 as suggested by @phoddie at #2309 (comment)
We plan to fix #1331 in a stack of PRs starting with this one
Passabletype,ByteArray, corresponding to the OCapNByteArray.ByteArrayobjects.See the README.md in this PR for more.
Security Considerations
Better support for immutability generally helps security. The imperfections of the shim are a leaky abstraction in all the ways explained in the Caveats section of the README.md. For example, objects that are purely artifacts of the emulation, like the
immutableArrayBufferPrototype, are easily discoverable, revealing the emulation's mechanisms.As a pure JavaScript polyfill/shim, this
@endo/immutable-arraybufferpackage does not harden the objects it exposes. Thus, by itself it does not provide much security -- like the initial state of JavaScript does not by itself provide much security. Rather, both provide securability, depending on Hardened JavaScript to harden early as needed to provide the security. See #2311Once hardened early, the abstraction will still be leaky as above, but the immutability of the buffer contents are robustly enforced.
Scaling Considerations
This ponyfill/shim is a zero-copy implementation, meaning that it does no more buffer copying than expected of a native implementation.
Compatibility and Documentation Considerations
This ponyfill/shim implements zero-copy by relying on the platform to provide one of two primitives:
structuredCloneorArrayBuffer.prototype.transfer. Neither exist on Node <= 16. Without either, this ponyfill/shim will fail to initialize.This PR sets the stage for writing an Immutable ArrayBuffer proposal, proposing it to tc39, and including it in our own documentation.
Testing Considerations
Ideally, we should identify the subset of test262
ArrayBuffertests that should be applicable to immutable ArrayBuffers, and duplicate them for that purpose.Upgrade Considerations
Nothing breaking.