Skip to content

ABI: implement external ZigString ownership and finalization #324

Description

@chrisbbreuer

Parent: #140
Tracked by: #134, #163, #164
Follow-up to: #199

Pinned scope

Implement the three remaining external-string exports shared by the pinned Home 7ed99c02 and Bun 4982b91e private profiles:

  • ZigString__external — retain the caller buffer and invoke (ctx, ptr, len) exactly once when the JS string releases it.
  • ZigString__toExternalValueWithCallback — the same exact-once lifetime with the pinned null callback context.
  • ZigString__toExternalU16 — transfer a globally allocated UTF-16 buffer and preserve exact UTF-16 code units, including lone surrogates.

The pinned references are src/jsc/bindings/bindings.cpp plus src/jsc/ZigString.zig/ZigString.rs. Copied, atomic, and rope construction are already complete under #199.

Design requirements

  • External storage stays immutable and usable until the last engine reference dies; do not implement a copy followed by an eager callback and call it external ownership.
  • Finalization is exact-once across ordinary GC, duplicate references, context teardown, construction failure, and zero-length strings.
  • Callback execution must be thread-safe, must not occur while GC/object locks are held, and must preserve the supplied pointer, length, and context exactly.
  • Latin-1/tagged UTF-16 decoding and UTF-16/WTF-8 conversion preserve JavaScript code-unit semantics, including astral pairs and lone surrogates.
  • Invalid pointer/length pairs, over-limit lengths, cross-VM misuse, and allocation failure publish the correct pending exception while returning the empty encoded sentinel and releasing transferred ownership exactly once where required.
  • Arena and moving-GC modes have one documented ownership model; if zig-gc needs a general external-cell finalizer hook, implement and test it in ~/Code/Libraries/zig-gc as its own linked small commit.

Acceptance

  • Focused Zig tests cover 8-bit and 16-bit buffers, empty strings, embedded NUL, astral/lone-surrogate values, source lifetime, mutation visibility contract, duplicate references, collection, teardown, callback reentry, callback thread behavior, errors, and injected OOM.
  • The separately compiled Home consumer declares, links, and executes all three signatures.
  • Home and Bun inventories and ABI documentation are regenerated with exact counts.
  • Relevant focused tests and both ABI audits pass; one full CI run is accepted before closure.
  • Parent issues receive completion evidence and updated remaining counts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions