Skip to content

feat: expand standard library lowerings and add GCC toolchain driver support - #249

Open
mcpe500 wants to merge 23 commits into
vercel-labs:mainfrom
mcpe500:feat/stdlib-lowerings-and-gcc-support
Open

feat: expand standard library lowerings and add GCC toolchain driver support#249
mcpe500 wants to merge 23 commits into
vercel-labs:mainfrom
mcpe500:feat/stdlib-lowerings-and-gcc-support

Conversation

@mcpe500

@mcpe500 mcpe500 commented Aug 28, 2026

Copy link
Copy Markdown

Summary

This PR expands standard library lowering support across several built-in APIs and adds SCRIPTC_CC=gcc toolchain driver support for Linux environments. All extended built-ins have been verified with differential tests ensuring 100% byte-for-byte identical output against Node.js and Bun.js.

Enhancements & Built-in Lowerings

  1. Array.* & Array.prototype.*:

    • Array.isArray(x) on dynamic and computed expression values.
    • Array.prototype.splice(start, deleteCount, ...items) with variadic element insertion.
    • Array.from(Set / Array / String) native iterable conversion.
    • Array.of(...items) static constructor.
  2. Set.* & Set.prototype.*:

    • new Set(iterable) supporting Array and Set iterable initializers.
    • Nullable and optional Set<T> | null and Set<T> | undefined union arms support.
  3. Object.*:

    • Object.fromEntries(iterable) supporting tuple entries and string row arrays.
    • Object.keys(), Object.values(), Object.entries().
  4. crypto.*:

    • crypto.timingSafeEqual(a, b) constant-time XOR comparison in runtime C.
    • Bare createHash(alg).update(data).digest() returning raw Buffer/Uint8Array.
  5. process.*:

    • process.memoryUsage() record lowering (rss, heapTotal, heapUsed, external, arrayBuffers).
  6. net.* & URL:

    • net.isIP(str), net.isIPv4(str), net.isIPv6(str) IP address validation.
    • URL.port property getter extraction.
  7. Toolchain Support:

    • Added SCRIPTC_CC=gcc driver support in native-toolchain.ts.

Verification

All 12 extended test suites pass with 100% byte-for-byte parity against Node.js (v26) and Bun.js (v1.4):

  • 1200 - Array.isArray Extended
  • 1201 - Array.splice with Items
  • 1202 - crypto.timingSafeEqual
  • 1203 - crypto bare digest()
  • 1204 - net.isIP / isIPv4 / isIPv6
  • 1205 - URL.port property
  • 1206 - process.memoryUsage()
  • 1207 - Array.from(Set / Array)
  • 1208 - Nullable Set/Date in Unions
  • 1209 - Array.of static method
  • 1210 - Object.fromEntries & Object.entries
  • 1211 - new Set with Array Iterable

@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

@mcpe500 is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@vercel vercel Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

LLVM unionNewOwned/unionExtract route date union arms through the ref-counted-pointer path, emitting a double where LLVM expects a ptr and producing invalid IR for Date | null / Date | undefined unions.

Fix on Vercel

Comment thread packages/compiler/src/frontend/lowering/lower-calls.ts Outdated
mcpe500 added 21 commits August 28, 2026 09:29
URL.origin, os.freemem/loadavg, process.version, Function type,
new Date(any), new Set(iterable), Number(any/dyn), ReadonlyArray.includes,
Object.entries/values, mixed logical operators, catch property basics.

14 compiler/runtime files + 12 differential corpus tests.
Fork-compatible: differential stdout/stderr/exit byte-identical vs Node.

Co-authored-by: internal-model
- os.arch maps to process.arch via surfaces.ts (same runtime string)
- Promise.allSettled lowers via sequential await loop helper
  (%promise.allSettled) producing honest subset {status:string}[]
  sequential helper preserves order and always fulfills
  also supports dynamic island via jsOp when marshalable
- corpus 2727-os-arch and 2728-promise-allsettled differential PASS (gcc)

