Repository navigation
Conversation
Adds the report-only Node island policy, configuration and detector of the scope-B plan (milestone NI-2). Coverage now lists the npm packages a build would run in a Node island and why, gap islands first, without changing code generation. - project-config.ts reads the `scriptc` key of the entry's package.json with a schema; an unknown value in `scriptc.packages` or `scriptc.nodeIslands` is SC8004 instead of being ignored. Package shims and the WebAssembly scanner read through it. - node-islands/: origin (user, npm, shim, builtin; package instances), rules R1.1-R2.5 and the four classes, a syntactic pre-scan for R1/R2 markers, classification of refusals and runtime fences (reason ids at the refusal sites that need them), the policy (auto, explicit, off; forced node and native packages; marked user modules) and the report with island closure. - coverage: a "Node islands" section, `--explain-island=<pkg>`, a `nodeIslands` field in the diagnostics envelope, and `--fail-on` `node-islands`, `eager-node-islands` and `island-gaps`. - CLI: `--node-islands`, `--node-island`, `--native`, `--node` (validated, report-only) and `--strict-user-js` (SC8101-SC8105 for R2 constructs in user JavaScript). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Comment on lines
+121
to
+123
| s.importers.add(""); | ||
| s.nativeSites.push(e.loc); | ||
| } else if (e.fromDir !== s.key) { |
Contributor
Comment on lines
+121
to
+126
| s.importers.add(""); | ||
| s.nativeSites.push(e.loc); | ||
| } else if (e.fromDir !== s.key) { | ||
| s.importers.add(e.fromDir); | ||
| } | ||
| } |
Contributor
Comment on lines
+295
to
+298
| if (marked !== null) { | ||
| userModules.push({ file: m.file, source: marked }); | ||
| continue; | ||
| } |
Contributor
Comment on lines
+260
to
+269
| const reachingIslands: string[] = []; | ||
| for (const from of s.importers) { | ||
| const importer = states.get(from); | ||
| if (importer === undefined) continue; | ||
| const owner = importer.island ? importer.key : importer.carriedBy; | ||
| if (owner !== null) { | ||
| const name = states.get(owner)!.name; | ||
| if (!reachingIslands.includes(name)) reachingIslands.push(name); | ||
| } | ||
| } |
Contributor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <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.
Summary
This is milestone NI-2 of the scope-B plan: the Node island policy, the project configuration and the detector, all in report-only mode.
scriptc coveragenow lists the npm packages that a build would run in a Node island and explains why. Code generation does not change, and no build output changes. Builds and coverage gain one new failure, by design: an unknown value in the project'sscriptcconfiguration is now an error (SC8004).project-config.ts). One reader for thescriptckey of the entry's nearestpackage.json, with a schema. An unknown key or value inscriptc.packagesorscriptc.nodeIslandsis SC8004, located at the key. Until nowconfigurePackageShimsignored anything except"unloaded", so a typo such as"unloded"silently did nothing. Package shims and the WebAssembly scanner now read through this module, andscriptc.wasmkeeps its lenient reading."unloaded" | "node" | "native" | "auto"or{ run, evaluate, share, marshal, schedule }.nodeIslandsacceptsauto,modules,node,nodeVersion,packagingandspeculativeStart.node-islands/):origin.ts: whether a file is user, npm, shim or builtin code, and which package instance (identified by its directory) an npm file belongs to.rules.ts: the rule families R1.1–R2.5 and the classes runtime, object-model, gap and packaging. A fifth value,marked, covers islands that have no reason of their own.detect.ts: a syntactic pre-scan for R1 and R2 markers.scan.ts: module and package-edge collection on the final program, and on the program that still held each package the drop-and-reload loop removed.classify.ts: maps a refusal, a runtime fence or a package refusal to a class. Some refusal sites carry a reason id, and the rest are matched by their messages. The sites with a reason id are computedimport(), computedrequire(),createRequire, native addons,require.cache,WeakRef/evaland sloppyarguments.policy.ts:auto | explicit | off, packages forced tonodeornative, and user modules marked by glob or path.report.ts: decisions and the island closure. A package imported only by islands runs inside the island. A package reached from both native code and an island is reported as shared.--explain-island=<pkg>shows the first reason per module, the native import sites (the boundary) and the packages inside the island's closure.nodeIslandsfield.--fail-ongainsnode-islands,eager-node-islands(the same asnode-islandsuntil deferred evaluation lands) andisland-gaps.--node-islands=auto|explicit|off,--node-island=<pkg-or-path>,--native=<pkg>and--node=<path>: accepted bybuild,runandcoverage, validated, and report-only.--strict-user-js(coverage): reports R2 constructs in the user's own.js/.cjs/.mjsfiles as SC8101–SC8105 blockers. These are the SC81xx codes, kept behind a flag.Zero cost
scripts/zero-cost-gate.mjsagainstorigin/main0237d70, Linux sandbox:--set=bench,self: 34 identical, PASS.--set=corpus --corpus=all, in two shards:corpus/fs-extra-package. It differs only in IR source locations: the path of the compiler's ownfs-extrashim, which lives in the compiler checkout, so baseline and candidate necessarily disagree. LLVM and the executable are byte-identical, and the IR is byte-identical once that path is normalized. This is an artifact of the gate, not of this change.tests/fixtures/npm/cases,npm-static,commander-calc), LLVM from both compilers: 112 byte-identical. The other 28 fail to build under both compilers with identical diagnostics. None differ.coveragetakes is unchanged. On the same VM, the corpus coverage sweep (shard 1/4) took 212.8 s against 215.8 s on main.analyze()on commander-calc, jose and effect is within noise of main.native/cli.ts --emit=ir) produces no diagnostics.Classification
npm fixture corpus (
tests/fixtures/npm/cases,npm-static,commander-calc): 140 programs, of which 79 have at least one would-be island. Across 122 distinct packages:.d.ts, 1 typed by a third-party@typespackage, 3 bundler-interop refusalscreateRequireescapes in bundles), R1.1 1, R1.4 1, R1.5 1Many fixture packages exist to exercise edge cases, so gaps are over-represented. Some notable packages:
varabove its declaration.Real-world fixtures:
effectandeffect4: object-model, from R2.2Object.setPrototypeOf.Object.definePropertyon function objects, plus 30 gap fences in untaken WebCrypto and deflate paths;Design corrections found
defineProperty-built function objects, so it would become an island. One of these has to change:definePropertyon a fresh function literal whose.d.tsdeclares the member as native.node_modulesthat would become islands. Either the policy test is limited to programs without npm code, or those programs become island tests.nodeIslandsJSON shape. It is an object,{ mode: "would-be", policy, islands, userModules, npmPackages, violations, unknownPackages }, rather than a bare array, so the report-only state is machine-readable.npmPackageslives inside it.--fail-ongates. They are not build errors.Tests
node-islands/detect.test.ts: every marker of R1.1–R2.5, plus the exceptions (the global-object idiom, the probe intry, the transpiled-Erroridiom, null-prototype literals, interop helpers, strict code);node-islands/report.test.ts: decisions, closure, forced native and node,offandexplicit, marked user modules, SC81xx, glob matching;project-config.test.ts: the schema and SC8004 messages and locations.tests/coverage-fixtures/node-islands: one package per class, a package inside an island's closure and a shared package. Covers the explain output, the envelope, the gates and the command-line policy.node-islands-user-js.cjs: SC8101–SC8105.tests/diagnostics/node-islands-config(SC8004 with code frames inpackage.json). Its order-parity baseline is recorded, andpnpm test:ts7 --baselines-onlypasses.node24-url-authority, WebCrypto HMAC,net.BlockList, legacy url) also fail on main in the same sandbox, because its Node is 24.15.pnpm lintandpnpm format:checkpass.Not in this milestone
statementsInNodeIslands. Both depend on islands being real (NI-4).🤖 Generated with Claude Code