Files
scriptc/packages/node/index.d.ts
T
Malte UblandClaude Opus 5.5 51e9812493 Call into Node.js from compiled programs with @scriptc/node
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>
2026-10-21 09:59:55 -07:00

37 lines
1.6 KiB
TypeScript

/** Calls the function `name` exported by the module `specifier` and returns
* its result.
*
* In scriptc builds the call runs in Node.js loaded into the program on
* the first call (the libnode pack recorded at build time, or
* SCRIPTC_LIBNODE). Under Node.js it runs in the same process too. Either
* way:
*
* - the module loads with require() from the calling module, so a relative
* specifier resolves from the caller's directory and a bare one from its
* node_modules (ES modules load through require(esm));
* - the arguments cross as a copy, `JSON.parse(JSON.stringify(args))`, and
* the function runs with the module namespace as `this`;
* - the result crosses as its JSON copy (undefined stays undefined), and
* scriptc checks it against `T` like `JSON.parse(text) as T`;
* - a thrown Error crosses as a new error of its nearest intrinsic class
* (Error, TypeError, RangeError, SyntaxError, ReferenceError, EvalError,
* URIError) with its message and string `code`; other thrown values cross
* as JSON copies.
*
* A function that returns a promise cannot be called synchronously: the
* call throws a TypeError. Use {@link call}. */
export declare function callSync<T = unknown>(
specifier: string,
name: string,
...args: unknown[]
): T;
/** Like {@link callSync}, asynchronously: the function may return a
* promise, whose result is copied when it settles. The returned promise
* rejects instead of throwing, also when the arguments cannot be copied. */
export declare function call<T = unknown>(
specifier: string,
name: string,
...args: unknown[]
): Promise<T>;