ai-core scriptc:dev blockers reduced: os.arch and allSettled now pass
… + fs shim callbacks

- vendor-archives: mbedtls host-arch compile used hardcoded clang; use
  SCRIPTC_CC like the quickjs path (fixes spawn clang ENOENT on gcc-only hosts)
- scr_island: SCRIPTC_VERBOSE=1 prints the engine exception .stack before the
  uncaught bridge swallows it (default output unchanged)
- scr_island: node:fs shim gains ReadStream/WriteStream constructors and
  callback-style readFile/writeFile/appendFile/mkdir/rm/realpath/exists
size_t a_len = a->len * scr_bytes_elem_size(a->elem);
size_t b_len = b->len * scr_bytes_elem_size(b->elem);
if (a_len != b_len) {
scr_throw_error_msg(SCR_ERR_RANGE, "Input buffers must have the same byte length", 42);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
scr_throw_error_msg(SCR_ERR_RANGE, "Input buffers must have the same byte length", 42);
scr_throw_error_msg(SCR_ERR_RANGE, "Input buffers must have the same byte length", 44);

Error message length of 42 truncates the 44-byte "Input buffers must have the same byte length" RangeError message to "Input buffers must have the same byte leng"

Fix on Vercel

Comment on lines +9502 to +9507
" if (builtins.process().env.SCRIPTC_VERBOSE === '1') {\n"
" host.write(2, 'scriptc: captureTrace raw=' + JSON.stringify(raw) + '\\n');\n"
" host.write(2, 'scriptc: captureTrace parsed=' + frames.length + ' prep=' + (prepAtCapture === null ? 'null' : 'fn') + '\\n');\n"
" for (const f of frames) host.write(2, 'scriptc: pf ' + JSON.stringify(String(f)) + '\\n');\n"
" }\n"
" const prepAtCapture = typeof Error.prepareStackTrace === 'function' ? Error.prepareStackTrace : null;\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
" if (builtins.process().env.SCRIPTC_VERBOSE === '1') {\n"
" host.write(2, 'scriptc: captureTrace raw=' + JSON.stringify(raw) + '\\n');\n"
" host.write(2, 'scriptc: captureTrace parsed=' + frames.length + ' prep=' + (prepAtCapture === null ? 'null' : 'fn') + '\\n');\n"
" for (const f of frames) host.write(2, 'scriptc: pf ' + JSON.stringify(String(f)) + '\\n');\n"
" }\n"
" const prepAtCapture = typeof Error.prepareStackTrace === 'function' ? Error.prepareStackTrace : null;\n"
" const prepAtCapture = typeof Error.prepareStackTrace === 'function' ? Error.prepareStackTrace : null;\n"
" if (builtins.process().env.SCRIPTC_VERBOSE === '1') {\n"
" host.write(2, 'scriptc: captureTrace raw=' + JSON.stringify(raw) + '\\n');\n"
" host.write(2, 'scriptc: captureTrace parsed=' + frames.length + ' prep=' + (prepAtCapture === null ? 'null' : 'fn') + '\\n');\n"
" for (const f of frames) host.write(2, 'scriptc: pf ' + JSON.stringify(String(f)) + '\\n');\n"
" }\n"

The injected Error.captureStackTrace shim references block-scoped const prepAtCapture in the SCRIPTC_VERBOSE diagnostic block before it is declared, hitting the temporal dead zone and throwing ReferenceError on every captureStackTrace call when verbose mode is enabled.

Fix on Vercel

* same combinator, and a HETEROGENEOUS tuple of promises
* (Promise<[A, B]>) lowers as sequential in-order awaits building the
* tuple record. Null otherwise: non-literal arguments keep the array
* path and its fences. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The heterogeneous branch of lowerPromiseAllTupleCall unconditionally emits awaitExpr IR nodes, producing invalid IR when Promise.all([...heterogeneous...] as const) appears in a non-async body, and eagerly awaits (returning a record instead of a Promise) when the result is not directly awaited.

Fix on Vercel

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant