Scope-B milestone NI-1, API side: the explicit call API that replaces the
build container's hand-written node subprocess (api patch 09).
- The new package @scriptc/node exports callSync(specifier, name, ...args)
and call(...). The module loads with require() from the calling module;
arguments and results cross as JSON copies; a thrown Error crosses as its
nearest intrinsic class with its message and string code, other thrown
values as JSON copies; callSync refuses a function that returns a
promise. Its Node implementation runs the calls in-process with the same
copies, so a program prints the same under Node and compiled.
- The compiler lowers calls to the named or namespace imports
(node-api-import.ts, lower-node-island.ts) to the nodeIsland.callSync
and nodeIsland.call libCalls: the calling module's real path, the
specifier, the export name and the boxed argument array, with the result
checked against the declared type like `JSON.parse(s) as T`. Arguments
and results whose types are not JSON data are refused at build time, and
the functions and the namespace refuse as values.
- Corpus programs 6800-6803 (sync and async results, errors, process.exit
from Node with the program's exit listeners, Node's pending timers
keeping the program alive) run under Node and as binaries that load
libnode; `// @requires-libnode` skips them where SCRIPTC_LIBNODE names no
pack (until the pack CI matrix publishes packs). The node-island harness
covers loading Node only on the first call, the beside packaging, a
missing pack, a pack of another Node version or bridge ABI, and the
executable's symbols.
- Release tooling publishes @scriptc/node with the other packages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>