@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
|
@@ -184,11 +184,11 @@ leading?: readonly IrExpr[]): IrExpr[];
|
|
|
184
184
|
* `type` has no undefined arm to wrap into. */
|
|
185
185
|
export declare function wrappedUndefined(L: Lowerer, type: IrType, loc: SrcLoc): IrExpr | null;
|
|
186
186
|
/** The synthesized argument for an omitted omittable param: the interned
|
|
187
|
-
* undefined arm of the param's `T | undefined` ABI union, or the
|
|
187
|
+
* undefined arm of the param's `T | undefined` ABI union, or the checked-dynamic tree
|
|
188
188
|
* undefined for a checked-dynamic param (`bar?: any`). */
|
|
189
189
|
/** The "absent argument" value for a param SLOT type, or null when the
|
|
190
190
|
* slot cannot hold one: the interned undefined arm for undefined-armed
|
|
191
|
-
* unions, the
|
|
191
|
+
* unions, the dyn undefined for checked-dynamic slots, the engine's own
|
|
192
192
|
* undefined for island slots. Shared by every call-completion loop
|
|
193
193
|
* (direct calls and calls through func-typed values). */
|
|
194
194
|
export declare function omittedArgFor(L: Lowerer, type: IrType, loc: SrcLoc): IrExpr | null;
|
|
@@ -382,7 +382,7 @@ export declare function lowerCall(L: Lowerer, expr: ts.CallExpression): IrExpr;
|
|
|
382
382
|
* - CHECKED-DYNAMIC (dyn spread sources — a JS rest binding, a dyn
|
|
383
383
|
* value): box the callee (dynFrom; a dyn callee is already boxed),
|
|
384
384
|
* convert every argument into dyn, and emit the spread-marked dynCall
|
|
385
|
-
* — the emitters build one fresh
|
|
385
|
+
* — the emitters build one fresh dyn argument array (spreads flatten
|
|
386
386
|
* left-to-right, non-iterables throw V8's TypeError) and apply through
|
|
387
387
|
* it; the boxed thunk delivers JS arity exactly. Result dyn, checked
|
|
388
388
|
* per use like every any-origin value.
|
|
@@ -404,7 +404,7 @@ export declare function lowerSpreadArgsCall(L: Lowerer, expr: ts.CallExpression,
|
|
|
404
404
|
* slots keep completeArgs' same-element spread packing. */
|
|
405
405
|
export declare function spreadNeedsRuntimeArity(shapes: readonly ParamShape[], argNodes: readonly ts.Expression[]): boolean;
|
|
406
406
|
/** The SHARED prototype names scr_dyn_invoke dispatches at runtime (the
|
|
407
|
-
* subset of
|
|
407
|
+
* subset of DYN_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
|
|
408
408
|
* runtime runs the real method for the receiver's kind, throws Node's
|
|
409
409
|
* is-not-a-function where the kind's prototype lacks the name, and
|
|
410
410
|
* fences LOUDLY on real-but-unimplemented pairs. */
|
|
@@ -85,7 +85,7 @@ export function paramShape(L, param) {
|
|
|
85
85
|
const raw = L.irTypeOf(param.name);
|
|
86
86
|
// A DYNAMIC-TIER pattern source (`function f({} = a)` with
|
|
87
87
|
// `a: any` — jsval for island values, dyn for the checked-dynamic
|
|
88
|
-
//
|
|
88
|
+
// dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
|
|
89
89
|
// is the slot itself — no synthesized union; the prologue tests
|
|
90
90
|
// undefined at runtime (declareParams).
|
|
91
91
|
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
@@ -103,7 +103,7 @@ export function paramShape(L, param) {
|
|
|
103
103
|
}
|
|
104
104
|
if (param.dotDotDotToken) {
|
|
105
105
|
// A JS rest param with no static element type (`(...args)` — any[]):
|
|
106
|
-
// the VARIADIC dyn form. The lifted function takes one trailing
|
|
106
|
+
// the VARIADIC dyn form. The lifted function takes one trailing dyn
|
|
107
107
|
// ARRAY param the dyn call thunk fills with the call's surplus
|
|
108
108
|
// arguments; the binding is that array (dynRest — funcType marks
|
|
109
109
|
// `rest`, and the value only ever calls through the boxed thunk).
|
|
@@ -133,7 +133,7 @@ export function paramShape(L, param) {
|
|
|
133
133
|
const raw = L.irTypeOf(param.name);
|
|
134
134
|
// A DYNAMIC-TIER defaulted param (`function f(x = a)` with `a: any`
|
|
135
135
|
// — tsc types x any; jsval for island values, dyn for the checked-
|
|
136
|
-
// dynamic
|
|
136
|
+
// dynamic dyn): the slot holds its tier's undefined directly, so
|
|
137
137
|
// the ABI is the slot itself and the prologue's default test is the
|
|
138
138
|
// runtime undefined test (declareParams).
|
|
139
139
|
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
@@ -169,7 +169,7 @@ export function paramShape(L, param) {
|
|
|
169
169
|
if (param.questionToken && !L.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
|
|
170
170
|
// `x?: unknown` where unknown came from an annotation: undefined is
|
|
171
171
|
// absorbed into the hole type, so no undefined ARM exists — but a
|
|
172
|
-
// checked-dynamic slot holds the
|
|
172
|
+
// checked-dynamic slot holds the dyn undefined directly (`bar?: any`
|
|
173
173
|
// — an omitted call passes it, undefinedArgFor), and an island slot
|
|
174
174
|
// the engine's own undefined likewise (`options?: [string?]` — an
|
|
175
175
|
// optional-tuple param, jsval-mapped), so dyn and jsval params stay
|
|
@@ -243,7 +243,7 @@ leading) {
|
|
|
243
243
|
// A missing argument for a CHECKED-DYNAMIC param (an implicit-any
|
|
244
244
|
// JS signature called short — `mustCall(fn)` with `expected`
|
|
245
245
|
// omitted): JS fills undefined, and the dyn slot holds exactly
|
|
246
|
-
// that — the undefined
|
|
246
|
+
// that — the undefined dyn value. tsc's arity families don't gate
|
|
247
247
|
// .js builds (SEMANTICS.md 116), so the completion lands here.
|
|
248
248
|
if (shape.type.kind === "dyn") {
|
|
249
249
|
return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
|
|
@@ -271,7 +271,7 @@ leading) {
|
|
|
271
271
|
else if (restAt >= 0 && shapes[restAt].mode === "dynRest") {
|
|
272
272
|
// The VARIADIC dyn pack (a JS `...args` with no static element
|
|
273
273
|
// type, or the synthetic `arguments` slot): surplus arguments
|
|
274
|
-
// convert through the dyn boundary into one fresh
|
|
274
|
+
// convert through the dyn boundary into one fresh dyn array —
|
|
275
275
|
// exactly what the boxed call thunk builds for indirect calls.
|
|
276
276
|
const elems = sources.slice(restAt).map((a) => {
|
|
277
277
|
if (isIr(a))
|
|
@@ -384,11 +384,11 @@ export function wrappedUndefined(L, type, loc) {
|
|
|
384
384
|
return wrapped.kind === "unionWrap" ? wrapped : null;
|
|
385
385
|
}
|
|
386
386
|
/** The synthesized argument for an omitted omittable param: the interned
|
|
387
|
-
* undefined arm of the param's `T | undefined` ABI union, or the
|
|
387
|
+
* undefined arm of the param's `T | undefined` ABI union, or the checked-dynamic tree
|
|
388
388
|
* undefined for a checked-dynamic param (`bar?: any`). */
|
|
389
389
|
/** The "absent argument" value for a param SLOT type, or null when the
|
|
390
390
|
* slot cannot hold one: the interned undefined arm for undefined-armed
|
|
391
|
-
* unions, the
|
|
391
|
+
* unions, the dyn undefined for checked-dynamic slots, the engine's own
|
|
392
392
|
* undefined for island slots. Shared by every call-completion loop
|
|
393
393
|
* (direct calls and calls through func-typed values). */
|
|
394
394
|
export function omittedArgFor(L, type, loc) {
|
|
@@ -529,7 +529,7 @@ export function appendImplicitUndefinedReturn(L, body, bodyReturn, loc) {
|
|
|
529
529
|
// A DYN body that can complete without returning (a JS function whose
|
|
530
530
|
// guarded return may not run — mustSucceed's `if (typeof fn ===
|
|
531
531
|
// 'function') return fn.apply(...)`): JS completes with undefined —
|
|
532
|
-
// the undefined
|
|
532
|
+
// the undefined dyn value.
|
|
533
533
|
if (bodyReturn.kind === "dyn") {
|
|
534
534
|
body.push({
|
|
535
535
|
kind: "return",
|
|
@@ -584,7 +584,7 @@ export function declaredReturnType(L, decl, blame) {
|
|
|
584
584
|
// The RECORD twin (the tracing suite's traced closures — `function ()
|
|
585
585
|
// { return expectedResult; }` infers `{ foo: string }`): JS object
|
|
586
586
|
// literals are checked-dynamic VALUES, so a record-typed return would
|
|
587
|
-
// copy the
|
|
587
|
+
// copy the dyn value into a struct at the return and copy it back out
|
|
588
588
|
// at any dyn boundary — identity lost twice (found.result !==
|
|
589
589
|
// expectedResult where Node passes the object through). The inferred
|
|
590
590
|
// shape is inference, not a contract: the return stays checked-
|
|
@@ -1332,7 +1332,7 @@ function resolveInferredReturn(L, inst, infer, body, decl) {
|
|
|
1332
1332
|
distinct.push(e.stmt.value.type);
|
|
1333
1333
|
}
|
|
1334
1334
|
if (distinct.length === 0) {
|
|
1335
|
-
final = DYN; // no valued return: JS completes with undefined — the
|
|
1335
|
+
final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
|
|
1336
1336
|
}
|
|
1337
1337
|
else if (distinct.length === 1) {
|
|
1338
1338
|
const t = distinct[0];
|
|
@@ -1459,7 +1459,7 @@ export function lowerGenericFnValue(L, ref, info) {
|
|
|
1459
1459
|
const inst = genericValueInstance(L, ref, info, bindings);
|
|
1460
1460
|
// The value's type is the completed ABI signature — exact-arity, the
|
|
1461
1461
|
// declared-function value rule (dynRest slots stay out of the param
|
|
1462
|
-
// list; the rest marker carries the trailing
|
|
1462
|
+
// list; the rest marker carries the trailing dyn-array ABI).
|
|
1463
1463
|
const funcType = {
|
|
1464
1464
|
kind: "func",
|
|
1465
1465
|
params: inst.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
|
|
@@ -2442,7 +2442,7 @@ export function lowerCall(L, expr) {
|
|
|
2442
2442
|
// non-format argument: strings VERBATIM, everything else through
|
|
2443
2443
|
// inspect at the rest-args depth 2 (formatWithOptions) — scalar
|
|
2444
2444
|
// kinds byte-exactly, boxed functions as [Function: name] /
|
|
2445
|
-
// [Function (anonymous)], composites through the dyn
|
|
2445
|
+
// [Function (anonymous)], composites through the dyn walk
|
|
2446
2446
|
// (insp.dyn). Never throws — Node's console.log never does.
|
|
2447
2447
|
if (lowered.type.kind === "dyn") {
|
|
2448
2448
|
return {
|
|
@@ -2551,10 +2551,10 @@ export function lowerCall(L, expr) {
|
|
|
2551
2551
|
}
|
|
2552
2552
|
return { kind: "libCall", fn: "timers.queueMicrotask", args: [adapted], type: VOID, loc };
|
|
2553
2553
|
}
|
|
2554
|
-
// structuredClone: the JSON-safe + bytes subset over the
|
|
2554
|
+
// structuredClone: the JSON-safe + bytes subset over the checked-dynamic tree, deep;
|
|
2555
2555
|
// %DOMException clones through WebIDL serialization (name/message,
|
|
2556
2556
|
// the code re-derives). Functions/handles throw the spec's catchable
|
|
2557
|
-
// DataCloneError; cycles fence (the
|
|
2557
|
+
// DataCloneError; cycles fence (the checked-dynamic tree cannot represent them — Node
|
|
2558
2558
|
// clones cycles, a documented divergence). Option validation throws
|
|
2559
2559
|
// Node's exact errors; the zero-argument call Node's
|
|
2560
2560
|
// ERR_MISSING_ARGS. Provenance-checked like setTimeout.
|
|
@@ -2580,7 +2580,7 @@ export function lowerCall(L, expr) {
|
|
|
2580
2580
|
const valueNode = expr.arguments[0];
|
|
2581
2581
|
// A NON-EMPTY transfer array of static values: nothing static is
|
|
2582
2582
|
// transferable, so the call is Node's DataCloneError — decided here
|
|
2583
|
-
// (the list's values need no
|
|
2583
|
+
// (the list's values need no dyn representation to fail). An EMPTY
|
|
2584
2584
|
// literal transfer list is a no-op member and drops.
|
|
2585
2585
|
{
|
|
2586
2586
|
let optNode = expr.arguments[1];
|
|
@@ -2611,8 +2611,8 @@ export function lowerCall(L, expr) {
|
|
|
2611
2611
|
const value = toDynArg(valueNode);
|
|
2612
2612
|
const cloned = { kind: "libCall", fn: "dyn.structuredClone", args: [value, optsArg], type: DYN, loc };
|
|
2613
2613
|
// The declared result is the value's own type (the generic's T):
|
|
2614
|
-
// validate the
|
|
2615
|
-
// dyn-typed and unmappable results stay
|
|
2614
|
+
// validate the dyn copy back into it when the type can be checked;
|
|
2615
|
+
// dyn-typed and unmappable results stay dyn values (JS files).
|
|
2616
2616
|
const resultT = L.mapTypeOf(L.typeOf(expr));
|
|
2617
2617
|
if (resultT !== null && resultT.kind !== "dyn" && resultT.kind !== "void" &&
|
|
2618
2618
|
canDynCheckTo(resultT, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
|
|
@@ -2718,7 +2718,7 @@ export function lowerCall(L, expr) {
|
|
|
2718
2718
|
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
2719
2719
|
L.isIslandExpr(expr.expression.expression)) {
|
|
2720
2720
|
const receiver = L.lowerExpr(expr.expression.expression);
|
|
2721
|
-
// A checker-`any` receiver whose VALUE lives in the
|
|
2721
|
+
// A checker-`any` receiver whose VALUE lives in the checked-dynamic tree (a
|
|
2722
2722
|
// checked-dynamic local behind the any-typed spelling — the JS
|
|
2723
2723
|
// WeakSet placeholder, rest-args arrays): the checked-dynamic
|
|
2724
2724
|
// method machinery owns it — receiver-kind dispatch, stored-member
|
|
@@ -2765,7 +2765,7 @@ export function lowerCall(L, expr) {
|
|
|
2765
2765
|
}
|
|
2766
2766
|
const callee = L.lowerExpr(expr.expression);
|
|
2767
2767
|
// A checker-`any` callee that LOWERED checked-dynamic (a dyn member
|
|
2768
|
-
// chain's stored function): the
|
|
2768
|
+
// chain's stored function): the checked-dynamic tree's own call — dynCall reads and
|
|
2769
2769
|
// calls the stored member with Node's is-not-a-function TypeError
|
|
2770
2770
|
// on refusal.
|
|
2771
2771
|
if (callee.type.kind === "dyn") {
|
|
@@ -2890,6 +2890,11 @@ export function lowerCall(L, expr) {
|
|
|
2890
2890
|
const fsLadder = L.lowerFsLadderCall(expr, bi, loc);
|
|
2891
2891
|
if (fsLadder)
|
|
2892
2892
|
return fsLadder;
|
|
2893
|
+
// The crypto introspection statics (getFips and the name lists)
|
|
2894
|
+
// bake at the call site — no runtime entry exists to table.
|
|
2895
|
+
const cryptoServed = L.lowerCryptoModuleCall(expr, bi, loc);
|
|
2896
|
+
if (cryptoServed)
|
|
2897
|
+
return cryptoServed;
|
|
2893
2898
|
const builtinFn = builtinModuleFnOf(L, bi.module, bi.member);
|
|
2894
2899
|
if (!builtinFn) {
|
|
2895
2900
|
// Typed by @types/node (the fallback declarations only declare
|
|
@@ -3031,7 +3036,7 @@ export function lowerCall(L, expr) {
|
|
|
3031
3036
|
}
|
|
3032
3037
|
// STATIC atob/btoa (str.atob / str.btoa — scr_string.c; WHATWG
|
|
3033
3038
|
// forgiving-base64, Node is the oracle). The argument crosses as a
|
|
3034
|
-
//
|
|
3039
|
+
// dyn value: WebIDL ToString runs in the runtime over the dyn kind
|
|
3035
3040
|
// (Node's atob(null) decodes "null"), a malformed input throws the
|
|
3036
3041
|
// catchable DOMException InvalidCharacterError, and the
|
|
3037
3042
|
// zero-argument call throws Node's TypeError [ERR_MISSING_ARGS].
|
|
@@ -3524,7 +3529,7 @@ export function lowerCall(L, expr) {
|
|
|
3524
3529
|
if (callee.type.kind === "dyn") {
|
|
3525
3530
|
if (expr.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
3526
3531
|
// The runtime-arity lane: a dyn callee is already boxed — the
|
|
3527
|
-
// spread-marked dynCall applies through a fresh
|
|
3532
|
+
// spread-marked dynCall applies through a fresh dyn argument
|
|
3528
3533
|
// array (lowerSpreadArgsCall). Sources outside it keep the fence.
|
|
3529
3534
|
const spreadServed = lowerSpreadArgsCall(L, expr, callee, loc);
|
|
3530
3535
|
if (spreadServed)
|
|
@@ -3604,7 +3609,7 @@ export function lowerCall(L, expr) {
|
|
|
3604
3609
|
// skip — not a shape this surface models; fence.
|
|
3605
3610
|
for (let i = args.length; i < params.length; i++) {
|
|
3606
3611
|
// A missing argument completes with the slot's absent value — the
|
|
3607
|
-
// interned undefined arm, the
|
|
3612
|
+
// interned undefined arm, the dyn undefined for checked-dynamic
|
|
3608
3613
|
// slots (a JS-inferred wrapper like mustCall's, called short), or
|
|
3609
3614
|
// the engine undefined for island slots.
|
|
3610
3615
|
const absent = omittedArgFor(L, params[i], loc);
|
|
@@ -3624,7 +3629,7 @@ export function lowerCall(L, expr) {
|
|
|
3624
3629
|
* - CHECKED-DYNAMIC (dyn spread sources — a JS rest binding, a dyn
|
|
3625
3630
|
* value): box the callee (dynFrom; a dyn callee is already boxed),
|
|
3626
3631
|
* convert every argument into dyn, and emit the spread-marked dynCall
|
|
3627
|
-
* — the emitters build one fresh
|
|
3632
|
+
* — the emitters build one fresh dyn argument array (spreads flatten
|
|
3628
3633
|
* left-to-right, non-iterables throw V8's TypeError) and apply through
|
|
3629
3634
|
* it; the boxed thunk delivers JS arity exactly. Result dyn, checked
|
|
3630
3635
|
* per use like every any-origin value.
|
|
@@ -3712,7 +3717,7 @@ export function spreadNeedsRuntimeArity(shapes, argNodes) {
|
|
|
3712
3717
|
}
|
|
3713
3718
|
/** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
|
|
3714
3719
|
* `ws.packages.filter(...)` — JSON.parse-derived values): validate the
|
|
3715
|
-
* receiver's
|
|
3720
|
+
* receiver's dyn kind, extract, and ride the STATIC method machinery — the
|
|
3716
3721
|
* dyn boundary's trust-but-verify stance extended to receivers. The
|
|
3717
3722
|
* receiver-kind mismatch throws V8's own catchable TypeErrors (nullish:
|
|
3718
3723
|
* "Cannot read properties of undefined (reading 'replace')"; other kinds:
|
|
@@ -3720,14 +3725,14 @@ export function spreadNeedsRuntimeArity(shapes, argNodes) {
|
|
|
3720
3725
|
* evaluate, where JS evaluates them first for the non-nullish case
|
|
3721
3726
|
* (SEMANTICS.md). String methods ride the string/regex intrinsic tables
|
|
3722
3727
|
* through a validated-string receiver; `.filter` runs the predicate over
|
|
3723
|
-
* the
|
|
3728
|
+
* the dyn array and validated-extracts the survivors into the element type
|
|
3724
3729
|
* the checker committed the result to. Null when the receiver isn't a dyn
|
|
3725
3730
|
* value or the method isn't claimable (the method-call fence stays). */
|
|
3726
3731
|
function lowerDynReceiverMethodCall(L, call, access) {
|
|
3727
3732
|
if (L.chainBlocked(call, access))
|
|
3728
3733
|
return null;
|
|
3729
3734
|
// Only checker-untyped receivers: `any`/`unknown`, or the `any[]` an
|
|
3730
|
-
// Array.isArray guard narrows them to (the value is STILL the
|
|
3735
|
+
// Array.isArray guard narrows them to (the value is STILL the checked-dynamic tree
|
|
3731
3736
|
// array — scalar narrowings bridge through maybeNarrow's dynCheck and
|
|
3732
3737
|
// take the ordinary typed paths, but there is no static home for an
|
|
3733
3738
|
// any-elemented array). Typed receivers keep their own lowerings.
|
|
@@ -3759,7 +3764,7 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
3759
3764
|
return null;
|
|
3760
3765
|
// Typed-destination filter first (validated extraction into a real
|
|
3761
3766
|
// T[]); an untyped destination falls through to the runtime dispatch
|
|
3762
|
-
// below (the survivors stay
|
|
3767
|
+
// below (the survivors stay dyn values).
|
|
3763
3768
|
if (access.name.text === "filter") {
|
|
3764
3769
|
const extracted = lowerDynArrayFilterCall(L, call, access, recv);
|
|
3765
3770
|
if (extracted)
|
|
@@ -3767,10 +3772,10 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
3767
3772
|
}
|
|
3768
3773
|
if (access.name.text === "flatMap")
|
|
3769
3774
|
return lowerDynArrayFlatMapCall(L, call, access, recv);
|
|
3770
|
-
// String methods claim only names NO other
|
|
3775
|
+
// String methods claim only names NO other dyn-representable kind's
|
|
3771
3776
|
// prototype declares (Array carries includes/indexOf/slice too): for
|
|
3772
3777
|
// these, "the receiver is a string, or the call throws V8's TypeError"
|
|
3773
|
-
// IS Node's semantics for every possible
|
|
3778
|
+
// IS Node's semantics for every possible dyn value. Shared names would
|
|
3774
3779
|
// need a receiver-kind dispatch — they keep the fence.
|
|
3775
3780
|
if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
|
|
3776
3781
|
const checked = () => dynStringReceiver(L, recv, access);
|
|
@@ -3804,7 +3809,7 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
3804
3809
|
}
|
|
3805
3810
|
// SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
|
|
3806
3811
|
// push/slice/join/forEach/map/apply/... dispatch on the receiver's
|
|
3807
|
-
// RUNTIME kind — the honest answer for names more than one
|
|
3812
|
+
// RUNTIME kind — the honest answer for names more than one dyn-
|
|
3808
3813
|
// representable prototype declares (test/common's mustCall internals:
|
|
3809
3814
|
// mustCallChecks.push(context), failed.forEach(fn), fn.apply(this,
|
|
3810
3815
|
// args)). Implemented (kind, name) pairs run JS-exact; real-but-
|
|
@@ -3826,18 +3831,18 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
3826
3831
|
loc: locOf(call),
|
|
3827
3832
|
};
|
|
3828
3833
|
}
|
|
3829
|
-
// Names NO
|
|
3834
|
+
// Names NO dyn-representable prototype declares: the member can only
|
|
3830
3835
|
// be an OWN property, so "read the member, call it" IS Node's
|
|
3831
|
-
// semantics for every possible
|
|
3836
|
+
// semantics for every possible dyn value — `handlers.onDone(x)` on a
|
|
3832
3837
|
// checked-dynamic object calls the stored function (dynKeyGet answers
|
|
3833
3838
|
// the member or undefined; dynCall throws Node's exact catchable
|
|
3834
3839
|
// "handlers.onDone is not a function" on a non-function). Prototype
|
|
3835
3840
|
// names (map/join/hasOwnProperty/call/...) keep the fence: on a real
|
|
3836
|
-
//
|
|
3841
|
+
// dyn array/string/object Node would run the METHOD, which no stored
|
|
3837
3842
|
// member models. Order note: JS reads the callee before evaluating
|
|
3838
3843
|
// arguments — dynKeyGet's undefined-receiver TypeError fires first,
|
|
3839
3844
|
// exactly Node.
|
|
3840
|
-
if (
|
|
3845
|
+
if (DYN_PROTO_METHOD_NAMES.has(access.name.text))
|
|
3841
3846
|
return null;
|
|
3842
3847
|
// Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
|
|
3843
3848
|
// machinery's short-circuit semantics — not modeled here yet.
|
|
@@ -3857,12 +3862,12 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
3857
3862
|
const args = call.arguments.map((a) => L.lowerExprExpecting(a, DYN));
|
|
3858
3863
|
return { kind: "dynCall", callee: member, calleeName: access.getText(), args, type: DYN, loc };
|
|
3859
3864
|
}
|
|
3860
|
-
/** Prototype method names of the
|
|
3865
|
+
/** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
|
|
3861
3866
|
* Object, Function, Number prototypes): a dyn receiver call on one of
|
|
3862
3867
|
* these could be a REAL method on a real value, which a stored-member
|
|
3863
3868
|
* read would silently mis-answer — they keep the fence. Everything else
|
|
3864
|
-
* is own-property-or-throw for every
|
|
3865
|
-
const
|
|
3869
|
+
* is own-property-or-throw for every dyn value (the honest dynCall). */
|
|
3870
|
+
const DYN_PROTO_METHOD_NAMES = new Set([
|
|
3866
3871
|
// Object.prototype
|
|
3867
3872
|
"hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf",
|
|
3868
3873
|
// Function.prototype
|
|
@@ -3877,7 +3882,7 @@ const DOM_PROTO_METHOD_NAMES = new Set([
|
|
|
3877
3882
|
"toExponential", "toFixed", "toPrecision",
|
|
3878
3883
|
]);
|
|
3879
3884
|
/** The SHARED prototype names scr_dyn_invoke dispatches at runtime (the
|
|
3880
|
-
* subset of
|
|
3885
|
+
* subset of DYN_PROTO_METHOD_NAMES with a receiver-kind dispatch): the
|
|
3881
3886
|
* runtime runs the real method for the receiver's kind, throws Node's
|
|
3882
3887
|
* is-not-a-function where the kind's prototype lacks the name, and
|
|
3883
3888
|
* fences LOUDLY on real-but-unimplemented pairs. */
|
|
@@ -3891,7 +3896,7 @@ export const DYN_DISPATCH_METHODS = new Set([
|
|
|
3891
3896
|
// the runtime kind so a boxed IncomingMessage/ServerResponse/Socket
|
|
3892
3897
|
// routes onto the same entry points the static lowerings use (modeled
|
|
3893
3898
|
// members) or the loud not-supported ladder (real-but-unmodeled ones).
|
|
3894
|
-
// On every other
|
|
3899
|
+
// On every other dyn kind they answer exactly what the stored-member
|
|
3895
3900
|
// path answered (OBJ own members call; the rest throw Node's
|
|
3896
3901
|
// is-not-a-function).
|
|
3897
3902
|
"on", "once", "addListener", "removeListener", "off", "removeAllListeners",
|
|
@@ -3903,14 +3908,17 @@ export const DYN_DISPATCH_METHODS = new Set([
|
|
|
3903
3908
|
"writeContinue", "writeEarlyHints", "cork", "uncork", "addTrailers",
|
|
3904
3909
|
"ref", "unref", "address", "setNoDelay", "setKeepAlive", "connect",
|
|
3905
3910
|
"resetAndDestroy", "destroySoon",
|
|
3911
|
+
// The Agent handle's own member (no other dyn prototype declares it,
|
|
3912
|
+
// so the remainder keeps the stored-member answers).
|
|
3913
|
+
"getName",
|
|
3906
3914
|
// The netServer half of the handle surface (`let server; server =
|
|
3907
3915
|
// createServer(...)` — the handle lives in a dyn binding whose
|
|
3908
3916
|
// closures the checker cannot narrow): listen/close dispatch onto the
|
|
3909
|
-
// server ops; no other
|
|
3917
|
+
// server ops; no other dyn prototype declares either name, so the
|
|
3910
3918
|
// remainder keeps the stored-member answers.
|
|
3911
3919
|
"listen", "close",
|
|
3912
3920
|
// Promise.prototype (SCR_DYN_PROMISE receivers): the reaction trio
|
|
3913
|
-
// rides the fiber machinery (scr_dyn_promise_then); on every other
|
|
3921
|
+
// rides the fiber machinery (scr_dyn_promise_then); on every other dyn
|
|
3914
3922
|
// kind then/catch/finally answer the stored-member path (OBJ own
|
|
3915
3923
|
// members call, the rest throw Node's is-not-a-function).
|
|
3916
3924
|
"then", "catch", "finally",
|
|
@@ -3924,15 +3932,15 @@ export const DYN_DISPATCH_METHODS = new Set([
|
|
|
3924
3932
|
"additionalHeaders", "altsvc", "origin",
|
|
3925
3933
|
]);
|
|
3926
3934
|
/** STR_METHODS ∪ the regex-form names, MINUS everything Array (or any
|
|
3927
|
-
* other
|
|
3935
|
+
* other dyn kind's prototype) also declares. */
|
|
3928
3936
|
const DYN_STRING_ONLY_METHODS = new Set([
|
|
3929
3937
|
"charCodeAt", "charAt", "startsWith", "endsWith", "substring", "repeat",
|
|
3930
3938
|
"trim", "trimStart", "trimEnd", "split", "padStart", "padEnd",
|
|
3931
3939
|
"toLowerCase", "toUpperCase", "replace", "replaceAll", "match", "matchAll",
|
|
3932
3940
|
"search",
|
|
3933
3941
|
]);
|
|
3934
|
-
/** `Array.isArray(v)` — a real runtime test on `unknown` values (the
|
|
3935
|
-
* array kind:
|
|
3942
|
+
/** `Array.isArray(v)` — a real runtime test on `unknown` values (the checked-dynamic tree's
|
|
3943
|
+
* array kind: dyn arrays answer true, bytes/objects/scalars false — exactly
|
|
3936
3944
|
* JS, Uint8Array included), a compile-time constant on statically-typed
|
|
3937
3945
|
* ones (an `T[]` value IS an array, every other static kind is not; folded
|
|
3938
3946
|
* only over side-effect-free reads, the `in`-operator discipline; unions
|
|
@@ -4667,7 +4675,7 @@ export function lambdaSignature(L, node) {
|
|
|
4667
4675
|
// VARIADIC JS functions: a dynRest param (above), or a plain function
|
|
4668
4676
|
// whose body reads `arguments` (test/common's mustCall wrapper —
|
|
4669
4677
|
// `function() { ...; return fn.apply(this, arguments); }`). Both mark
|
|
4670
|
-
// the func type `rest`: the lifted body takes one trailing
|
|
4678
|
+
// the func type `rest`: the lifted body takes one trailing dyn-array
|
|
4671
4679
|
// param, filled by the boxed call thunk with the call's arguments
|
|
4672
4680
|
// from index params.length on. `arguments` is only claimed in
|
|
4673
4681
|
// ZERO-param functions (there it IS the surplus array); alongside
|
|
@@ -4687,7 +4695,7 @@ export function lambdaSignature(L, node) {
|
|
|
4687
4695
|
shapes,
|
|
4688
4696
|
funcType: {
|
|
4689
4697
|
kind: "func",
|
|
4690
|
-
// dynRest is EXCLUDED (the boxed thunk fills the trailing
|
|
4698
|
+
// dynRest is EXCLUDED (the boxed thunk fills the trailing dyn
|
|
4691
4699
|
// array — no spelled slot); islandRest is INCLUDED (the trailing
|
|
4692
4700
|
// jsval param IS the engine arguments array, the REST host-call
|
|
4693
4701
|
// adapter's one uniform shape).
|
|
@@ -4770,7 +4778,7 @@ export function lowerLambda(L, node) {
|
|
|
4770
4778
|
try {
|
|
4771
4779
|
const { params, prologue } = L.declareParams(node.parameters, shapes);
|
|
4772
4780
|
// The VARIADIC `arguments` form (rest-marked with no declared rest
|
|
4773
|
-
// param): a synthetic trailing
|
|
4781
|
+
// param): a synthetic trailing dyn-array param carries the call's
|
|
4774
4782
|
// arguments; `arguments` reads resolve to it (identifier lowering).
|
|
4775
4783
|
if (funcType.rest && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
|
|
4776
4784
|
const argsLocal = L.declareHiddenLocal("%arguments", DYN);
|
|
@@ -4875,7 +4883,7 @@ export function lowerLambda(L, node) {
|
|
|
4875
4883
|
const first = captured[0];
|
|
4876
4884
|
const pos = ts.getLineAndCharacterOfPosition(L.program.getSourceFile(first.loc.file) ?? node.getSourceFile(), first.loc.start);
|
|
4877
4885
|
const params = funcType.params.map((t, i) => ({ localId: `%pf${i}`, name: `%pf${i}`, type: t }));
|
|
4878
|
-
// A REST-MARKED value type hides one synthetic trailing
|
|
4886
|
+
// A REST-MARKED value type hides one synthetic trailing dyn-array
|
|
4879
4887
|
// param in the lifted function (the boxed call thunk fills it) —
|
|
4880
4888
|
// the fence lambda must spell that slot too or the validator's
|
|
4881
4889
|
// closure-signature check trips (SC9001). Island rest types SPELL
|
|
@@ -5102,7 +5110,7 @@ export function lowerPromiseMethodCall(L, call, access) {
|
|
|
5102
5110
|
// A TYPED handler on a DYN-settling promise (the tracePromise
|
|
5103
5111
|
// result's `.then((value) => ...)` — the checker's generic
|
|
5104
5112
|
// instantiation typed the parameter, but the settled value is a
|
|
5105
|
-
//
|
|
5113
|
+
// dyn value): box the handler and ride the dyn-handler desugar
|
|
5106
5114
|
// below — its call thunk validates the settled value into the
|
|
5107
5115
|
// declared parameter type (the per-arg dynCheck), Node's own
|
|
5108
5116
|
// runtime contract for a value that came off the wire untyped.
|
|
@@ -5114,10 +5122,10 @@ export function lowerPromiseMethodCall(L, call, access) {
|
|
|
5114
5122
|
}
|
|
5115
5123
|
// A CHECKED-DYNAMIC handler VALUE (`p.then(common.mustCall())` — the
|
|
5116
5124
|
// Node-suite wrapper is an untyped rest-args function): the same
|
|
5117
|
-
// async desugar with the handler called through the
|
|
5125
|
+
// async desugar with the handler called through the checked-dynamic tree — the
|
|
5118
5126
|
// settled value boxes (dyn passes through; void arrives as JS's
|
|
5119
5127
|
// explicit undefined argument), the result promise settles with the
|
|
5120
|
-
// handler's
|
|
5128
|
+
// handler's dyn result. A receiver rejection passes through the
|
|
5121
5129
|
// await like the typed path; the dyn call's own argument checking
|
|
5122
5130
|
// throws Node's TypeError for non-callables.
|
|
5123
5131
|
if (cb.type.kind === "dyn") {
|
|
@@ -5127,7 +5135,7 @@ export function lowerPromiseMethodCall(L, call, access) {
|
|
|
5127
5135
|
if (canConvertToDyn(v.type, (id) => L.shapes.get(id), (id) => L.unions.get(id))) {
|
|
5128
5136
|
return { kind: "dynFrom", value: v, type: DYN, loc };
|
|
5129
5137
|
}
|
|
5130
|
-
L.unsupported("SC1090", call.arguments[0], `then handlers receiving '${L.fmt(v.type)}' values through an untyped handler (the settled value cannot cross the
|
|
5138
|
+
L.unsupported("SC1090", call.arguments[0], `then handlers receiving '${L.fmt(v.type)}' values through an untyped handler (the settled value cannot cross the checked-dynamic tree boundary)`);
|
|
5131
5139
|
};
|
|
5132
5140
|
const resultT = { kind: "promise", inner: DYN };
|
|
5133
5141
|
const fnName = `%fn${L.lambdaCounter++}_then`;
|
|
@@ -5353,8 +5361,8 @@ export function lowerPromiseMethodCall(L, call, access) {
|
|
|
5353
5361
|
}
|
|
5354
5362
|
}
|
|
5355
5363
|
// .catch on a DYN-SETTLING promise (the tracePromise result's
|
|
5356
|
-
// `.catch((e) => ...)`): the rejection reason is a
|
|
5357
|
-
// handler runs through the
|
|
5364
|
+
// `.catch((e) => ...)`): the rejection reason is a dyn value, so the
|
|
5365
|
+
// handler runs through the checked-dynamic tree — a lifted async helper awaits the
|
|
5358
5366
|
// receiver, passes fulfillments through as dyn, and on rejection
|
|
5359
5367
|
// calls the boxed handler with caughtToDyn's identity-preserving
|
|
5360
5368
|
// snapshot (the dyn-then desugar's catch twin).
|
|
@@ -5540,7 +5548,7 @@ export function lowerPromiseMethodCall(L, call, access) {
|
|
|
5540
5548
|
else if (R.kind === "dyn") {
|
|
5541
5549
|
// A checked-dynamic result (the dyn-handler .then's promise-of-dyn
|
|
5542
5550
|
// chained into .catch): falling off the handler's end resolves
|
|
5543
|
-
// with the
|
|
5551
|
+
// with the dyn undefined.
|
|
5544
5552
|
catchBody.push({ kind: "return", value: dynUndefinedExpr(loc), loc });
|
|
5545
5553
|
}
|
|
5546
5554
|
else if (R.kind === "jsval") {
|
|
@@ -6272,7 +6280,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6272
6280
|
// REAL prototype semantics: reads delegate LIVE, writes shadow,
|
|
6273
6281
|
// and inspect renders Node's exact shapes ("[Object: null
|
|
6274
6282
|
// prototype]" included). null and engine-held (jsval) prototypes
|
|
6275
|
-
// route; checked-dynamic (
|
|
6283
|
+
// route; checked-dynamic (dyn) prototypes keep the named fence —
|
|
6276
6284
|
// their marshal into the engine is a DEEP COPY, so a later
|
|
6277
6285
|
// prototype mutation would be invisible through the created
|
|
6278
6286
|
// object where Node delegates live.
|
|
@@ -6337,7 +6345,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6337
6345
|
const tProbe = probeLower(L, call.arguments[0]);
|
|
6338
6346
|
const sProbe = probeLower(L, call.arguments[1]);
|
|
6339
6347
|
// CHECKED-DYNAMIC target and source (the JS file-scope
|
|
6340
|
-
// object-literal identity story): the runtime
|
|
6348
|
+
// object-literal identity story): the runtime dyn copy — own
|
|
6341
6349
|
// members of the source land on the target, which returns.
|
|
6342
6350
|
if (tProbe?.type.kind === "dyn") {
|
|
6343
6351
|
const loc = locOf(call);
|
|
@@ -6372,7 +6380,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6372
6380
|
// `Object.assign(target, ...sources)` over a CHECKED-DYNAMIC target
|
|
6373
6381
|
// — the n-ary/spread form (`Object.assign({}, ...plugins.map(p =>
|
|
6374
6382
|
// p.options), coreOptions)`, support.js's option-table merge). The
|
|
6375
|
-
// sources pack into one fresh
|
|
6383
|
+
// sources pack into one fresh dyn array FIRST — plain sources
|
|
6376
6384
|
// retain in, spread sources flatten through the spread-call walk
|
|
6377
6385
|
// (V8's exact TypeError texts, the source spelling carried for the
|
|
6378
6386
|
// nullish form) — so every source evaluates and flattens before any
|
|
@@ -6384,7 +6392,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6384
6392
|
// spread copies in at the boundary, the documented aliasing
|
|
6385
6393
|
// stance); anything else keeps the fence. Targets: dyn values, a
|
|
6386
6394
|
// FRESH object-literal target (`Object.assign({}, ...)` — no alias
|
|
6387
|
-
// exists, so building it as a
|
|
6395
|
+
// exists, so building it as a dyn object instead of a record is
|
|
6388
6396
|
// unobservable), or a nullish unit (Node's ToObject TypeError
|
|
6389
6397
|
// throws at the call, catchably); aliased record targets keep the
|
|
6390
6398
|
// fence — their identity could not survive the conversion.
|
|
@@ -6459,7 +6467,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6459
6467
|
// Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
|
|
6460
6468
|
// _mustCallInner copying name/length onto the mustCall wrapper): the
|
|
6461
6469
|
// runtime turns each descriptor's `value` into a plain own property on
|
|
6462
|
-
// the
|
|
6470
|
+
// the dyn node (OBJ members; FUNC nodes carry an own-property table) —
|
|
6463
6471
|
// flags accepted and ignored, accessors throw loudly (SEMANTICS.md).
|
|
6464
6472
|
// The result is the target, like JS. Typed targets keep the fence:
|
|
6465
6473
|
// static shapes have no property table to extend.
|
|
@@ -6522,7 +6530,7 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6522
6530
|
const keyNode = call.arguments[1];
|
|
6523
6531
|
const probed = probeLower(L, recvNode);
|
|
6524
6532
|
// A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
|
|
6525
|
-
// identity story): the runtime
|
|
6533
|
+
// identity story): the runtime dyn probe — OBJ member presence, ARR
|
|
6526
6534
|
// index bounds, Node's ToObject TypeError on nullish.
|
|
6527
6535
|
if (probed?.type.kind === "dyn") {
|
|
6528
6536
|
const loc = locOf(call);
|
|
@@ -6562,9 +6570,9 @@ function lowerObjectStaticCall(L, call, access) {
|
|
|
6562
6570
|
const argNode = call.arguments[0];
|
|
6563
6571
|
// A CHECKED-DYNAMIC argument — the checker may still spell a record
|
|
6564
6572
|
// type (the JS file-scope object-literal identity story stores the
|
|
6565
|
-
//
|
|
6566
|
-
// runtime walks the
|
|
6567
|
-
// JS's own-key order) and answers a
|
|
6573
|
+
// dyn object), so the LOWERED value's kind is the dispatch: the
|
|
6574
|
+
// runtime walks the dyn node's own keys (integer-like keys first,
|
|
6575
|
+
// JS's own-key order) and answers a dyn array.
|
|
6568
6576
|
{
|
|
6569
6577
|
const probed = probeLower(L, argNode);
|
|
6570
6578
|
const isDyn = probed?.type.kind === "dyn";
|
|
@@ -6786,7 +6794,7 @@ export function lowerFunction(L, decl) {
|
|
|
6786
6794
|
const { params, prologue } = L.declareParams(decl.parameters, sig.params);
|
|
6787
6795
|
// The synthetic `arguments` slot (a dynRest shape BEYOND the declared
|
|
6788
6796
|
// parameters — collectSignatureInner appended it): one trailing
|
|
6789
|
-
//
|
|
6797
|
+
// dyn-array param, resolved by `arguments` reads.
|
|
6790
6798
|
if (sig.params.length > decl.parameters.length && sig.params[sig.params.length - 1].mode === "dynRest") {
|
|
6791
6799
|
const argsLocal = L.declareHiddenLocal("%arguments", DYN);
|
|
6792
6800
|
params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
|