@scriptc/compiler 0.0.3 → 0.0.5
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 +23 -0
- package/dist/backend/cc.js +89 -0
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.js +2 -2
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +37 -2
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-shapes.js +3 -2
- package/dist/backend/emission/emit-shapes.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +7 -8
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +1 -0
- package/dist/backend/emission/emitter.js +123 -3
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.js +198 -15
- 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/diagnostics/diagnostic.d.ts +25 -0
- package/dist/diagnostics/diagnostic.js +88 -2
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lib-exports.d.ts +16 -0
- package/dist/frontend/lib-exports.js +35 -0
- package/dist/frontend/lib-exports.js.map +1 -0
- 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 +124 -34
- 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 +257 -34
- 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 +411 -10
- 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 +25 -4
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +4 -2
- package/dist/frontend/lowering/lower-mixins.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 +163 -0
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +72 -2
- package/dist/frontend/lowering/lowerer.js +339 -19
- 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-static-rewrite.d.ts +3 -0
- package/dist/frontend/npm-static-rewrite.js +677 -0
- package/dist/frontend/npm-static-rewrite.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +8 -1
- package/dist/frontend/npm-static.js +159 -18
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.js +2 -2
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +6 -0
- package/dist/frontend/program.js +110 -22
- 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 +22 -0
- package/dist/index.js +256 -17
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +86 -1
- package/dist/ir/nodes.js +183 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +89 -6
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/profile.d.ts +52 -0
- package/dist/library/profile.js +232 -0
- package/dist/library/profile.js.map +1 -0
- package/package.json +2 -2
- package/surface-manifest.json +67 -2
|
@@ -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
|
}
|