Repository navigation
islands: a value an island made passes the checked conversions - #3029
Merged
Merged
Conversation
A checked conversion accepts an island handle. A record reads each field through the handle, as Node reads a property; an array, tuple or index-signature record takes a native view of the value, with the view released at every exit. JSON.stringify, Object.keys and object spread and rest read the island object's own enumerable properties in Node, so a toJSON method, an accessor and a function-valued member keep their meaning. A program without islands emits the same code as before.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
cramforce
added a commit
that referenced
this pull request
Nov 7, 2026
#3029 (ctate/islands-value-island-a1a34a) already serializes an island value in JSON.stringify inside the existing protocol walk: the island object's kind from an `is_array` slot in ScrNiDynOps, its keys and members through scr_dyn_obj_keys and scr_dyn_obj_read, an array's length read in Node, its toJSON with the real key, and cycles by the handle's referent. This branch carried a second walk for the same thing (scr_json_island_write, its own `is_array` slot with another signature, a member-read branch, a toJSON branch and an entry in the compact walker). Both together would leave two live paths and one struct slot declared twice, so this merge deletes ours and builds on #3029's. This PR is now stacked on #3029 and merges after it. What stays is what #3029's walk does not do, each a small addition on top of it under SCR_NODE_ISLANDS. Measured with this branch's 37 JSON.stringify cases against #3029 merged with main: 27 match, and these four behaviours account for the other 10. - A replacer that is an island function or an island array is honoured (scr_json_stringify_value tested the native kinds only and ignored it, for island and native values alike), with the boxed String and Number keys of an island property list. - A boxed primitive or a raw JSON object an island made writes V8's text. Walked as an object it printed `{}`, `{"0":"s"}` or `{"rawJSON":"…"}`. The `scriptc:json` host helper answers it through the `json_query` slot, which is kept; the walk asks before it enters an island object that is not an array. - An island symbol is omitted like a native one: `[Symbol()]` inside an island object printed `[{}]` where Node prints `[null]`. - The circular-structure TypeError names an island object's constructor (`'Link'`, not `'Object'`): the walk marks the entry it pushes for an island object. Corpus 8886 gains a line for the symbol, with a Map, a Set, a hole, NaN and -0 beside it. The receiver two-arm call and its tests are untouched by the merge. Co-Authored-By: Claude Code <noreply@anthropic.com>
cramforce
added a commit
that referenced
this pull request
Nov 7, 2026
Merging #3029 with main changes how most kinds of value cross an island boundary, and the value matrix main gained after #3029 branched pins the old answers: 107 of its 239 programs fail on #3029 merged with main, and the same 107 on this branch. The table is regenerated here for this tree (SCRIPTC_ISLAND_MATRIX=update, then a pinned run: 239 of 239). Of its change against main, 4213 entries to 3509, all but two entries are #3029's and are the same on #3029 merged with main alone, whose own regenerated table has 3511 entries: 856 gone, 154 new, 172 with another status. This PR's part is two entries gone and none new: reading a native Map-holding record back by key through an island (map-obj.p, n2i2n/N.read.getByKey with and without the island callee) threw and now matches Node. Co-Authored-By: Claude Code <noreply@anthropic.com>
cramforce
added a commit
that referenced
this pull request
Nov 7, 2026
#3029 gained a commit (3787c75) after this branch merged it: its walk now omits an island symbol like a native one, a toJSON that is an island function on a native object is called, a handle is tracked by the value behind its box in the conversion visit, and Array.isArray follows a proxy in the bridge. The symbol was one of the four things this branch added on top of that walk, so the addition here (scr_json_island_symbol and its test in scr_json_omitted) is deleted and both conflicts resolve to #3029's side. Three remain on top: island replacers, the text of a boxed primitive or a raw JSON object, and the constructor name in the circular-structure TypeError. Co-Authored-By: Claude Code <noreply@anthropic.com>
cramforce
added a commit
that referenced
this pull request
Nov 7, 2026
#3029's new commit changes a few more cells (a proxied array, symbols). Regenerated for this tree and rerun pinned: 239 of 239. The table has 3515 entries; #3029 merged with main alone regenerates to 3517, and the difference is the same two entries as before, both gone here (map-obj.p, n2i2n/N.read.getByKey with and without the island callee). Co-Authored-By: Claude Code <noreply@anthropic.com>
This was referenced Nov 7, 2026
cramforce
added a commit
that referenced
this pull request
Nov 8, 2026
No conflict. Main brings trains perf-2 and cli-2, #3029 and #3380; lowerer.ts keeps main's checkVariadicFunctions call at the start of finishModule beside the train's code. Regenerating the refusal baseline and the compatibility files on the merged tree changes nothing. Co-Authored-By: Claude Code <noreply@anthropic.com>
This was referenced Nov 8, 2026
yowainwright
pushed a commit
to yowainwright/scriptc
that referenced
this pull request
Nov 8, 2026
import { Type } from "schema-pkg"; // an island package
const item = Type.Object({ id: Type.String() });
export const list = Type.Array(item);
Lowered call by call, each initializer crosses into the island once per
call with its literal arguments, and the first of them starts Node while
the program's modules still initialize, whatever the build deferred. An
initializer built only from literals, island imports, other such
constants, and member reads, calls and `new` on those holds no native
value, so the island can evaluate it itself.
The build writes the initializers of each run of consecutive such
constants into an island module of the shipped tree
(.scriptc/closed/<module>.<digest>.<n>.mjs), loads it where the run's
first constant is declared through nodeIsland.defer, and each constant's
initializer becomes a read of the module's export, met with the conversion
the original expression's value met. The rest is the deferral of a static
island import: the probe decides, the interface snapshot stands in until
Node starts, reconciliation keeps identity. The native constant keeps its
global, type, exports and initialization flag. One module per run: a
native statement between two closed constants still runs between them.
A constant is closed when its value is the island's own on both sides (a
handle or an immutable primitive) and every operand is initialized before
it in every execution; anything else keeps the call-by-call lowering.
A generated module computes from state other island code left behind, so:
- it defers only where the program reaches it at one fixed point of its
start (before any await, outside conditions, in an initializer only the
static import graph calls), where the modules probed before it are the
ones evaluated before it; elsewhere it evaluates at its position;
- a program with generated modules does not use per-module mode, where a
snapshot would answer for a module while Node runs;
- the probe withholds the effects and inputs of these modules instead of
performing them: the build does not run the program's effects.
A literal in a closed initializer is now made by the island. On main an
island-made object fails the checked conversion when the program receives
it through an untyped value and asserts it to a native record type; that
case becomes a TypeError until island-made values pass checked
conversions (vercel-labs#3029). Reads typed by the island's declarations are views.
No runtime change.
Co-Authored-By: Claude Code <noreply@anthropic.com>
This branch was successfully deployed
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.
JSON.stringify,Object.keysand object spread and rest read an island object's own properties in Node, sotoJSON, accessors and function-valued members keep their meaning.