You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b92c2de
Browse filesBrowse the repository at this point in the historyBrowse files
## Summary
- add `js.OwnedTypedArray(Element, array_type)` and concrete
`Owned*Array` aliases
- transfer allocator-owned element storage to an external ArrayBuffer
without copying
- support owned typed arrays as return values from DSL functions and
class methods
- make ownership transfer transactional: pre-transfer failures preserve
the Zig owner; successful or potentially transferred values leave the
source empty
- align `OwnedBuffer.intoValue` with the same pointer-based
transactional ownership model while retaining its existing
unsupported-runtime copy fallback
- validate each `Element` against its N-API TypedArray kind at compile
time
- keep `TypedArray.fromExternal` unchanged from `main`
- propagate `NoExternalBuffersAllowed` unchanged for owned typed arrays;
no copy fallback
## API
```zig
pub fn serialize() !js.OwnedUint8Array {
const allocator = js.allocator();
const data = try allocator.alloc(u8, 32);
// Fill data...
return js.OwnedUint8Array.fromOwnedSlice(allocator, data);
}
```
`fromOwnedSlice` takes an existing allocator-owned mutable slice without
copying. `fromSlice` creates an owned copy when that is what the caller
needs.
`intoValue` takes `*OwnedTypedArray`. Once ownership transfers, it
empties the source, so a normal deferred `deinit` is safe. The allocator
must remain valid until the ArrayBuffer finalizer runs.
`OwnedBuffer.intoValue` now follows the same pointer-based transfer
contract. It retains its existing `NoExternalBuffersAllowed` copy
fallback and consumes the source only after that copy succeeds.
## Lodestar-Z use case
In the Lodestar-Z BLS bindings, `compress` and `serialize` currently
produce fixed-size stack arrays and pass them to
`TypedArray.fromExternal`, which copies them into allocator-owned native
storage before creating the external ArrayBuffer. With this API, the
bindings can allocate the output slice on the native heap, let `blst`
write into it directly, and return it with
`OwnedUint8Array.fromOwnedSlice`. This removes one stack-to-native-heap
copy per result while preserving the external ArrayBuffer GC lifecycle.
## Ownership boundary
- zero length: create a normal zero-length V8 ArrayBuffer and empty the
source only after TypedArray creation succeeds
- owner heap allocation failure: leave the allocation owned by the
caller
- `NoExternalBuffersAllowed`, `PendingException`, or `CannotRunJS`: Node
returns before finalizer registration, so restore ownership to the
caller and propagate the original error
- other external ArrayBuffer errors: leave the source empty because Node
may already have installed or invoked the finalizer
- typed-array view creation failure or success: leave the source empty;
the external ArrayBuffer finalizer owns the allocation
- DSL return conversion: defer `deinit` on the local owner, which frees
restored/untransferred data and is a no-op after transfer
The heap finalizer context is the owning value itself, matching the
boxed-owner model rather than duplicating ownership fields in a second
context type.
Node implementation reference for the ambiguous failure boundary:
-
https://github.com/nodejs/node/blob/main/src/js_native_api_v8.cc#L3126-L3141
- https://github.com/nodejs/node/blob/main/src/node_api.cc#L1077-L1113
0 commit comments