@scriptc/compiler 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +153 -24
- package/ambient/scriptc.d.ts +2 -2
- package/dist/backend/cc.d.ts +10 -2
- package/dist/backend/cc.js +12 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.js +1 -1
- package/dist/backend/emission/emit-exprs.js +235 -64
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +14 -14
- package/dist/backend/emission/emit-walkers.js +44 -44
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +3 -3
- package/dist/backend/emission/emitter.js +8 -8
- package/dist/backend/emission/may-throw.js +1 -1
- package/dist/backend/llvm/dyn.d.ts +10 -10
- package/dist/backend/llvm/dyn.js +26 -26
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +140 -49
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -1
- package/dist/backend/llvm/walkers.js +2 -2
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +1 -1
- package/dist/diagnostics/diagnostic.js +4 -3
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/crypto-tables.d.ts +7 -0
- package/dist/frontend/lowering/crypto-tables.js +139 -0
- package/dist/frontend/lowering/crypto-tables.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.js +5 -5
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +12 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +45 -27
- package/dist/frontend/lowering/lower-builtins.js +203 -70
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +4 -4
- package/dist/frontend/lowering/lower-calls.js +74 -66
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +41 -7
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +5 -5
- package/dist/frontend/lowering/lower-containers.js +19 -19
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.js +2 -2
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +7 -7
- package/dist/frontend/lowering/lower-exprs.js +227 -119
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +5 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +12 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -17
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +11 -1
- package/dist/frontend/lowering/lower-namespaces.js +41 -6
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +21 -0
- package/dist/frontend/lowering/lower-server.js +278 -23
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
- package/dist/frontend/lowering/lower-stmts.js +195 -34
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +67 -23
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +31 -13
- package/dist/frontend/lowering/lowerer.js +99 -45
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +6 -0
- package/dist/frontend/lowering/surfaces.js +78 -2
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.js +1 -1
- package/dist/frontend/shared.js +7 -7
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +2 -2
- package/dist/frontend/types.js +27 -15
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +44 -8
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +208 -106
- package/dist/ir/nodes.js +100 -22
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +96 -38
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.js +13 -0
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/profile.d.ts +8 -6
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +1 -1
- package/dist/library/sidecar.js +20 -7
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +289 -4
|
@@ -15,6 +15,7 @@ import { invalidJsonModuleDiag, requiresDynamicImportDiag } from "../../diagnost
|
|
|
15
15
|
import { builtinModuleFnOf, FS_READDIR_DOCUMENTED_OPTIONS, FS_WATCH_DOCUMENTED_OPTIONS, FS_WRITE_FILE_DOCUMENTED_OPTIONS, QS_PARSE_DOCUMENTED_OPTIONS, QS_STRINGIFY_DOCUMENTED_OPTIONS, READLINE_DOCUMENTED_OPTIONS, builtinConstLit, fenceOrDropOptionKey, isChildSurfaceMember, } from "./surfaces.js";
|
|
16
16
|
import { conditionalSpreadOf, lowerDynObjectLiteral } from "./lower-exprs.js";
|
|
17
17
|
import { HTTP2_CONSTANTS } from "./http2-constants.js";
|
|
18
|
+
import { CRYPTO_CIPHERS, CRYPTO_CONSTANTS, CRYPTO_CURVES, CRYPTO_HASHES } from "./crypto-tables.js";
|
|
18
19
|
import { timerStyleCallback } from "./lower-calls.js";
|
|
19
20
|
import { registerHttpClientFnBinding } from "./lower-server.js";
|
|
20
21
|
import { BOOL, BYTES_U8, CHILD_T, CHILDSTREAM_T, DYN, F64, FSWATCHER_T, PROCSTREAM_T, JSVAL, NULL_T, SEARCH_PARAMS_T, SPAWNRES_T, STRING, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, funcOf, isUnitType, typeEquals, typeKey } from "../../ir/nodes.js";
|
|
@@ -376,38 +377,60 @@ export function lowerCreateRequireCall(L, call, loc) {
|
|
|
376
377
|
loc,
|
|
377
378
|
};
|
|
378
379
|
}
|
|
379
|
-
/**
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
|
|
384
|
-
|
|
380
|
+
/** The builtin modules whose `constants` object bakes as literals at
|
|
381
|
+
* every access site (the fs.constants precedent, scaled up): http2's
|
|
382
|
+
* full Node v24 table, and crypto's OpenSSL-constant table. The object
|
|
383
|
+
* itself never materializes at runtime. */
|
|
384
|
+
const BUILTIN_CONSTANTS_TABLES = {
|
|
385
|
+
http2: {
|
|
386
|
+
table: HTTP2_CONSTANTS,
|
|
387
|
+
hint: "the table bakes Node v24's 240 members as literals — this name is not one of them",
|
|
388
|
+
},
|
|
389
|
+
crypto: {
|
|
390
|
+
table: CRYPTO_CONSTANTS,
|
|
391
|
+
hint: "the table bakes Node v24's crypto.constants members as literals — this name is not one of them",
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
/** The module whose baked-constants OBJECT `node` denotes, or null — any
|
|
395
|
+
* of the spellings: `http2.constants`/`crypto.constants` through a
|
|
396
|
+
* namespace/require binding, a destructured or member-bound `constants`
|
|
397
|
+
* alias from the module, or `require("http2").constants` inline. The
|
|
398
|
+
* object itself never materializes; each member read bakes as its
|
|
399
|
+
* literal. */
|
|
400
|
+
export function builtinConstantsModuleOf(L, node) {
|
|
401
|
+
let module = null;
|
|
385
402
|
if (ts.isPropertyAccessExpression(node) && !node.questionDotToken) {
|
|
386
403
|
if (node.name.text !== "constants")
|
|
387
|
-
return
|
|
404
|
+
return null;
|
|
388
405
|
const bi = L.builtinMemberOf(node);
|
|
389
|
-
if (bi
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
406
|
+
if (bi)
|
|
407
|
+
module = bi.module;
|
|
408
|
+
else {
|
|
409
|
+
const spec = requireSpecOf(node.expression);
|
|
410
|
+
module = spec !== null ? canonicalBuiltinModule(spec) : null;
|
|
411
|
+
}
|
|
393
412
|
}
|
|
394
|
-
if (ts.isIdentifier(node)) {
|
|
413
|
+
else if (ts.isIdentifier(node)) {
|
|
395
414
|
const bi = builtinImportOf(L, node);
|
|
396
|
-
|
|
415
|
+
if (bi !== null && bi.member === "constants")
|
|
416
|
+
module = bi.module;
|
|
397
417
|
}
|
|
398
|
-
return
|
|
418
|
+
return module !== null && own(BUILTIN_CONSTANTS_TABLES, module) !== undefined ? module : null;
|
|
399
419
|
}
|
|
400
|
-
/** `constants.NGHTTP2_CANCEL`
|
|
401
|
-
* literal; unknown members fence by name.
|
|
402
|
-
* the constants object (the property
|
|
403
|
-
|
|
420
|
+
/** `constants.NGHTTP2_CANCEL` / `constants.SSL_OP_NO_TICKET` (any baked-
|
|
421
|
+
* constants spelling) → the literal; unknown members fence by name.
|
|
422
|
+
* Null when the receiver is not a baked constants object (the property
|
|
423
|
+
* chain keeps trying). */
|
|
424
|
+
export function lowerBuiltinConstantsProperty(L, expr) {
|
|
404
425
|
if (expr.questionDotToken)
|
|
405
426
|
return null;
|
|
406
|
-
|
|
427
|
+
const module = builtinConstantsModuleOf(L, expr.expression);
|
|
428
|
+
if (module === null)
|
|
407
429
|
return null;
|
|
408
|
-
const
|
|
430
|
+
const entry = BUILTIN_CONSTANTS_TABLES[module];
|
|
431
|
+
const value = own(entry.table, expr.name.text);
|
|
409
432
|
if (value === undefined) {
|
|
410
|
-
L.noLowering(
|
|
433
|
+
L.noLowering(`${module}.constants.${expr.name.text}`, expr, entry.hint);
|
|
411
434
|
}
|
|
412
435
|
return builtinConstLit(value, locOf(expr));
|
|
413
436
|
}
|
|
@@ -487,27 +510,30 @@ function perfNowFnValueOf(L) {
|
|
|
487
510
|
}
|
|
488
511
|
return name;
|
|
489
512
|
}
|
|
490
|
-
/** True for `const { NGHTTP2_CANCEL, ... } = http2.constants`
|
|
491
|
-
*
|
|
492
|
-
* defaults/nesting) over
|
|
493
|
-
*
|
|
494
|
-
* (lowerVarDecl and collectGlobals both
|
|
495
|
-
* baked literal
|
|
496
|
-
|
|
513
|
+
/** True for `const { NGHTTP2_CANCEL, ... } = http2.constants` (and the
|
|
514
|
+
* crypto.constants twin) — a plain object destructure (identifier
|
|
515
|
+
* elements, renames allowed, no rest/defaults/nesting) over a baked
|
|
516
|
+
* constants object whose every name is in its table. The declaration is
|
|
517
|
+
* alias plumbing with no storage (lowerVarDecl and collectGlobals both
|
|
518
|
+
* skip it); each USE reads its baked literal
|
|
519
|
+
* (builtinConstantBindingOf). */
|
|
520
|
+
export function builtinConstantsDestructureDecl(L, nameNode, init) {
|
|
497
521
|
if (!ts.isObjectBindingPattern(nameNode) || !init)
|
|
498
522
|
return false;
|
|
499
|
-
|
|
523
|
+
const module = builtinConstantsModuleOf(L, init);
|
|
524
|
+
if (module === null)
|
|
500
525
|
return false;
|
|
526
|
+
const table = BUILTIN_CONSTANTS_TABLES[module].table;
|
|
501
527
|
return nameNode.elements.every((el) => !el.dotDotDotToken &&
|
|
502
528
|
el.initializer === undefined &&
|
|
503
529
|
el.name !== undefined &&
|
|
504
530
|
ts.isIdentifier(el.name) &&
|
|
505
531
|
(el.propertyName === undefined || ts.isIdentifier(el.propertyName)) &&
|
|
506
|
-
own(
|
|
532
|
+
own(table, (el.propertyName ?? el.name).text) !== undefined);
|
|
507
533
|
}
|
|
508
|
-
/** Resolves an identifier bound by
|
|
509
|
-
* baked literal value. Null for every other binding. */
|
|
510
|
-
export function
|
|
534
|
+
/** Resolves an identifier bound by a builtinConstantsDestructureDecl to
|
|
535
|
+
* its baked literal value. Null for every other binding. */
|
|
536
|
+
export function builtinConstantBindingOf(L, ident) {
|
|
511
537
|
const symbol = L.checker.getSymbolAtLocation(ident);
|
|
512
538
|
const decl = symbol ? L.checker.declarationsOf(symbol)[0] : undefined;
|
|
513
539
|
if (!decl || !ts.isBindingElement(decl) || decl.dotDotDotToken || decl.initializer)
|
|
@@ -517,14 +543,15 @@ export function http2ConstantBindingOf(L, ident) {
|
|
|
517
543
|
const varDecl = decl.parent.parent;
|
|
518
544
|
if (!ts.isVariableDeclaration(varDecl) || varDecl.initializer === undefined)
|
|
519
545
|
return null;
|
|
520
|
-
|
|
546
|
+
const module = builtinConstantsModuleOf(L, varDecl.initializer);
|
|
547
|
+
if (module === null)
|
|
521
548
|
return null;
|
|
522
549
|
const key = decl.propertyName && ts.isIdentifier(decl.propertyName)
|
|
523
550
|
? decl.propertyName.text
|
|
524
551
|
: decl.name !== undefined && ts.isIdentifier(decl.name) ? decl.name.text : null;
|
|
525
552
|
if (key === null)
|
|
526
553
|
return null;
|
|
527
|
-
const value = own(
|
|
554
|
+
const value = own(BUILTIN_CONSTANTS_TABLES[module].table, key);
|
|
528
555
|
if (value === undefined)
|
|
529
556
|
return null;
|
|
530
557
|
return builtinConstLit(value, locOf(ident));
|
|
@@ -587,7 +614,7 @@ function optionMember(p) {
|
|
|
587
614
|
* utimes family runs on its time arguments: finite numbers pass
|
|
588
615
|
* (negatives answer now/1000, Node's shape), numeric STRINGS coerce
|
|
589
616
|
* through ToNumber's loose-equality gate, everything else throws
|
|
590
|
-
* Node's exact ERR_INVALID_ARG_TYPE. The argument crosses as a
|
|
617
|
+
* Node's exact ERR_INVALID_ARG_TYPE. The argument crosses as a dyn
|
|
591
618
|
* value so the runtime renders the Received tail. Null when this is
|
|
592
619
|
* not that call (the table fence stays for other shapes). */
|
|
593
620
|
export function lowerFsToUnixTimestampCall(L, expr, bi, loc) {
|
|
@@ -605,7 +632,7 @@ export function lowerFsToUnixTimestampCall(L, expr, bi, loc) {
|
|
|
605
632
|
/** The fs validation-ladder spoke (checked-dynamic lane, JS sources
|
|
606
633
|
* only — TypeScript keeps its compile fences): implemented-namespace
|
|
607
634
|
* calls whose misuse Node rejects with typed errors lower to fs.*Chk
|
|
608
|
-
* libCalls that replicate the validation ladder over
|
|
635
|
+
* libCalls that replicate the validation ladder over dyn values and
|
|
609
636
|
* throw Node's exact ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE /
|
|
610
637
|
* ERR_OUT_OF_RANGE — the honest tail (the real operation where one
|
|
611
638
|
* exists, the compiler-rendered SC2020 fence otherwise) runs only
|
|
@@ -619,7 +646,7 @@ export function lowerFsLadderCall(L, expr, bi, loc) {
|
|
|
619
646
|
const args = expr.arguments;
|
|
620
647
|
if (args.some(ts.isSpreadElement))
|
|
621
648
|
return null;
|
|
622
|
-
// Every ladder argument crosses as a
|
|
649
|
+
// Every ladder argument crosses as a dyn value; an argument that
|
|
623
650
|
// cannot leaves the historical fence in place.
|
|
624
651
|
const dynArg = (node) => {
|
|
625
652
|
if (!node)
|
|
@@ -657,7 +684,7 @@ export function lowerFsLadderCall(L, expr, bi, loc) {
|
|
|
657
684
|
// false THROUGH it, and the answer is asynchronous.
|
|
658
685
|
// A provably-non-file `new URL('<literal>')` path (the suite's
|
|
659
686
|
// https://foo probe): Node answers false through the callback
|
|
660
|
-
// synchronously — the
|
|
687
|
+
// synchronously — the checked-dynamic tree has no URL kind, so the path slot
|
|
661
688
|
// carries the unvalidatable token instead (construction of a
|
|
662
689
|
// parseable literal is effect-free; file: URLs keep the fence —
|
|
663
690
|
// they would need the real path conversion).
|
|
@@ -779,7 +806,7 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
|
|
|
779
806
|
}
|
|
780
807
|
// node:querystring — parse/stringify are entirely special-cased (the
|
|
781
808
|
// sep/eq/options completions, parse's call-site-shaped dictionary
|
|
782
|
-
// result, stringify's
|
|
809
|
+
// result, stringify's dyn-crossing object argument); decode/encode
|
|
783
810
|
// are Node's own aliases of the pair (`const decode = parse` in the
|
|
784
811
|
// module source) and take the same lowerings. escape/unescape ride
|
|
785
812
|
// the generic table tail below.
|
|
@@ -817,7 +844,7 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
|
|
|
817
844
|
}
|
|
818
845
|
}
|
|
819
846
|
// node:diagnostics_channel — the module-level pub/sub surface. The
|
|
820
|
-
// subscriber arguments box into the
|
|
847
|
+
// subscriber arguments box into the checked-dynamic tree (dyn) so JS harness wrappers
|
|
821
848
|
// (test/common's mustCall — a rest-args function value) and typed
|
|
822
849
|
// closures both cross; publish and the Channel methods lower in
|
|
823
850
|
// lowerDcChannelMethodCall over the f64 channel handle.
|
|
@@ -2484,7 +2511,7 @@ function isReadlineTyped(L, node) {
|
|
|
2484
2511
|
function dcChannelNameArg(L, node) {
|
|
2485
2512
|
return L.lowerExprExpecting(node, STRING);
|
|
2486
2513
|
}
|
|
2487
|
-
/** A diagnostics_channel subscriber as a
|
|
2514
|
+
/** A diagnostics_channel subscriber as a dyn value: dyn callables pass
|
|
2488
2515
|
* through (test/common's mustCall wrapper — an untyped JS function
|
|
2489
2516
|
* value), boxable typed closures ride dynFrom. Identity is preserved
|
|
2490
2517
|
* either way, so unsubscribe(fn) finds the subscribe(fn) entry. */
|
|
@@ -2506,14 +2533,14 @@ function dcSubscriberArg(L, node) {
|
|
|
2506
2533
|
canBoxFuncIntoDyn(cb.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
|
|
2507
2534
|
return { kind: "dynFrom", value: cb, type: DYN, loc: locOf(node) };
|
|
2508
2535
|
}
|
|
2509
|
-
L.unsupported("SC1090", node, `channel subscribers of type '${L.fmt(cb.type)}' (subscribers cross as
|
|
2536
|
+
L.unsupported("SC1090", node, `channel subscribers of type '${L.fmt(cb.type)}' (subscribers cross as dyn functions — parameters must be dyn-representable)`);
|
|
2510
2537
|
}
|
|
2511
|
-
/** A published message as a
|
|
2538
|
+
/** A published message as a dyn value: dyn passes through, everything
|
|
2512
2539
|
* in the dynFrom domain (JSON-safe data, bytes, %Error, boxable
|
|
2513
2540
|
* functions, handle kinds) boxes; the rest fences with the domain named. */
|
|
2514
2541
|
function dcMessageArg(L, node) {
|
|
2515
2542
|
// An explicit `undefined` argument (tracePromise(fn, ctx, undefined,
|
|
2516
|
-
// ...args) — Node's own no-this spelling) is the undefined
|
|
2543
|
+
// ...args) — Node's own no-this spelling) is the undefined dyn value,
|
|
2517
2544
|
// exactly what an omitted slot defaults to.
|
|
2518
2545
|
if (ts.isIdentifier(node) && node.text === "undefined") {
|
|
2519
2546
|
return dynUndefinedExpr(locOf(node));
|
|
@@ -2524,7 +2551,7 @@ function dcMessageArg(L, node) {
|
|
|
2524
2551
|
if (canConvertToDyn(msg.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
|
|
2525
2552
|
return { kind: "dynFrom", value: msg, type: DYN, loc: locOf(node) };
|
|
2526
2553
|
}
|
|
2527
|
-
L.unsupported("SC1090", node, `publishing '${L.fmt(msg.type)}' messages (messages cross as
|
|
2554
|
+
L.unsupported("SC1090", node, `publishing '${L.fmt(msg.type)}' messages (messages cross as dyn values — JSON-safe data, Uint8Array, errors, and functions)`);
|
|
2528
2555
|
}
|
|
2529
2556
|
/** True when `node`'s checker type is diagnostics_channel's Channel
|
|
2530
2557
|
* (stdlib provenance plus the ambient module, the readline.Interface
|
|
@@ -2565,7 +2592,7 @@ export function lowerDcChannelMethodCall(L, call, access) {
|
|
|
2565
2592
|
// bindStore(store[, transform]) / unbindStore(store) / runStores(data,
|
|
2566
2593
|
// fn[, thisArg[, ...args]]): the AsyncLocalStorage integration — the
|
|
2567
2594
|
// store argument is the ALS f64 handle; the transform crosses as a
|
|
2568
|
-
//
|
|
2595
|
+
// dyn function (absent = identity, the undefined dyn value); runStores
|
|
2569
2596
|
// enters the bound stores, publishes inside them, and forwards
|
|
2570
2597
|
// this/arguments to fn exactly like the trace calls.
|
|
2571
2598
|
if ((name === "bindStore" || name === "unbindStore") &&
|
|
@@ -2608,7 +2635,7 @@ function isAlsTyped(L, node) {
|
|
|
2608
2635
|
}
|
|
2609
2636
|
/** Method calls on AsyncLocalStorage receivers: run(store, fn, ...args),
|
|
2610
2637
|
* exit(fn, ...args), getStore(), enterWith(store), disable() — over the
|
|
2611
|
-
* f64 store handle (als.* libCalls; values cross as
|
|
2638
|
+
* f64 store handle (als.* libCalls; values cross as dyn values). Null
|
|
2612
2639
|
* for non-ALS receivers. */
|
|
2613
2640
|
export function lowerAlsMethodCall(L, call, access) {
|
|
2614
2641
|
if (call.questionDotToken || access.questionDotToken)
|
|
@@ -2678,8 +2705,8 @@ function isDcTracingChannelTyped(L, node) {
|
|
|
2678
2705
|
L.isStdlibFile(d.getSourceFile()));
|
|
2679
2706
|
}
|
|
2680
2707
|
const DC_TRACE_EVENTS = ["start", "end", "asyncStart", "asyncEnd", "error"];
|
|
2681
|
-
/** A TracingChannel handlers object as a
|
|
2682
|
-
* an INLINE object literal of plain event-name properties builds the
|
|
2708
|
+
/** A TracingChannel handlers object as a dyn value: dyn passes through;
|
|
2709
|
+
* an INLINE object literal of plain event-name properties builds the checked-dynamic tree
|
|
2683
2710
|
* object member-by-member (each value through the message conversion —
|
|
2684
2711
|
* closures box by identity, so unsubscribe still matches), covering the
|
|
2685
2712
|
* `{ start: () => {} }` spelling whose record type (function members)
|
|
@@ -2708,7 +2735,7 @@ function dcHandlersArg(L, node) {
|
|
|
2708
2735
|
}
|
|
2709
2736
|
return dcMessageArg(L, node);
|
|
2710
2737
|
}
|
|
2711
|
-
/** A trace-call argument list's tail as ONE
|
|
2738
|
+
/** A trace-call argument list's tail as ONE dyn array (dynArrLit over
|
|
2712
2739
|
* per-element conversions). Spread arguments fence — the built array
|
|
2713
2740
|
* must mirror the call site's argument vector exactly. */
|
|
2714
2741
|
function dcTraceArgsArr(L, args, loc) {
|
|
@@ -2721,9 +2748,9 @@ function dcTraceArgsArr(L, args, loc) {
|
|
|
2721
2748
|
return { kind: "dynArrLit", elems, type: DYN, loc };
|
|
2722
2749
|
}
|
|
2723
2750
|
/** Method calls on TracingChannel receivers: subscribe/unsubscribe over
|
|
2724
|
-
* a
|
|
2751
|
+
* a dyn handlers object, traceSync/traceCallback through the runtime's
|
|
2725
2752
|
* publish choreography (dc.tcTraceSync/dc.tcTraceCallback — fn, context,
|
|
2726
|
-
* thisArg, and the argument vector all cross as
|
|
2753
|
+
* thisArg, and the argument vector all cross as dyn values; context
|
|
2727
2754
|
* defaults to a fresh `{}` and thisArg to undefined, Node's defaults),
|
|
2728
2755
|
* and tracePromise through the reaction-fiber choreography
|
|
2729
2756
|
* (dc.tcTracePromise — the result is the reaction promise, typed
|
|
@@ -2994,7 +3021,7 @@ export function strdecHelper(L, op, shapeId, loc) {
|
|
|
2994
3021
|
}
|
|
2995
3022
|
/** `JSON.parse(text)` / `JSON.stringify(value)`.
|
|
2996
3023
|
* - parse → a may-throw `libCall` producing a dyn value (the runtime JSON
|
|
2997
|
-
*
|
|
3024
|
+
* dyn); malformed input throws a catchable SyntaxError-shaped string.
|
|
2998
3025
|
* The divergence override types the one-argument form `unknown`; the
|
|
2999
3026
|
* lib's reviver form typechecks (returning `any`) and is fenced here.
|
|
3000
3027
|
* - stringify → the type-DIRECTED `jsonStringify` node: the lib
|
|
@@ -3048,8 +3075,8 @@ export function lowerJsonMethodCall(L, call, access) {
|
|
|
3048
3075
|
}
|
|
3049
3076
|
// A dyn ROOT (`JSON.stringify(u)` over unknown / `{}` / `Object` /
|
|
3050
3077
|
// `object` slots, the JSON.parse round-trip) serializes with the
|
|
3051
|
-
// runtime's
|
|
3052
|
-
//
|
|
3078
|
+
// runtime's dyn walker instead of a type-directed serializer — the
|
|
3079
|
+
// dyn is JSON-representable by construction (non-JSON values fenced
|
|
3053
3080
|
// at their conversion INTO the slot). Two edges, both documented:
|
|
3054
3081
|
// a root the stringify drops (runtime undefined) produces the TEXT
|
|
3055
3082
|
// "undefined" where Node produces the undefined VALUE (tsc's own lib
|
|
@@ -3268,6 +3295,41 @@ function lowerHashDigestChain(L, call, access) {
|
|
|
3268
3295
|
}
|
|
3269
3296
|
L.noLowering(`Hash.update of '${dataIr ? L.fmt(dataIr) : L.checker.typeToString(L.typeOf(dataNode))}' values`, dataNode, "string and Buffer/Uint8Array inputs are the lowered update forms");
|
|
3270
3297
|
}
|
|
3298
|
+
/** The node:crypto introspection statics — build-time constants of the
|
|
3299
|
+
* compiled runtime, baked at the call site (the http2.constants stance
|
|
3300
|
+
* extended to calls): getFips() answers 0 (no FIPS provider can ever
|
|
3301
|
+
* load into a compiled binary — Node's own answer for a non-FIPS
|
|
3302
|
+
* build), and getCiphers()/getHashes()/getCurves() answer Node v24's
|
|
3303
|
+
* name lists as fresh string[] literals. The lists are INTROSPECTION
|
|
3304
|
+
* data (Node's contract is "names the provider recognizes"); the
|
|
3305
|
+
* operations behind the names keep their per-member fences — a program
|
|
3306
|
+
* that probes the list and then constructs a cipher fences at the
|
|
3307
|
+
* construction site, never here. Null for other members (the dispatch
|
|
3308
|
+
* keeps trying). */
|
|
3309
|
+
export function lowerCryptoModuleCall(L, expr, bi, loc) {
|
|
3310
|
+
if (bi.module !== "crypto")
|
|
3311
|
+
return null;
|
|
3312
|
+
const LISTS = {
|
|
3313
|
+
getCiphers: CRYPTO_CIPHERS,
|
|
3314
|
+
getHashes: CRYPTO_HASHES,
|
|
3315
|
+
getCurves: CRYPTO_CURVES,
|
|
3316
|
+
};
|
|
3317
|
+
const list = own(LISTS, bi.member);
|
|
3318
|
+
if (bi.member !== "getFips" && list === undefined)
|
|
3319
|
+
return null;
|
|
3320
|
+
if (expr.arguments.length !== 0) {
|
|
3321
|
+
L.noLowering(`crypto.${bi.member} with ${expr.arguments.length} arguments`, expr);
|
|
3322
|
+
}
|
|
3323
|
+
if (bi.member === "getFips") {
|
|
3324
|
+
return { kind: "numLit", value: 0, type: F64, loc };
|
|
3325
|
+
}
|
|
3326
|
+
return {
|
|
3327
|
+
kind: "arrayLit",
|
|
3328
|
+
elems: list.map((s) => ({ kind: "strLit", value: s, type: STRING, loc })),
|
|
3329
|
+
type: arrayOf(STRING),
|
|
3330
|
+
loc,
|
|
3331
|
+
};
|
|
3332
|
+
}
|
|
3271
3333
|
/** Method calls on URL-typed receivers: `u.toString()` is Node's href
|
|
3272
3334
|
* serialization (the href getter's libCall). Everything else the lib
|
|
3273
3335
|
* declares fences member-qualified. Null for non-URL receivers. */
|
|
@@ -3390,7 +3452,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
|
|
|
3390
3452
|
// One name/value slot, WHATWG USVString rules: statically-string
|
|
3391
3453
|
// arguments lower directly; a symbol can never convert (V8's
|
|
3392
3454
|
// TypeError, statically decided); everything else crosses into the
|
|
3393
|
-
//
|
|
3455
|
+
// dyn and coerces at runtime with the object protocol (a user
|
|
3394
3456
|
// toString/valueOf runs and its throw propagates).
|
|
3395
3457
|
const strArg = (i) => {
|
|
3396
3458
|
const node = args[i];
|
|
@@ -3402,7 +3464,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
|
|
|
3402
3464
|
}
|
|
3403
3465
|
let v;
|
|
3404
3466
|
if (ts.isObjectLiteralExpression(node)) {
|
|
3405
|
-
// Object literals take the
|
|
3467
|
+
// Object literals take the dyn literal path directly (method
|
|
3406
3468
|
// members box as dyn functions — the typed record fence never
|
|
3407
3469
|
// applies to the coercion probes).
|
|
3408
3470
|
v = lowerDynObjectLiteral(L, node);
|
|
@@ -3415,7 +3477,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
|
|
|
3415
3477
|
v = { kind: "dynFrom", value: raw, type: DYN, loc: raw.loc };
|
|
3416
3478
|
}
|
|
3417
3479
|
else if (raw.type.kind === "record") {
|
|
3418
|
-
// A RECORD-represented value that cannot cross into the
|
|
3480
|
+
// A RECORD-represented value that cannot cross into the checked-dynamic tree (a
|
|
3419
3481
|
// func-carrying shape — the throwing-toString probes): run
|
|
3420
3482
|
// ToPrimitive's string hint STATICALLY. A zero-parameter
|
|
3421
3483
|
// toString func member is called (its throw propagates); a
|
|
@@ -3430,7 +3492,7 @@ export function lowerSearchParamsMethodCall(L, call, access) {
|
|
|
3430
3492
|
tsMember.type.kind === "func" &&
|
|
3431
3493
|
tsMember.type.params.length === 0 &&
|
|
3432
3494
|
L.dynConvertible(tsMember.type)) {
|
|
3433
|
-
// Box just the toString member into a fresh
|
|
3495
|
+
// Box just the toString member into a fresh dyn carrier and
|
|
3434
3496
|
// run the protocol at runtime — the boxed call propagates its
|
|
3435
3497
|
// throw, string answers convert, and a bare (void) return is
|
|
3436
3498
|
// ToString(undefined), all through one path.
|
|
@@ -3446,11 +3508,11 @@ export function lowerSearchParamsMethodCall(L, call, access) {
|
|
|
3446
3508
|
};
|
|
3447
3509
|
}
|
|
3448
3510
|
else {
|
|
3449
|
-
L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the
|
|
3511
|
+
L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the checked-dynamic tree — narrow unions first)");
|
|
3450
3512
|
}
|
|
3451
3513
|
}
|
|
3452
3514
|
else {
|
|
3453
|
-
L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the
|
|
3515
|
+
L.noLowering(`URLSearchParams.${name} with a '${L.fmt(raw.type)}' argument`, node, "string arguments are the lowered shape (other values coerce through the checked-dynamic tree — narrow unions first)");
|
|
3454
3516
|
}
|
|
3455
3517
|
}
|
|
3456
3518
|
return { kind: "libCall", fn: "dyn.toStringCoerce", args: [v], type: STRING, loc };
|
|
@@ -4552,7 +4614,7 @@ export function lowerQuerystringParseCall(L, call, loc) {
|
|
|
4552
4614
|
return { kind: "libCall", fn: "qs.parse", args: [str, sep, eq, maxKeys], type: result, loc };
|
|
4553
4615
|
}
|
|
4554
4616
|
/** querystring.stringify / querystring.encode: the object crosses as a
|
|
4555
|
-
*
|
|
4617
|
+
* dyn value (dynFrom — JSON-safe records and, in JS sources, dyn values
|
|
4556
4618
|
* directly) and Node's encodeStringified rules run in the runtime
|
|
4557
4619
|
* (scr_qs_stringify), so arrays expand to repeated keys and
|
|
4558
4620
|
* null/undefined values are empty. The default encoder is the one
|
|
@@ -4844,19 +4906,29 @@ export function lowerProcessMethodCall(L, call, access) {
|
|
|
4844
4906
|
// (test-event-emitter-special-event-names.js's process.on).
|
|
4845
4907
|
const SIGNALS = { SIGINT: 2, SIGTERM: 15 };
|
|
4846
4908
|
const signo = event !== null ? own(SIGNALS, event) : undefined;
|
|
4847
|
-
// 'unhandledRejection': the listener crosses as a
|
|
4909
|
+
// 'unhandledRejection': the listener crosses as a dyn function and
|
|
4848
4910
|
// the loop-end report dispatches it (reason, promise) per
|
|
4849
4911
|
// never-observed rejection instead of printing and exiting 1
|
|
4850
4912
|
// (scr_async.c; the end-of-turn timing is a SEMANTICS.md
|
|
4851
|
-
// divergence). `once
|
|
4852
|
-
|
|
4913
|
+
// divergence). `once` auto-removes after one delivery and
|
|
4914
|
+
// `off`/`removeListener` remove by closure identity — the warning
|
|
4915
|
+
// registry's story. 'rejectionHandled' is the sibling registry:
|
|
4916
|
+
// under the loop-exhaustion model its ONE firing window is a
|
|
4917
|
+
// handler attached during an unhandledRejection listener (earlier
|
|
4918
|
+
// handling never enters the report at all — the same documented
|
|
4919
|
+
// divergence), dispatched synchronously with the promise.
|
|
4920
|
+
if (event === "unhandledRejection" || event === "rejectionHandled") {
|
|
4853
4921
|
if (!ts.isExpressionStatement(call.parent)) {
|
|
4854
4922
|
L.unsupported("SC1090", call, "chaining process listener registration (the result is void here — register each listener as its own statement)");
|
|
4855
4923
|
}
|
|
4856
4924
|
const cb = dcSubscriberArg(L, call.arguments[1]);
|
|
4857
|
-
|
|
4925
|
+
const onceArg = { kind: "boolLit", value: member === "once", type: BOOL, loc };
|
|
4926
|
+
const fn = event === "unhandledRejection"
|
|
4927
|
+
? (isOff ? "process.offUnhandledRejection" : "process.onUnhandledRejection")
|
|
4928
|
+
: (isOff ? "process.offRejectionHandled" : "process.onRejectionHandled");
|
|
4929
|
+
return { kind: "libCall", fn, args: isOff ? [cb] : [cb, onceArg], type: VOID, loc };
|
|
4858
4930
|
}
|
|
4859
|
-
// 'warning': the listener crosses as a
|
|
4931
|
+
// 'warning': the listener crosses as a dyn function; emitWarning
|
|
4860
4932
|
// and the runtime deprecation sites dispatch synchronously
|
|
4861
4933
|
// (SEMANTICS.md). off/removeListener remove by closure identity.
|
|
4862
4934
|
if (event === "warning" && (member === "on" || isOff)) {
|
|
@@ -4873,7 +4945,7 @@ export function lowerProcessMethodCall(L, call, access) {
|
|
|
4873
4945
|
};
|
|
4874
4946
|
}
|
|
4875
4947
|
if (signo === undefined && event !== "exit") {
|
|
4876
|
-
L.noLowering(`process.${member}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, call.arguments[0], '"SIGINT", "SIGTERM", "exit", "warning", and "
|
|
4948
|
+
L.noLowering(`process.${member}(${event === null ? "non-literal event" : `"${event}"`}, ...)`, call.arguments[0], '"SIGINT", "SIGTERM", "exit", "warning", "unhandledRejection", and "rejectionHandled" are the supported process events (as literals)');
|
|
4877
4949
|
}
|
|
4878
4950
|
if (!ts.isExpressionStatement(call.parent)) {
|
|
4879
4951
|
L.unsupported("SC1090", call, "chaining process listener registration (the result is void here — register each listener as its own statement)");
|
|
@@ -4931,7 +5003,7 @@ export function lowerProcessMethodCall(L, call, access) {
|
|
|
4931
5003
|
}
|
|
4932
5004
|
return { kind: "libCall", fn: "process.onExit", args: [cb, onceArg], type: VOID, loc };
|
|
4933
5005
|
}
|
|
4934
|
-
// process.emitWarning(...): the argument vector crosses as ONE
|
|
5006
|
+
// process.emitWarning(...): the argument vector crosses as ONE dyn
|
|
4935
5007
|
// array and the runtime applies Node's full grammar (string or Error
|
|
4936
5008
|
// warning; type/ctor/options second; code/ctor third — wrong kinds
|
|
4937
5009
|
// throw ERR_INVALID_ARG_TYPE). A single SPREAD of a checked-dynamic
|
|
@@ -5596,9 +5668,70 @@ export function lowerPromiseStaticCall(L, call, access) {
|
|
|
5596
5668
|
};
|
|
5597
5669
|
return { kind: "intrinsic", name: "promise.all", args: [entriesArr], type: resultT, loc };
|
|
5598
5670
|
}
|
|
5671
|
+
// MIXED entries where some entry is already an ISLAND value (the
|
|
5672
|
+
// withPlugins shape: Promise.all([loadBuiltinPlugins(),
|
|
5673
|
+
// loadPlugins(plugins)]) with an 'any'-typed loader): the
|
|
5674
|
+
// ENGINE's own Promise.all runs — island entries pass through,
|
|
5675
|
+
// STATIC promises cross as real engine thenables (the reverse
|
|
5676
|
+
// bridge, payload-domain gated), plain values marshal per the
|
|
5677
|
+
// boundary — and the combined result stays an island value
|
|
5678
|
+
// (awaiting it rides the island→static promise bridge; element
|
|
5679
|
+
// reads are the routed keyed ops). All-static tuples keep the
|
|
5680
|
+
// typed fence hint below. --dynamic only by construction: jsval
|
|
5681
|
+
// entries exist only there.
|
|
5682
|
+
if (elems.some((e) => e.type.kind === "jsval")) {
|
|
5683
|
+
const diagsBefore = L.diags.length;
|
|
5684
|
+
try {
|
|
5685
|
+
const marshaled = argNode.elements.map((el, i) => L.jsvalIn(elems[i], el));
|
|
5686
|
+
return {
|
|
5687
|
+
kind: "jsOp",
|
|
5688
|
+
op: "callMethod",
|
|
5689
|
+
name: "all",
|
|
5690
|
+
args: [
|
|
5691
|
+
{ kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc },
|
|
5692
|
+
{ kind: "jsOp", op: "arrLit", args: marshaled, type: JSVAL, loc },
|
|
5693
|
+
],
|
|
5694
|
+
type: JSVAL,
|
|
5695
|
+
loc,
|
|
5696
|
+
};
|
|
5697
|
+
}
|
|
5698
|
+
catch (err) {
|
|
5699
|
+
// An entry outside every crossing domain: drop the boundary
|
|
5700
|
+
// diagnostics and let the shape fence below name the fix.
|
|
5701
|
+
if (!(err instanceof PoisonError))
|
|
5702
|
+
throw err;
|
|
5703
|
+
L.diags.splice(diagsBefore);
|
|
5704
|
+
}
|
|
5705
|
+
}
|
|
5599
5706
|
L.noLowering("Promise.all over this argument shape", argNode, "the entries must share ONE promise type — Promise.all([p, q]) lowers when p and q are the same Promise<T>");
|
|
5600
5707
|
}
|
|
5601
5708
|
const entries = L.lowerExpr(argNode);
|
|
5709
|
+
// A NON-literal island argument (`Promise.all(plugins.map((p) =>
|
|
5710
|
+
// loadPlugin(p)))` — the loadPlugins shape, where the checker
|
|
5711
|
+
// spells `any[]`): the ENGINE's own Promise.all runs over the
|
|
5712
|
+
// marshaled array (an 'any' value passes through; an `any[]` value
|
|
5713
|
+
// lifts per element by reference), the result staying an island
|
|
5714
|
+
// value the static side awaits through the island→static bridge.
|
|
5715
|
+
if (entries.type.kind === "jsval" ||
|
|
5716
|
+
(entries.type.kind === "array" && entries.type.elem.kind === "jsval")) {
|
|
5717
|
+
const diagsBefore = L.diags.length;
|
|
5718
|
+
try {
|
|
5719
|
+
const arg = L.jsvalIn(entries, argNode);
|
|
5720
|
+
return {
|
|
5721
|
+
kind: "jsOp",
|
|
5722
|
+
op: "callMethod",
|
|
5723
|
+
name: "all",
|
|
5724
|
+
args: [{ kind: "jsOp", op: "globalGet", name: "Promise", args: [], type: JSVAL, loc }, arg],
|
|
5725
|
+
type: JSVAL,
|
|
5726
|
+
loc,
|
|
5727
|
+
};
|
|
5728
|
+
}
|
|
5729
|
+
catch (err) {
|
|
5730
|
+
if (!(err instanceof PoisonError))
|
|
5731
|
+
throw err;
|
|
5732
|
+
L.diags.splice(diagsBefore);
|
|
5733
|
+
}
|
|
5734
|
+
}
|
|
5602
5735
|
if (entries.type.kind !== "array" || entries.type.elem.kind !== "promise") {
|
|
5603
5736
|
// The heterogeneous-literal case: the checker's tuple overload
|
|
5604
5737
|
// types the literal as a TUPLE of promises (a tuple-flagged record
|