@scriptc/compiler 0.0.2 → 0.0.4
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 +145 -9
- package/dist/backend/cc.d.ts +7 -0
- package/dist/backend/cc.js +1 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +35 -0
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -0
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emitter.js +15 -3
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.js +65 -11
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -0
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/coverage/surface-manifest.d.ts +22 -0
- package/dist/coverage/surface-manifest.js +295 -0
- package/dist/coverage/surface-manifest.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +16 -0
- package/dist/diagnostics/diagnostic.js +26 -2
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +76 -6
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +37 -4
- package/dist/frontend/lowering/lower-builtins.js +240 -6
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +122 -32
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +34 -2
- package/dist/frontend/lowering/lower-classes.js +256 -33
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +25 -3
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +10 -0
- package/dist/frontend/lowering/lower-exprs.js +410 -9
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +16 -1
- package/dist/frontend/lowering/lower-inspect.js +132 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +24 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +6 -5
- package/dist/frontend/lowering/lower-modules.js +56 -18
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +56 -0
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +57 -1
- package/dist/frontend/lowering/lowerer.js +291 -10
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +9 -2
- package/dist/frontend/lowering/surfaces.js +44 -7
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm.js +2 -2
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.js +59 -8
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.js +120 -5
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/shared.d.ts +8 -2
- package/dist/frontend/shared.js +22 -6
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/ts7/checker.js +1 -1
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/types.d.ts +25 -1
- package/dist/frontend/types.js +121 -7
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +43 -1
- package/dist/ir/nodes.js +41 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +38 -6
- package/dist/ir/validate.js.map +1 -1
- package/package.json +6 -4
- package/surface-manifest.json +2117 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PoisonError } from "./lowerer.js";
|
|
2
|
-
import { canAdaptDynFuncTo, STRING, isUnitType, typeEquals } from "../../ir/nodes.js";
|
|
2
|
+
import { canAdaptDynFuncTo, canMarshalTypedFuncIntoIsland, DYN, JSVAL, STRING, isUnitType, typeEquals } from "../../ir/nodes.js";
|
|
3
3
|
import { LIB_FN_SIGS, REGEX_INTRINSIC_SIGS, STR_INTRINSIC_SIGS } from "../../ir/validate.js";
|
|
4
4
|
import { unionMismatchDiag, unsupportedDiag } from "../../diagnostics/diagnostic.js";
|
|
5
5
|
/** What a dynCheck can validate — coerceToExpected's dyn→typed domain,
|
|
@@ -29,6 +29,18 @@ function dynCheckable(L, want) {
|
|
|
29
29
|
function coerceSlot(L, arg, want, what) {
|
|
30
30
|
if (typeEquals(arg.type, want))
|
|
31
31
|
return arg;
|
|
32
|
+
// An ISLAND value in a typed intrinsic slot (`/x/.test(anyText)`,
|
|
33
|
+
// `" ".repeat(anyN)` — checker-`any` arguments the surface signatures
|
|
34
|
+
// accept): the VALIDATED island exit, exactly the dynCheck stance one
|
|
35
|
+
// branch down — strict for primitives, JSON round-trip for composites,
|
|
36
|
+
// a lying handle throws the catchable TypeError. Targets outside the
|
|
37
|
+
// exit set keep the named fence.
|
|
38
|
+
if (arg.type.kind === "jsval" && want.kind !== "jsval") {
|
|
39
|
+
if (L.boundaryExitSafe(want)) {
|
|
40
|
+
return { kind: "jsExit", value: arg, type: want, loc: arg.loc };
|
|
41
|
+
}
|
|
42
|
+
fence(L, "SC1100", arg.loc, `passing 'any'-typed values where '${L.fmt(want)}' is expected (${what})`);
|
|
43
|
+
}
|
|
32
44
|
if (arg.type.kind === "dyn" && want.kind !== "dyn") {
|
|
33
45
|
if (dynCheckable(L, want)) {
|
|
34
46
|
return { kind: "dynCheck", value: arg, type: want, loc: arg.loc };
|
|
@@ -112,18 +124,22 @@ export function enforceLibBoundary(L, node) {
|
|
|
112
124
|
}
|
|
113
125
|
if (kind === "arrIntrinsic") {
|
|
114
126
|
const e = rec;
|
|
115
|
-
if (e.receiver.type.kind === "dyn" || isUnitType(e.receiver.type)) {
|
|
127
|
+
if (e.receiver.type.kind === "dyn" || e.receiver.type.kind === "jsval" || isUnitType(e.receiver.type)) {
|
|
116
128
|
// No element type exists to validate a dyn receiver against — the
|
|
117
|
-
// honest answer is the operations-on-unknown fence.
|
|
118
|
-
//
|
|
119
|
-
//
|
|
129
|
+
// honest answer is the operations-on-unknown fence. An island
|
|
130
|
+
// (jsval) receiver fences too: the exit would COPY the engine
|
|
131
|
+
// array, so a static intrinsic over it silently mutates the copy —
|
|
132
|
+
// the producing sites route jsval receivers through the engine's
|
|
133
|
+
// own methods instead. Other non-array receivers stay the
|
|
134
|
+
// validator's ICE (frontend breakage, not a checked-dynamic
|
|
135
|
+
// escape).
|
|
120
136
|
fence(L, "SC1100", e.receiver.loc, `'.${e.method}()' on '${L.fmt(e.receiver.type)}' array receivers`);
|
|
121
137
|
}
|
|
122
138
|
return;
|
|
123
139
|
}
|
|
124
140
|
if (kind === "callValue") {
|
|
125
141
|
const e = rec;
|
|
126
|
-
if (e.callee.type.kind === "dyn" || isUnitType(e.callee.type)) {
|
|
142
|
+
if (e.callee.type.kind === "dyn" || e.callee.type.kind === "jsval" || isUnitType(e.callee.type)) {
|
|
127
143
|
fence(L, "SC1100", e.loc, `calling '${L.fmt(e.callee.type)}' values`);
|
|
128
144
|
}
|
|
129
145
|
if (e.callee.type.kind !== "func")
|
|
@@ -139,5 +155,59 @@ export function enforceLibBoundary(L, node) {
|
|
|
139
155
|
});
|
|
140
156
|
return;
|
|
141
157
|
}
|
|
158
|
+
if (kind === "jsOp") {
|
|
159
|
+
// Engine-op arguments must be jsval. The producing sites marshal with
|
|
160
|
+
// jsvalIn, but a checker-`any` expression can LOWER to another world
|
|
161
|
+
// (dyn.this, the DOM WeakSet placeholder, JS rest-args) — re-apply
|
|
162
|
+
// jsvalIn's rules here: units become the engine's own units, typed
|
|
163
|
+
// values with an island representation marshal in, and dyn values (no
|
|
164
|
+
// DOM→engine bridge that preserves handles/functions) fence with
|
|
165
|
+
// jsvalIn's own message.
|
|
166
|
+
const e = rec;
|
|
167
|
+
e.args.forEach((a, i) => {
|
|
168
|
+
if (a.type.kind === "jsval")
|
|
169
|
+
return;
|
|
170
|
+
if (isUnitType(a.type)) {
|
|
171
|
+
e.args[i] = { kind: "jsOp", op: a.type.kind === "undefinedT" ? "undefLit" : "nullLit", args: [], type: JSVAL, loc: a.loc };
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (a.type.kind === "dyn") {
|
|
175
|
+
fence(L, "SC1100", a.loc, "passing 'unknown' values into dynamically-executed ('any'-typed) code (validate with 'as <type>' first)");
|
|
176
|
+
}
|
|
177
|
+
if (L.boundarySafe(a.type) ||
|
|
178
|
+
(a.type.kind === "func" && canMarshalTypedFuncIntoIsland(a.type, (id) => L.shapes.get(id), (id) => L.unions.get(id)))) {
|
|
179
|
+
e.args[i] = { kind: "jsMarshal", value: a, type: JSVAL, loc: a.loc };
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
fence(L, "SC1090", a.loc, `'${L.fmt(a.type)}' values crossing into dynamically-executed ('any'-typed) code`);
|
|
183
|
+
});
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (kind === "dynCall" || kind === "dynInvoke") {
|
|
187
|
+
// Checked-dynamic call arguments must be dyn. Convertible typed values
|
|
188
|
+
// take the ordinary dynFrom crossing; island values have NO bridge
|
|
189
|
+
// into the DOM (a jsval handle cannot ride the deep-copy), so they
|
|
190
|
+
// fence — named, catchable at runtime in JS sources, never an ICE.
|
|
191
|
+
const e = rec;
|
|
192
|
+
if (kind === "dynInvoke") {
|
|
193
|
+
const inv = e;
|
|
194
|
+
if (inv.recv.type.kind !== "dyn") {
|
|
195
|
+
fence(L, "SC1100", inv.recv.loc, `'.${inv.method}()' calls through '${L.fmt(inv.recv.type)}' receivers in checked-dynamic positions`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
e.args.forEach((a, i) => {
|
|
199
|
+
if (a.type.kind === "dyn")
|
|
200
|
+
return;
|
|
201
|
+
if (a.type.kind === "jsval") {
|
|
202
|
+
fence(L, "SC1100", a.loc, "passing 'any'-typed values into calls through 'unknown' values (validate with 'as <type>' first)");
|
|
203
|
+
}
|
|
204
|
+
if (a.kind === "unitLit" || L.dynConvertible(a.type)) {
|
|
205
|
+
e.args[i] = { kind: "dynFrom", value: a, type: DYN, loc: a.loc };
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
fence(L, "SC1100", a.loc, `passing '${L.fmt(a.type)}' values into calls through 'unknown' values`);
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
142
212
|
}
|
|
143
213
|
//# sourceMappingURL=lib-boundary.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib-boundary.js","sourceRoot":"","sources":["../../../src/frontend/lowering/lib-boundary.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"lib-boundary.js","sourceRoot":"","sources":["../../../src/frontend/lowering/lib-boundary.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,6 +44,22 @@ export declare function isHttp2ConstantsExpr(L: Lowerer, node: ts.Expression): b
|
|
|
44
44
|
* literal; unknown members fence by name. Null when the receiver is not
|
|
45
45
|
* the constants object (the property chain keeps trying). */
|
|
46
46
|
export declare function lowerHttp2ConstantsProperty(L: Lowerer, expr: ts.PropertyAccessExpression): IrExpr | null;
|
|
47
|
+
/** True for any spelling of node:perf_hooks' `performance` object — the
|
|
48
|
+
* named import binding, a namespace/default-import member, the require
|
|
49
|
+
* twins (all through the shared builtin tables), or the GLOBAL Node
|
|
50
|
+
* exposes without any import (the module export and the global are one
|
|
51
|
+
* value; provenance-checked like console/process, so the bare
|
|
52
|
+
* identifier and the globalThis.performance member both land here and
|
|
53
|
+
* a user's own `performance` binding never does). */
|
|
54
|
+
export declare function isPerfHooksPerformanceExpr(L: Lowerer, node: ts.Expression): boolean;
|
|
55
|
+
/** The node:perf_hooks spoke: `performance.now()` reads the runtime's
|
|
56
|
+
* monotonic clock anchored at process start — Node's timeOrigin for a
|
|
57
|
+
* compiled program, fractional milliseconds — and
|
|
58
|
+
* `performance.now.bind(performance)` (the mockable-clock idiom's
|
|
59
|
+
* getTimestamp) is the same clock as a plain () => number function
|
|
60
|
+
* value. Other members on the performance object fence by name; null
|
|
61
|
+
* for non-perf_hooks callees (the call chain keeps trying). */
|
|
62
|
+
export declare function lowerPerfHooksCall(L: Lowerer, expr: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
|
|
47
63
|
/** True for `const { NGHTTP2_CANCEL, ... } = http2.constants` — a plain
|
|
48
64
|
* object destructure (identifier elements, renames allowed, no rest/
|
|
49
65
|
* defaults/nesting) over the constants object whose every name is in
|
|
@@ -414,6 +430,22 @@ export declare function lowerFsReaddirTypesCall(L: Lowerer, call: ts.CallExpress
|
|
|
414
430
|
* %dtype field compared against libuv's UV_DIRENT code. Node's other
|
|
415
431
|
* type probes (isBlockDevice, ...) fence with the supported list. */
|
|
416
432
|
export declare function lowerDirentMethodCall(L: Lowerer, call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
|
|
433
|
+
/** querystring.parse / querystring.decode: the scan runs in the runtime
|
|
434
|
+
* (scr_qs_parse_into fills the result dictionary's overflow map), so the
|
|
435
|
+
* frontend completes sep/eq/maxKeys to Node's defaults and verifies the
|
|
436
|
+
* call site's mapped result IS the ParsedUrlQuery dictionary — a pure
|
|
437
|
+
* index-signature record over `string | string[]` (an undefined arm
|
|
438
|
+
* tolerated: @types/node's Dict) — the networkInterfaces verification
|
|
439
|
+
* stance. The default decoder is the one lowered decoder; a custom
|
|
440
|
+
* decodeURIComponent option fences by name. */
|
|
441
|
+
export declare function lowerQuerystringParseCall(L: Lowerer, call: ts.CallExpression, loc: SrcLoc): IrExpr;
|
|
442
|
+
/** querystring.stringify / querystring.encode: the object crosses as a
|
|
443
|
+
* DOM value (dynFrom — JSON-safe records and, in JS sources, dyn values
|
|
444
|
+
* directly) and Node's encodeStringified rules run in the runtime
|
|
445
|
+
* (scr_qs_stringify), so arrays expand to repeated keys and
|
|
446
|
+
* null/undefined values are empty. The default encoder is the one
|
|
447
|
+
* lowered encoder; a custom encodeURIComponent option fences by name. */
|
|
448
|
+
export declare function lowerQuerystringStringifyCall(L: Lowerer, call: ts.CallExpression, loc: SrcLoc): IrExpr;
|
|
417
449
|
export declare function lowerOsNetworkInterfacesCall(L: Lowerer, call: ts.CallExpression, loc: SrcLoc): IrExpr;
|
|
418
450
|
/** `process.env.NAME` → the process.envGet intrinsic with a literal key
|
|
419
451
|
* (the element form lands in lowerElementAccess). getenv(3) at runtime:
|
|
@@ -504,8 +536,9 @@ export declare function lowerProcessOptionalMethodCall(L: Lowerer, expr: ts.Call
|
|
|
504
536
|
export declare function envSnapshotHelper(L: Lowerer, shapeId: string, loc: SrcLoc): string | null;
|
|
505
537
|
export declare function isConsoleLog(L: Lowerer, call: ts.CallExpression): boolean;
|
|
506
538
|
/** The console member of a `console.<member>(...)` call, for the lowered
|
|
507
|
-
*
|
|
539
|
+
* set: "log"/"info"/"debug" (stdout — Node's info and debug ARE log
|
|
540
|
+
* under other names), and "error"/"warn" (both stderr — Node's warn IS
|
|
508
541
|
* error under another name; the output is identical). Provenance-checked
|
|
509
|
-
* like every stdlib global. Null for anything else (console.
|
|
510
|
-
*
|
|
511
|
-
export declare function consoleCallMember(L: Lowerer, call: ts.CallExpression): "log" | "error" | "warn" | null;
|
|
542
|
+
* like every stdlib global. Null for anything else (console.table, a
|
|
543
|
+
* user's own console binding, ...). */
|
|
544
|
+
export declare function consoleCallMember(L: Lowerer, call: ts.CallExpression): "log" | "info" | "debug" | "error" | "warn" | null;
|
|
@@ -6,7 +6,7 @@ import { builtinModules } from "node:module";
|
|
|
6
6
|
import * as ts from "../ts7/adapter.js";
|
|
7
7
|
import { dynUndefinedExpr, own } from "./lowerer.js";
|
|
8
8
|
import { canonicalBuiltinModule, isJsSourceFile, locOf, requireSpecOf } from "../program.js";
|
|
9
|
-
import { builtinModuleFnOf, FS_READDIR_DOCUMENTED_OPTIONS, FS_WATCH_DOCUMENTED_OPTIONS, FS_WRITE_FILE_DOCUMENTED_OPTIONS, READLINE_DOCUMENTED_OPTIONS, builtinConstLit, fenceOrDropOptionKey, isChildSurfaceMember, } from "./surfaces.js";
|
|
9
|
+
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";
|
|
10
10
|
import { conditionalSpreadOf } from "./lower-exprs.js";
|
|
11
11
|
import { HTTP2_CONSTANTS } from "./http2-constants.js";
|
|
12
12
|
import { timerStyleCallback } from "./lower-calls.js";
|
|
@@ -81,7 +81,7 @@ export function builtinImportOf(L, ident) {
|
|
|
81
81
|
}
|
|
82
82
|
// The RE-EXPORT FACADE hop: a binding acquired through a user module
|
|
83
83
|
// that re-exports a builtin (`import { ok } from "./assert-facade.js"`
|
|
84
|
-
// over `export { ok } from "node:assert"` —
|
|
84
|
+
// over `export { ok } from "node:assert"` — the formatter idiom's
|
|
85
85
|
// universal/assert idiom; the namespace-member spelling resolves to
|
|
86
86
|
// the facade's ExportSpecifier the same way). The specifier here is a
|
|
87
87
|
// user module, so provenance comes from the ALIAS CHAIN instead: the
|
|
@@ -180,6 +180,82 @@ export function lowerHttp2ConstantsProperty(L, expr) {
|
|
|
180
180
|
}
|
|
181
181
|
return builtinConstLit(value, locOf(expr));
|
|
182
182
|
}
|
|
183
|
+
/** True for any spelling of node:perf_hooks' `performance` object — the
|
|
184
|
+
* named import binding, a namespace/default-import member, the require
|
|
185
|
+
* twins (all through the shared builtin tables), or the GLOBAL Node
|
|
186
|
+
* exposes without any import (the module export and the global are one
|
|
187
|
+
* value; provenance-checked like console/process, so the bare
|
|
188
|
+
* identifier and the globalThis.performance member both land here and
|
|
189
|
+
* a user's own `performance` binding never does). */
|
|
190
|
+
export function isPerfHooksPerformanceExpr(L, node) {
|
|
191
|
+
if (L.isStdlibGlobal(node, "performance"))
|
|
192
|
+
return true;
|
|
193
|
+
if (ts.isIdentifier(node)) {
|
|
194
|
+
const bi = builtinImportOf(L, node);
|
|
195
|
+
return bi !== null && bi.module === "perf_hooks" && bi.member === "performance";
|
|
196
|
+
}
|
|
197
|
+
if (ts.isPropertyAccessExpression(node) && !node.questionDotToken) {
|
|
198
|
+
const bi = L.builtinMemberOf(node);
|
|
199
|
+
return bi !== null && bi.module === "perf_hooks" && bi.member === "performance";
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
/** The node:perf_hooks spoke: `performance.now()` reads the runtime's
|
|
204
|
+
* monotonic clock anchored at process start — Node's timeOrigin for a
|
|
205
|
+
* compiled program, fractional milliseconds — and
|
|
206
|
+
* `performance.now.bind(performance)` (the mockable-clock idiom's
|
|
207
|
+
* getTimestamp) is the same clock as a plain () => number function
|
|
208
|
+
* value. Other members on the performance object fence by name; null
|
|
209
|
+
* for non-perf_hooks callees (the call chain keeps trying). */
|
|
210
|
+
export function lowerPerfHooksCall(L, expr, access) {
|
|
211
|
+
if (access.questionDotToken)
|
|
212
|
+
return null;
|
|
213
|
+
const loc = locOf(expr);
|
|
214
|
+
if (access.name.text === "now" && isPerfHooksPerformanceExpr(L, access.expression)) {
|
|
215
|
+
if (expr.arguments.length !== 0) {
|
|
216
|
+
L.noLowering("performance.now with arguments", expr, "Node's performance.now takes none");
|
|
217
|
+
}
|
|
218
|
+
return { kind: "libCall", fn: "perf.now", args: [], type: F64, loc };
|
|
219
|
+
}
|
|
220
|
+
if (access.name.text === "bind" &&
|
|
221
|
+
ts.isPropertyAccessExpression(access.expression) &&
|
|
222
|
+
!access.expression.questionDotToken &&
|
|
223
|
+
access.expression.name.text === "now" &&
|
|
224
|
+
isPerfHooksPerformanceExpr(L, access.expression.expression)) {
|
|
225
|
+
if (expr.arguments.length !== 1 || !isPerfHooksPerformanceExpr(L, expr.arguments[0])) {
|
|
226
|
+
L.noLowering("this performance.now.bind form", expr, "performance.now.bind(performance) is the lowered function-value spelling");
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
kind: "closure",
|
|
230
|
+
fnName: perfNowFnValueOf(L),
|
|
231
|
+
captures: [],
|
|
232
|
+
type: funcOf([], F64),
|
|
233
|
+
loc,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (isPerfHooksPerformanceExpr(L, access.expression)) {
|
|
237
|
+
L.noLowering(`perf_hooks performance.${access.name.text}`, expr, "performance.now() — and its .bind(performance) function value — is the lowered surface");
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
/** The memoized () => number lifted wrapper behind
|
|
242
|
+
* performance.now.bind(performance): a plain function value over the
|
|
243
|
+
* same perf.now libCall. */
|
|
244
|
+
function perfNowFnValueOf(L) {
|
|
245
|
+
const name = "%perf.now.value";
|
|
246
|
+
if (!L.liftedFns.some((f) => f.name === name)) {
|
|
247
|
+
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
248
|
+
L.liftedFns.push({
|
|
249
|
+
name,
|
|
250
|
+
params: [],
|
|
251
|
+
returnType: F64,
|
|
252
|
+
locals: [],
|
|
253
|
+
body: [{ kind: "return", value: { kind: "libCall", fn: "perf.now", args: [], type: F64, loc }, loc }],
|
|
254
|
+
loc,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return name;
|
|
258
|
+
}
|
|
183
259
|
/** True for `const { NGHTTP2_CANCEL, ... } = http2.constants` — a plain
|
|
184
260
|
* object destructure (identifier elements, renames allowed, no rest/
|
|
185
261
|
* defaults/nesting) over the constants object whose every name is in
|
|
@@ -306,6 +382,20 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
|
|
|
306
382
|
if (bi.module === "os" && bi.member === "userInfo") {
|
|
307
383
|
return lowerOsUserInfoCall(L, expr, loc);
|
|
308
384
|
}
|
|
385
|
+
// node:querystring — parse/stringify are entirely special-cased (the
|
|
386
|
+
// sep/eq/options completions, parse's call-site-shaped dictionary
|
|
387
|
+
// result, stringify's DOM-crossing object argument); decode/encode
|
|
388
|
+
// are Node's own aliases of the pair (`const decode = parse` in the
|
|
389
|
+
// module source) and take the same lowerings. escape/unescape ride
|
|
390
|
+
// the generic table tail below.
|
|
391
|
+
if (bi.module === "querystring") {
|
|
392
|
+
if (bi.member === "parse" || bi.member === "decode") {
|
|
393
|
+
return lowerQuerystringParseCall(L, expr, loc);
|
|
394
|
+
}
|
|
395
|
+
if (bi.member === "stringify" || bi.member === "encode") {
|
|
396
|
+
return lowerQuerystringStringifyCall(L, expr, loc);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
309
399
|
// node:timers/promises — setTimeout([delay]) and setImmediate(): void
|
|
310
400
|
// promises the shared timer heap settles. The omitted delay completes
|
|
311
401
|
// to Node's 1ms floor (scr_timer_coerce_ms clamps anyway; the literal
|
|
@@ -3881,6 +3971,149 @@ function lowerOsUserInfoCall(L, call, loc) {
|
|
|
3881
3971
|
}
|
|
3882
3972
|
return { kind: "recordLit", fields, type: result, loc };
|
|
3883
3973
|
}
|
|
3974
|
+
/** querystring's sep/eq arguments: an omitted argument, the literal
|
|
3975
|
+
* null, and the literal undefined all mean the default (Node's falsy
|
|
3976
|
+
* rule — parse(s, null, null, opts) is the canonical maxKeys spelling);
|
|
3977
|
+
* a string expression passes through (the runtime applies the same
|
|
3978
|
+
* falsy rule to '' at runtime). Everything else fences. */
|
|
3979
|
+
function qsSepEqArg(L, node, dflt, what, loc) {
|
|
3980
|
+
if (!node ||
|
|
3981
|
+
node.kind === ts.SyntaxKind.NullKeyword ||
|
|
3982
|
+
(ts.isIdentifier(node) && node.text === "undefined")) {
|
|
3983
|
+
return { kind: "strLit", value: dflt, type: STRING, loc };
|
|
3984
|
+
}
|
|
3985
|
+
const v = L.lowerExpr(node);
|
|
3986
|
+
if (v.type.kind !== "string") {
|
|
3987
|
+
L.noLowering(`${what} with a '${L.fmt(v.type)}' separator`, node, "pass a string, or null/undefined for the default (narrow unions first)");
|
|
3988
|
+
}
|
|
3989
|
+
return v;
|
|
3990
|
+
}
|
|
3991
|
+
/** querystring.parse / querystring.decode: the scan runs in the runtime
|
|
3992
|
+
* (scr_qs_parse_into fills the result dictionary's overflow map), so the
|
|
3993
|
+
* frontend completes sep/eq/maxKeys to Node's defaults and verifies the
|
|
3994
|
+
* call site's mapped result IS the ParsedUrlQuery dictionary — a pure
|
|
3995
|
+
* index-signature record over `string | string[]` (an undefined arm
|
|
3996
|
+
* tolerated: @types/node's Dict) — the networkInterfaces verification
|
|
3997
|
+
* stance. The default decoder is the one lowered decoder; a custom
|
|
3998
|
+
* decodeURIComponent option fences by name. */
|
|
3999
|
+
export function lowerQuerystringParseCall(L, call, loc) {
|
|
4000
|
+
if (call.arguments.length > 4 || call.arguments.some(ts.isSpreadElement)) {
|
|
4001
|
+
L.noLowering(`querystring.parse with ${call.arguments.length} arguments`, call);
|
|
4002
|
+
}
|
|
4003
|
+
const fence = () => L.noLowering("querystring.parse where the result is not the ParsedUrlQuery dictionary", call, "the `{ [key: string]: string | string[] }` shape is the supported result");
|
|
4004
|
+
const result = L.mapTypeOf(L.typeOf(call));
|
|
4005
|
+
if (result?.kind !== "record")
|
|
4006
|
+
fence();
|
|
4007
|
+
const dictShape = L.shapes.get(result.shapeId);
|
|
4008
|
+
if (!dictShape || dictShape.tuple || dictShape.fields.length > 0 || !dictShape.indexValue)
|
|
4009
|
+
fence();
|
|
4010
|
+
const iv = dictShape.indexValue;
|
|
4011
|
+
if (iv.kind !== "union")
|
|
4012
|
+
fence();
|
|
4013
|
+
const ivDef = L.unions.get(iv.unionId);
|
|
4014
|
+
if (!ivDef)
|
|
4015
|
+
fence();
|
|
4016
|
+
let sawStr = false;
|
|
4017
|
+
let sawArr = false;
|
|
4018
|
+
for (const arm of ivDef.arms) {
|
|
4019
|
+
if (arm.kind === "string")
|
|
4020
|
+
sawStr = true;
|
|
4021
|
+
else if (arm.kind === "array" && arm.elem.kind === "string")
|
|
4022
|
+
sawArr = true;
|
|
4023
|
+
// undefined rides @types/node's Dict; the f64 arm is the
|
|
4024
|
+
// header-family canonicalization (types.ts interns every
|
|
4025
|
+
// `string | string[]`-slotted dictionary as the one canonical
|
|
4026
|
+
// header shape, whose slot adds number type-level only — parse
|
|
4027
|
+
// never stores one).
|
|
4028
|
+
else if (arm.kind !== "undefinedT" && arm.kind !== "f64")
|
|
4029
|
+
fence();
|
|
4030
|
+
}
|
|
4031
|
+
if (!sawStr || !sawArr)
|
|
4032
|
+
fence();
|
|
4033
|
+
const str = call.arguments[0]
|
|
4034
|
+
? L.lowerExprExpecting(call.arguments[0], STRING)
|
|
4035
|
+
: L.noLowering("querystring.parse without a query string", call);
|
|
4036
|
+
const sep = qsSepEqArg(L, call.arguments[1], "&", "querystring.parse", loc);
|
|
4037
|
+
const eq = qsSepEqArg(L, call.arguments[2], "=", "querystring.parse", loc);
|
|
4038
|
+
// The options walk: maxKeys lowers (Node's rule — > 0 caps the pair
|
|
4039
|
+
// count, 0 and negatives mean unlimited — lives in the runtime, so
|
|
4040
|
+
// any number expression works); a custom decodeURIComponent changes
|
|
4041
|
+
// every decoded byte and fences by name.
|
|
4042
|
+
let maxKeys = { kind: "numLit", value: 1000, type: F64, loc };
|
|
4043
|
+
const optsNode = call.arguments[3];
|
|
4044
|
+
if (optsNode) {
|
|
4045
|
+
if (!ts.isObjectLiteralExpression(optsNode)) {
|
|
4046
|
+
L.noLowering("querystring.parse with a non-literal options argument", optsNode, "the supported form spells the options inline: parse(s, sep, eq, { maxKeys: n })");
|
|
4047
|
+
}
|
|
4048
|
+
for (const p of optsNode.properties) {
|
|
4049
|
+
const m = optionMember(p);
|
|
4050
|
+
if (!m) {
|
|
4051
|
+
L.noLowering("querystring.parse with this options shape", p, "spreads and computed keys have no lowering — write each member inline");
|
|
4052
|
+
}
|
|
4053
|
+
if (m.name === "maxKeys") {
|
|
4054
|
+
maxKeys = L.lowerExprExpecting(m.value, F64);
|
|
4055
|
+
}
|
|
4056
|
+
else if (m.name === "decodeURIComponent") {
|
|
4057
|
+
L.noLowering("querystring.parse with a custom decodeURIComponent", p, "the default decoder is the lowered surface (strict decodeURIComponent with Node's lenient fallback)");
|
|
4058
|
+
}
|
|
4059
|
+
else {
|
|
4060
|
+
fenceOrDropOptionKey(L, p, m.name, "querystring.parse", QS_PARSE_DOCUMENTED_OPTIONS, "maxKeys is the supported option");
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
return { kind: "libCall", fn: "qs.parse", args: [str, sep, eq, maxKeys], type: result, loc };
|
|
4065
|
+
}
|
|
4066
|
+
/** querystring.stringify / querystring.encode: the object crosses as a
|
|
4067
|
+
* DOM value (dynFrom — JSON-safe records and, in JS sources, dyn values
|
|
4068
|
+
* directly) and Node's encodeStringified rules run in the runtime
|
|
4069
|
+
* (scr_qs_stringify), so arrays expand to repeated keys and
|
|
4070
|
+
* null/undefined values are empty. The default encoder is the one
|
|
4071
|
+
* lowered encoder; a custom encodeURIComponent option fences by name. */
|
|
4072
|
+
export function lowerQuerystringStringifyCall(L, call, loc) {
|
|
4073
|
+
if (call.arguments.length > 4 || call.arguments.some(ts.isSpreadElement)) {
|
|
4074
|
+
L.noLowering(`querystring.stringify with ${call.arguments.length} arguments`, call);
|
|
4075
|
+
}
|
|
4076
|
+
const objNode = call.arguments[0];
|
|
4077
|
+
// stringify() / stringify(undefined) / stringify(null): Node answers
|
|
4078
|
+
// '' for every non-object — the constant folds.
|
|
4079
|
+
if (!objNode ||
|
|
4080
|
+
objNode.kind === ts.SyntaxKind.NullKeyword ||
|
|
4081
|
+
(ts.isIdentifier(objNode) && objNode.text === "undefined")) {
|
|
4082
|
+
return { kind: "strLit", value: "", type: STRING, loc };
|
|
4083
|
+
}
|
|
4084
|
+
const objV = L.lowerExpr(objNode);
|
|
4085
|
+
let obj;
|
|
4086
|
+
if (objV.type.kind === "dyn") {
|
|
4087
|
+
obj = objV;
|
|
4088
|
+
}
|
|
4089
|
+
else if (objV.type.kind === "record" && L.dynConvertible(objV.type)) {
|
|
4090
|
+
obj = { kind: "dynFrom", value: objV, type: DYN, loc };
|
|
4091
|
+
}
|
|
4092
|
+
else {
|
|
4093
|
+
L.noLowering(`querystring.stringify of '${L.fmt(objV.type)}' values`, objNode, "pass a record of string/number/boolean values (arrays of those expand to repeated keys; null/undefined values serialize empty)");
|
|
4094
|
+
}
|
|
4095
|
+
const sep = qsSepEqArg(L, call.arguments[1], "&", "querystring.stringify", loc);
|
|
4096
|
+
const eq = qsSepEqArg(L, call.arguments[2], "=", "querystring.stringify", loc);
|
|
4097
|
+
const optsNode = call.arguments[3];
|
|
4098
|
+
if (optsNode) {
|
|
4099
|
+
if (!ts.isObjectLiteralExpression(optsNode)) {
|
|
4100
|
+
L.noLowering("querystring.stringify with a non-literal options argument", optsNode, "the supported form spells the options inline (and the only documented option, encodeURIComponent, has no lowering)");
|
|
4101
|
+
}
|
|
4102
|
+
for (const p of optsNode.properties) {
|
|
4103
|
+
const m = optionMember(p);
|
|
4104
|
+
if (!m) {
|
|
4105
|
+
L.noLowering("querystring.stringify with this options shape", p, "spreads and computed keys have no lowering — write each member inline");
|
|
4106
|
+
}
|
|
4107
|
+
if (m.name === "encodeURIComponent") {
|
|
4108
|
+
L.noLowering("querystring.stringify with a custom encodeURIComponent", p, "the default encoder (querystring.escape's component set) is the lowered surface");
|
|
4109
|
+
}
|
|
4110
|
+
else {
|
|
4111
|
+
fenceOrDropOptionKey(L, p, m.name, "querystring.stringify", QS_STRINGIFY_DOCUMENTED_OPTIONS, "no stringify options have a lowering");
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4115
|
+
return { kind: "libCall", fn: "qs.stringify", args: [obj, sep, eq], type: STRING, loc };
|
|
4116
|
+
}
|
|
3884
4117
|
export function lowerOsNetworkInterfacesCall(L, call, loc) {
|
|
3885
4118
|
if (call.arguments.length !== 0) {
|
|
3886
4119
|
L.noLowering(`networkInterfaces with ${call.arguments.length} arguments`, call, "networkInterfaces() takes no arguments");
|
|
@@ -5231,10 +5464,11 @@ export function isConsoleLog(L, call) {
|
|
|
5231
5464
|
return consoleCallMember(L, call) === "log";
|
|
5232
5465
|
}
|
|
5233
5466
|
/** The console member of a `console.<member>(...)` call, for the lowered
|
|
5234
|
-
*
|
|
5467
|
+
* set: "log"/"info"/"debug" (stdout — Node's info and debug ARE log
|
|
5468
|
+
* under other names), and "error"/"warn" (both stderr — Node's warn IS
|
|
5235
5469
|
* error under another name; the output is identical). Provenance-checked
|
|
5236
|
-
* like every stdlib global. Null for anything else (console.
|
|
5237
|
-
*
|
|
5470
|
+
* like every stdlib global. Null for anything else (console.table, a
|
|
5471
|
+
* user's own console binding, ...). */
|
|
5238
5472
|
export function consoleCallMember(L, call) {
|
|
5239
5473
|
if (!ts.isPropertyAccessExpression(call.expression))
|
|
5240
5474
|
return null;
|
|
@@ -5242,7 +5476,7 @@ export function consoleCallMember(L, call) {
|
|
|
5242
5476
|
if (access.questionDotToken || call.questionDotToken)
|
|
5243
5477
|
return null;
|
|
5244
5478
|
const name = access.name.text;
|
|
5245
|
-
if (name !== "log" && name !== "error" && name !== "warn")
|
|
5479
|
+
if (name !== "log" && name !== "info" && name !== "debug" && name !== "error" && name !== "warn")
|
|
5246
5480
|
return null;
|
|
5247
5481
|
return L.isStdlibGlobal(access.expression, "console") ? name : null;
|
|
5248
5482
|
}
|