@scriptc/compiler 0.0.21 → 0.0.23
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 +117 -37
- package/dist/backend/cc-cache.test.d.ts +1 -0
- package/dist/backend/cc-cache.test.js +2507 -0
- package/dist/backend/cc-cache.test.js.map +1 -0
- package/dist/backend/cc.d.ts +69 -11
- package/dist/backend/cc.js +1937 -222
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-async.js +3 -1
- package/dist/backend/emission/emit-async.js.map +1 -1
- package/dist/backend/emission/emit-exprs.d.ts +10 -0
- package/dist/backend/emission/emit-exprs.js +482 -18
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-stmts.js +13 -5
- package/dist/backend/emission/emit-stmts.js.map +1 -1
- package/dist/backend/emission/emit-types.js +4 -1
- package/dist/backend/emission/emit-types.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +108 -7
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +27 -1
- package/dist/backend/emission/emitter.js +84 -3
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +305 -8
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +831 -23
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +3 -2
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +118 -0
- package/dist/compat/fetch-profile.js +531 -0
- package/dist/compat/fetch-profile.js.map +1 -0
- package/dist/coverage/surface-manifest.js +69 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +10 -0
- package/dist/diagnostics/diagnostic.js +27 -1
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +24 -15
- package/dist/frontend/lowering/lower-builtins.js +217 -69
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +41 -0
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +32 -11
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +3 -3
- package/dist/frontend/lowering/lower-exprs.js +87 -15
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +7 -1
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +123 -7
- package/dist/frontend/lowering/lower-island.js +1976 -26
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +33 -9
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +40 -0
- package/dist/frontend/lowering/lowerer.js +290 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +55 -12
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +20 -4
- package/dist/frontend/program.js +391 -49
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +10 -0
- package/dist/frontend/resolve.js +37 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/ts7/enums.d.ts +9 -0
- package/dist/frontend/ts7/enums.js +8 -6
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/program.js +4 -1
- package/dist/frontend/ts7/program.js.map +1 -1
- package/dist/frontend/types.d.ts +16 -9
- package/dist/frontend/types.js +119 -38
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +70 -14
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +55 -26
- package/dist/ir/nodes.js +42 -29
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +106 -9
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.js +7 -1
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +80 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/sidecar-validate.js +5 -0
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +3 -0
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +1097 -130
|
@@ -785,6 +785,41 @@ export function lowerBuiltinModuleCall(L, expr, bi, fn, loc) {
|
|
|
785
785
|
if (bi.module === "fs" && bi.member === "watch") {
|
|
786
786
|
return lowerFsWatchCall(L, expr, loc);
|
|
787
787
|
}
|
|
788
|
+
// fs.readSync(fd, buffer, offset, length[, position]) — normalize the
|
|
789
|
+
// current-offset forms to Node/libuv's -1 sentinel so the IR and native
|
|
790
|
+
// ABI stay fixed-width. A real numeric position is a positioned read
|
|
791
|
+
// and therefore must not advance the descriptor. Literal null is the
|
|
792
|
+
// documented current-offset spelling; richer nullable expressions must
|
|
793
|
+
// narrow first so no effectful evaluation is silently discarded.
|
|
794
|
+
if (bi.module === "fs" && bi.member === "readSync") {
|
|
795
|
+
const supported = "use readSync(fd, buffer, offset, length[, position]) with a numeric position or literal null; options objects and bigint positions have no lowering";
|
|
796
|
+
if ((expr.arguments.length !== 4 && expr.arguments.length !== 5) ||
|
|
797
|
+
expr.arguments.some(ts.isSpreadElement)) {
|
|
798
|
+
L.noLowering(`readSync with ${expr.arguments.length} argument${expr.arguments.length === 1 ? "" : "s"}`, expr, supported);
|
|
799
|
+
}
|
|
800
|
+
const args = [
|
|
801
|
+
L.lowerExprExpecting(expr.arguments[0], F64),
|
|
802
|
+
L.lowerExprExpecting(expr.arguments[1], BYTES_U8),
|
|
803
|
+
L.lowerExprExpecting(expr.arguments[2], F64),
|
|
804
|
+
L.lowerExprExpecting(expr.arguments[3], F64),
|
|
805
|
+
];
|
|
806
|
+
const positionNode = expr.arguments[4];
|
|
807
|
+
let positionValueNode = positionNode;
|
|
808
|
+
while (positionValueNode && ts.isParenthesizedExpression(positionValueNode)) {
|
|
809
|
+
positionValueNode = positionValueNode.expression;
|
|
810
|
+
}
|
|
811
|
+
if (positionNode === undefined || positionValueNode.kind === ts.SyntaxKind.NullKeyword) {
|
|
812
|
+
args.push({ kind: "numLit", value: -1, type: F64, loc });
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
const positionType = L.mapTypeOf(L.typeOf(positionNode));
|
|
816
|
+
if (positionType?.kind !== "f64") {
|
|
817
|
+
L.noLowering(`readSync with a '${positionType ? L.fmt(positionType) : L.checker.typeToString(L.typeOf(positionNode))}' position`, positionNode, supported);
|
|
818
|
+
}
|
|
819
|
+
args.push(L.lowerExprExpecting(positionNode, F64));
|
|
820
|
+
}
|
|
821
|
+
return { kind: "libCall", fn: "fs.readSync", args, type: F64, loc };
|
|
822
|
+
}
|
|
788
823
|
if (bi.module === "child_process" &&
|
|
789
824
|
(bi.member === "execFileSync" || bi.member === "execSync")) {
|
|
790
825
|
return L.lowerExecSyncCall(expr, bi.member === "execSync", loc);
|
|
@@ -5326,13 +5361,29 @@ export function lowerNumberStaticCall(L, call, access) {
|
|
|
5326
5361
|
}
|
|
5327
5362
|
return null; // other Number statics land on the member fence
|
|
5328
5363
|
}
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5364
|
+
const DATE_GETTER_FNS = {
|
|
5365
|
+
getFullYear: "date.getFullYear",
|
|
5366
|
+
getUTCFullYear: "date.getUTCFullYear",
|
|
5367
|
+
getMonth: "date.getMonth",
|
|
5368
|
+
getUTCMonth: "date.getUTCMonth",
|
|
5369
|
+
getDate: "date.getDate",
|
|
5370
|
+
getUTCDate: "date.getUTCDate",
|
|
5371
|
+
getDay: "date.getDay",
|
|
5372
|
+
getUTCDay: "date.getUTCDay",
|
|
5373
|
+
getHours: "date.getHours",
|
|
5374
|
+
getUTCHours: "date.getUTCHours",
|
|
5375
|
+
getMinutes: "date.getMinutes",
|
|
5376
|
+
getUTCMinutes: "date.getUTCMinutes",
|
|
5377
|
+
getSeconds: "date.getSeconds",
|
|
5378
|
+
getUTCSeconds: "date.getUTCSeconds",
|
|
5379
|
+
getMilliseconds: "date.getMilliseconds",
|
|
5380
|
+
getUTCMilliseconds: "date.getUTCMilliseconds",
|
|
5381
|
+
getTimezoneOffset: "date.getTimezoneOffset",
|
|
5382
|
+
};
|
|
5383
|
+
const DATE_METHOD_HINT = "getTime(), valueOf(), toISOString(), the local/UTC calendar getters, and getTimezoneOffset() are supported; Date setters and locale/string formatters have no lowering";
|
|
5384
|
+
/** The Date slice: statics plus read-only Date values backed by one
|
|
5385
|
+
* TimeClip'd millisecond scalar. Construction lives in lowerNew;
|
|
5386
|
+
* identity and mutating methods remain fenced. */
|
|
5336
5387
|
export function lowerDateCall(L, call, access) {
|
|
5337
5388
|
if (call.questionDotToken || access.questionDotToken)
|
|
5338
5389
|
return null;
|
|
@@ -5363,83 +5414,180 @@ export function lowerDateCall(L, call, access) {
|
|
|
5363
5414
|
}
|
|
5364
5415
|
return { kind: "libCall", fn: "date.utc", args, type: F64, loc };
|
|
5365
5416
|
}
|
|
5366
|
-
if (
|
|
5417
|
+
if (L.mapTypeOf(L.typeOf(access.expression))?.kind !== "date")
|
|
5367
5418
|
return null;
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
const sym = L.resolveValueSymbol(recv.expression);
|
|
5372
|
-
if (!sym || sym.name !== "Date" || !L.isStdlibSymbol(sym))
|
|
5373
|
-
return null;
|
|
5374
|
-
if (access.name.text === "getTime") {
|
|
5375
|
-
// The composed `new Date(x).getTime()` read — the Date value
|
|
5376
|
-
// between the two never materializes (the toISOString precedent).
|
|
5377
|
-
// new Date().getTime() IS Date.now(); the STRING form parses the
|
|
5378
|
-
// bounded date-string grammar (the X509 validity shape portless's
|
|
5379
|
-
// cert-expiry check reads, plus ECMA's own date-time format) and
|
|
5380
|
-
// answers NaN elsewhere — a documented divergence from V8's wider
|
|
5381
|
-
// parser. The ms form is pointless composition; the fence points at
|
|
5382
|
-
// the value.
|
|
5383
|
-
if (call.arguments.length !== 0) {
|
|
5384
|
-
L.noLowering("getTime with arguments", call);
|
|
5385
|
-
}
|
|
5386
|
-
const ctorArgs = recv.arguments ?? [];
|
|
5387
|
-
if (ctorArgs.length === 0) {
|
|
5388
|
-
return { kind: "libCall", fn: "date.now", args: [], type: F64, loc };
|
|
5389
|
-
}
|
|
5390
|
-
if (ctorArgs.length !== 1) {
|
|
5391
|
-
L.noLowering("new Date with year/month/day arguments", recv, "the field constructor is local-time; only new Date() and new Date(dateString) compose with .getTime()");
|
|
5392
|
-
}
|
|
5393
|
-
const arg = L.lowerExpr(ctorArgs[0]);
|
|
5394
|
-
if (arg.type.kind !== "string") {
|
|
5395
|
-
L.noLowering(`new Date of '${L.fmt(arg.type)}' values composed with .getTime()`, ctorArgs[0], arg.type.kind === "f64"
|
|
5396
|
-
? "new Date(ms).getTime() is the ms value — use it directly (or Date.now())"
|
|
5397
|
-
: "the composed form parses date STRINGS — narrow unions first");
|
|
5398
|
-
}
|
|
5399
|
-
return { kind: "libCall", fn: "date.parseGetTime", args: [arg], type: F64, loc };
|
|
5400
|
-
}
|
|
5419
|
+
if (!L.isStdlibMember(access))
|
|
5420
|
+
return null;
|
|
5421
|
+
const name = access.name.text;
|
|
5401
5422
|
if (call.arguments.length !== 0) {
|
|
5402
|
-
L.noLowering(
|
|
5423
|
+
L.noLowering(`Date.prototype.${name} with arguments`, call, DATE_METHOD_HINT);
|
|
5403
5424
|
}
|
|
5404
|
-
const
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5425
|
+
const receiver = L.lowerExpr(access.expression);
|
|
5426
|
+
if (receiver.type.kind !== "date")
|
|
5427
|
+
L.badType(access.expression, L.typeOf(access.expression));
|
|
5428
|
+
if (name === "getTime" || name === "valueOf") {
|
|
5429
|
+
return {
|
|
5430
|
+
kind: "libCall",
|
|
5431
|
+
fn: name === "getTime" ? "date.getTime" : "date.valueOf",
|
|
5432
|
+
args: [receiver],
|
|
5433
|
+
type: F64,
|
|
5434
|
+
loc,
|
|
5435
|
+
};
|
|
5408
5436
|
}
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
if (arg.type.kind !== "f64") {
|
|
5412
|
-
L.noLowering(`new Date of '${L.fmt(arg.type)}' values`, ctorArgs[0], "only the milliseconds form composes — new Date(ms).toISOString(); date-string parsing has no lowering");
|
|
5413
|
-
}
|
|
5414
|
-
ms = arg;
|
|
5437
|
+
if (name === "toISOString") {
|
|
5438
|
+
return { kind: "libCall", fn: "date.toISOStringValue", args: [receiver], type: STRING, loc };
|
|
5415
5439
|
}
|
|
5416
|
-
|
|
5417
|
-
|
|
5440
|
+
const fn = DATE_GETTER_FNS[name];
|
|
5441
|
+
if (fn !== undefined) {
|
|
5442
|
+
return { kind: "libCall", fn, args: [receiver], type: F64, loc };
|
|
5418
5443
|
}
|
|
5419
|
-
|
|
5444
|
+
L.noLowering(`Date.prototype.${name}`, call, DATE_METHOD_HINT, L.checker.getSymbolAtLocation(access.name));
|
|
5420
5445
|
}
|
|
5421
|
-
/**
|
|
5422
|
-
*
|
|
5423
|
-
*
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5446
|
+
/** A direct construction of THE stdlib TextEncoder/TextDecoder, through
|
|
5447
|
+
* type-only wrappers. Name alone is never enough: a user class with the
|
|
5448
|
+
* same spelling keeps the ordinary class lowering. */
|
|
5449
|
+
function directTextCodecCtorOf(L, expr) {
|
|
5450
|
+
const ctor = stripTypeCasts(expr);
|
|
5451
|
+
if (!ts.isNewExpression(ctor))
|
|
5452
|
+
return null;
|
|
5453
|
+
const callee = stripTypeCasts(ctor.expression);
|
|
5454
|
+
if (!ts.isIdentifier(callee))
|
|
5455
|
+
return null;
|
|
5456
|
+
if (callee.text !== "TextDecoder" && callee.text !== "TextEncoder")
|
|
5457
|
+
return null;
|
|
5458
|
+
const sym = L.resolveValueSymbol(callee);
|
|
5459
|
+
if (!sym || !L.isStdlibSymbol(sym))
|
|
5460
|
+
return null;
|
|
5461
|
+
if (sym.name !== "TextDecoder" && sym.name !== "TextEncoder")
|
|
5462
|
+
return null;
|
|
5463
|
+
return { cls: sym.name, ctor };
|
|
5464
|
+
}
|
|
5465
|
+
/** True when construction itself is effect-free and inside the already
|
|
5466
|
+
* lowered codec slice, so a const binding can be erased and calls can
|
|
5467
|
+
* resolve back to the initializer. TextDecoder's explicit label must be
|
|
5468
|
+
* an actual literal here: accepting an arbitrary expression merely typed
|
|
5469
|
+
* as "utf-8" would move or repeat its effects when the binding is erased. */
|
|
5470
|
+
function erasableTextCodecCtor(info) {
|
|
5471
|
+
const args = info.ctor.arguments ?? [];
|
|
5472
|
+
if (info.cls === "TextEncoder")
|
|
5473
|
+
return args.length === 0;
|
|
5474
|
+
if (args.length === 0)
|
|
5475
|
+
return true;
|
|
5476
|
+
if (args.length !== 1)
|
|
5477
|
+
return false;
|
|
5478
|
+
const label = stripTypeCasts(args[0]);
|
|
5479
|
+
return ts.isStringLiteralLike(label) && (label.text === "utf-8" || label.text === "utf8");
|
|
5480
|
+
}
|
|
5481
|
+
/** `const encoder = new TextEncoder()` / the default TextDecoder twin:
|
|
5482
|
+
* compile-time alias plumbing with no runtime object. Calls through the
|
|
5483
|
+
* stable binding are recognized by textCodecReceiverOf below; any other
|
|
5484
|
+
* reached value use keeps the ordinary SC2020 representation fence. Both
|
|
5485
|
+
* declaration walks call this and independently gate on constness. */
|
|
5486
|
+
export function textCodecBindingClassOf(L, nameNode, init) {
|
|
5487
|
+
if (!ts.isIdentifier(nameNode) || init === undefined)
|
|
5488
|
+
return null;
|
|
5489
|
+
const decl = nameNode.parent;
|
|
5490
|
+
if (!ts.isVariableDeclaration(decl) || !ts.isVariableDeclarationList(decl.parent) ||
|
|
5491
|
+
!ts.isVariableStatement(decl.parent.parent)) {
|
|
5492
|
+
return null;
|
|
5493
|
+
}
|
|
5494
|
+
const info = directTextCodecCtorOf(L, init);
|
|
5495
|
+
return info !== null && erasableTextCodecCtor(info) ? info.cls : null;
|
|
5496
|
+
}
|
|
5497
|
+
export function textCodecBindingDecl(L, nameNode, init) {
|
|
5498
|
+
return textCodecBindingClassOf(L, nameNode, init) !== null;
|
|
5499
|
+
}
|
|
5500
|
+
/** The inline composed receiver, or a const identifier whose initializer
|
|
5501
|
+
* is an erasable codec construction in the same execution scope and
|
|
5502
|
+
* after that declaration. Following the declaration instead of
|
|
5503
|
+
* materializing the value is honest for the supported slice: receiver
|
|
5504
|
+
* reads are pure, construction has no effects, and every non-call use
|
|
5505
|
+
* fences because there is deliberately no general value lowering. */
|
|
5506
|
+
function textCodecReceiverOf(L, expr) {
|
|
5507
|
+
const direct = directTextCodecCtorOf(L, expr);
|
|
5508
|
+
if (direct !== null)
|
|
5509
|
+
return direct;
|
|
5510
|
+
const receiver = stripTypeCasts(expr);
|
|
5511
|
+
if (!ts.isIdentifier(receiver))
|
|
5512
|
+
return null;
|
|
5513
|
+
const sym = L.resolveValueSymbol(receiver);
|
|
5514
|
+
const decl = sym ? L.checker.valueDeclarationOf(sym) : undefined;
|
|
5515
|
+
if (!decl || !ts.isVariableDeclaration(decl) || decl.initializer === undefined ||
|
|
5516
|
+
!ts.isVariableDeclarationList(decl.parent) || (decl.parent.flags & ts.NodeFlags.Const) === 0 ||
|
|
5517
|
+
!textCodecBindingDecl(L, decl.name, decl.initializer)) {
|
|
5518
|
+
return null;
|
|
5519
|
+
}
|
|
5520
|
+
// A closure can run before the const initializes (TDZ), and an
|
|
5521
|
+
// imported binding can be observed during a module cycle; both need
|
|
5522
|
+
// real runtime storage rather than this deliberately trivial rewrite.
|
|
5523
|
+
const executionScope = (node) => {
|
|
5524
|
+
let child = node;
|
|
5525
|
+
for (let cur = node.parent;; child = cur, cur = cur.parent) {
|
|
5526
|
+
if (ts.isFunctionLike(cur) || ts.isSourceFile(cur))
|
|
5527
|
+
return cur;
|
|
5528
|
+
// An instance field initializer runs when an object is constructed,
|
|
5529
|
+
// not when its enclosing class expression evaluates. Treat it like
|
|
5530
|
+
// a closure boundary: a later source position does not prove the
|
|
5531
|
+
// codec declaration ran (a switch can enter a following case and
|
|
5532
|
+
// instantiate the class while the binding is still in its TDZ).
|
|
5533
|
+
if (ts.isPropertyDeclaration(cur) && cur.initializer === child &&
|
|
5534
|
+
(ts.getCombinedModifierFlags(cur) & ts.ModifierFlags.Static) === 0) {
|
|
5535
|
+
return cur;
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
};
|
|
5539
|
+
if (executionScope(receiver) !== executionScope(decl) || receiver.getStart() < decl.end)
|
|
5540
|
+
return null;
|
|
5541
|
+
// All switch clauses share one lexical environment, but dispatch can
|
|
5542
|
+
// enter a later clause without executing a const in an earlier one.
|
|
5543
|
+
// TypeScript normally diagnoses the direct read; an @ts-expect-error
|
|
5544
|
+
// can deliberately retain the runtime TDZ shape, so source order alone
|
|
5545
|
+
// is not a sufficient proof. A codec declared in a clause is erasable
|
|
5546
|
+
// only for uses inside that exact clause's subtree (nested switches are
|
|
5547
|
+
// fine; closures and instance initializers already fail executionScope).
|
|
5548
|
+
const switchClauseOf = (node) => {
|
|
5549
|
+
for (let cur = node.parent; cur !== undefined; cur = cur.parent) {
|
|
5550
|
+
if (ts.isCaseClause(cur) || ts.isDefaultClause(cur))
|
|
5551
|
+
return cur;
|
|
5552
|
+
if (ts.isFunctionLike(cur) || ts.isSourceFile(cur))
|
|
5553
|
+
return null;
|
|
5554
|
+
}
|
|
5555
|
+
return null;
|
|
5556
|
+
};
|
|
5557
|
+
const declClause = switchClauseOf(decl);
|
|
5558
|
+
if (declClause !== null) {
|
|
5559
|
+
let insideDeclClause = false;
|
|
5560
|
+
for (let cur = receiver; cur !== undefined; cur = cur.parent) {
|
|
5561
|
+
if (cur === declClause) {
|
|
5562
|
+
insideDeclClause = true;
|
|
5563
|
+
break;
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
if (!insideDeclClause)
|
|
5567
|
+
return null;
|
|
5568
|
+
}
|
|
5569
|
+
return directTextCodecCtorOf(L, decl.initializer);
|
|
5570
|
+
}
|
|
5571
|
+
/** The WHATWG encoder pair, COMPOSED or through an erasable const binding:
|
|
5572
|
+
* `new TextDecoder().decode(bytes)`, `new TextEncoder().encode(s)`, and
|
|
5573
|
+
* the idiomatic store-then-call equivalents. The codec object never
|
|
5574
|
+
* exists (the crypto/Date precedent); bare construction and value uses
|
|
5575
|
+
* are fenced with the composed hint. decode is the runtime's WHATWG
|
|
5576
|
+
* utf-8 decode with the leading BOM stripped; a zero-argument decode()
|
|
5577
|
+
* is "" like the spec's. encode IS Buffer.from(s, "utf8") — ScrStr
|
|
5578
|
+
* storage is well-formed UTF-8, so the bytes are identical (lone
|
|
5428
5579
|
* surrogates became U+FFFD at string construction, exactly what the
|
|
5429
|
-
* spec's encoder emits). Null when this is neither
|
|
5580
|
+
* spec's encoder emits). Null when this is neither supported form. */
|
|
5430
5581
|
export function lowerTextCodecCall(L, call, access) {
|
|
5431
5582
|
if (call.questionDotToken || access.questionDotToken)
|
|
5432
5583
|
return null;
|
|
5433
5584
|
const member = access.name.text;
|
|
5434
5585
|
if (member !== "decode" && member !== "encode")
|
|
5435
5586
|
return null;
|
|
5436
|
-
const
|
|
5437
|
-
if (
|
|
5438
|
-
return null;
|
|
5439
|
-
const sym = L.resolveValueSymbol(recv.expression);
|
|
5440
|
-
const cls = sym?.name;
|
|
5441
|
-
if (!sym || !L.isStdlibSymbol(sym))
|
|
5587
|
+
const info = textCodecReceiverOf(L, access.expression);
|
|
5588
|
+
if (info === null || !L.isStdlibMember(access))
|
|
5442
5589
|
return null;
|
|
5590
|
+
const { cls, ctor: recv } = info;
|
|
5443
5591
|
if (!(cls === "TextDecoder" && member === "decode") && !(cls === "TextEncoder" && member === "encode")) {
|
|
5444
5592
|
return null;
|
|
5445
5593
|
}
|