@scriptc/compiler 0.1.2 → 0.1.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 +258 -64
- package/dist/backend/c/async.d.ts +30 -0
- package/dist/backend/c/async.js +224 -0
- package/dist/backend/c/async.js.map +1 -1
- package/dist/backend/c/c-emitter.d.ts +13 -0
- package/dist/backend/c/c-emitter.js +28 -9
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.d.ts +8 -1
- package/dist/backend/c/exprs.js +445 -60
- package/dist/backend/c/exprs.js.map +1 -1
- package/dist/backend/c/shapes.js +15 -13
- package/dist/backend/c/shapes.js.map +1 -1
- package/dist/backend/c/types.d.ts +4 -0
- package/dist/backend/c/types.js +20 -1
- package/dist/backend/c/types.js.map +1 -1
- package/dist/backend/c/types.test.js +8 -1
- package/dist/backend/c/types.test.js.map +1 -1
- package/dist/backend/c/walkers.js +32 -11
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/json-literal.d.ts +7 -0
- package/dist/backend/json-literal.js +17 -0
- package/dist/backend/json-literal.js.map +1 -0
- package/dist/backend/json-literal.test.d.ts +1 -0
- package/dist/backend/json-literal.test.js +17 -0
- package/dist/backend/json-literal.test.js.map +1 -0
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js +6 -1
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/classes.js +8 -7
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +4 -0
- package/dist/backend/llvm/common.js +6 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/common.test.d.ts +1 -0
- package/dist/backend/llvm/common.test.js +9 -0
- package/dist/backend/llvm/common.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +4 -0
- package/dist/backend/llvm/dyn.js +24 -13
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +54 -12
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +8 -8
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +9 -0
- package/dist/backend/llvm/expr-callbacks.js +125 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +18 -2
- package/dist/backend/llvm/expr-dispatch.js +1 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +9 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +38 -9
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.d.ts +1 -0
- package/dist/backend/llvm/expr-primitives.test.js +38 -0
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -0
- package/dist/backend/llvm/expr-records.js +3 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +2 -1
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +6 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +122 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +22 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +68 -10
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +18 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +206 -11
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +82 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +23 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/shapes.js +10 -8
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/walkers.js +7 -5
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js +4 -0
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +24 -1
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +11 -6
- package/dist/backend/native-toolchain.js +30 -13
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +36 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +29 -10
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/targets.d.ts +9 -0
- package/dist/backend/targets.js +22 -0
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +13 -1
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/coverage/surface-manifest.js +9 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +4 -4
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -0
- package/dist/executable/executable-cache.js +4 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +1 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/fork-target.d.ts +17 -0
- package/dist/frontend/fork-target.js +256 -0
- package/dist/frontend/fork-target.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +6 -0
- package/dist/frontend/lowering/abstract-equality.js +250 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +0 -4
- package/dist/frontend/lowering/containers/bytes.js +112 -28
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +87 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +72 -44
- package/dist/frontend/lowering/lower-builtins.js +1323 -165
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +37 -27
- package/dist/frontend/lowering/lower-calls.js +682 -132
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +39 -8
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +162 -8
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +212 -21
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +238 -87
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +4 -0
- package/dist/frontend/lowering/lower-inspect.js +8 -1
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +6 -3
- package/dist/frontend/lowering/lower-island.js +165 -6
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +6 -0
- package/dist/frontend/lowering/lower-modules.js +192 -38
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.js +7 -0
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +130 -27
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +5 -4
- package/dist/frontend/lowering/lower-stmts.js +141 -21
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +3 -0
- package/dist/frontend/lowering/lower-stream.js +7 -0
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +90 -13
- package/dist/frontend/lowering/lowerer.js +416 -76
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +31 -3
- package/dist/frontend/lowering/surfaces.js +173 -90
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-declarations.d.ts +4 -0
- package/dist/frontend/npm-static-declarations.js +83 -14
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +33 -2
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static.js +6 -5
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +15 -3
- package/dist/frontend/npm.js +80 -8
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +76 -9
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/program.js +110 -12
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +28 -7
- package/dist/frontend/resolve.js +90 -26
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +21 -1
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +5 -0
- package/dist/frontend/type-mapper.js +115 -33
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +30 -3
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +1 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +155 -66
- package/dist/ir/ir.js +143 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +14 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.js +242 -18
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/library-cache.d.ts +1 -0
- package/dist/library/library-cache.js +1 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +18 -5
- package/dist/library/library-cache.test.js.map +1 -1
- package/package.json +17 -17
- package/surface-manifest.json +163 -54
|
@@ -9,7 +9,7 @@ import * as ts from "../ts7/adapter.js";
|
|
|
9
9
|
import { dirname, posix } from "node:path";
|
|
10
10
|
import { pathToFileURL } from "node:url";
|
|
11
11
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
12
|
-
import { BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, JSVAL, NULL_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_ERROR_CLASSES, SEARCH_PARAMS_T, STRING, UNDEFINED_T, VOID, arrayOf, canAdaptDynFuncTo, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isJsonSafeType, isSupportedArrayElem, isUnitType, jsOpResultKind, shapeHasAccessorSlots, typeEquals, typeKey, unionFuncSetArmsOk } from "../../ir/ir.js";
|
|
12
|
+
import { BIGINT_T, BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, JSVAL, NULL_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_ERROR_CLASSES, SEARCH_PARAMS_T, STRING, UNDEFINED_T, VOID, arrayOf, canAdaptDynFuncTo, canBoxFuncIntoDyn, funcOf, isDynTypedRefType, isJsonSafeType, isSupportedArrayElem, isUnitType, jsOpResultKind, shapeHasAccessorSlots, typeEquals, typeKey, unionFuncSetArmsOk } from "../../ir/ir.js";
|
|
13
13
|
import { cjsClassExprWholeExportOf, cjsExportAssignmentOf, cjsExportDiscardReason, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeEsmFile, locOf } from "../program.js";
|
|
14
14
|
import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, ISLAND_SURFACE, isChildSurfaceMember, MAP_METHODS, NARROW_FIRST, SET_METHODS, STR_METHODS, UNSUPPORTED_EXPR, sideEffectFreeOptionValue, stdlibGlobalNameOf } from "./surfaces.js";
|
|
15
15
|
import { blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag } from "../../diagnostics/diagnostic.js";
|
|
@@ -23,7 +23,7 @@ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUn
|
|
|
23
23
|
import { expandoMemberRead, expandoWritableTarget } from "./lower-expando.js";
|
|
24
24
|
import { lowerSocketInstanceOf, lowerTlsRootCertificates } from "./lower-server.js";
|
|
25
25
|
import { findGenericMethodOn, lowerStaticFieldRead } from "./lower-classes.js";
|
|
26
|
-
import { bindingNeverReassigned, implicitMonoFile, lowerTaggedTemplate, nullishGenericBindingUnitOf, objLitGenericFnInfoOf, objLitGenericFnNodeOf, requireObjLitGenericReceiver } from "./lower-calls.js";
|
|
26
|
+
import { bindingNeverReassigned, funcTypeFromParamShapes, implicitMonoFile, lowerTaggedTemplate, nullishGenericBindingUnitOf, objLitGenericFnInfoOf, objLitGenericFnNodeOf, requireObjLitGenericReceiver } from "./lower-calls.js";
|
|
27
27
|
import { mixinFnOfCallee } from "./lower-mixins.js";
|
|
28
28
|
import { isConstAssertionTypeNode, isGenericCallableMemberType, isParseArgsDynTypeName, underConstAssertion, unitOnlyUnion } from "../type-mapper.js";
|
|
29
29
|
import { lowerYield } from "./lower-generators.js";
|
|
@@ -34,6 +34,7 @@ import { hasOptionalChainGuard, isOptionalChainTail, isRequireMainFilename } fro
|
|
|
34
34
|
import { conditionalSpreadOf, foldedStringKeyOf } from "./expressions/object-literals.js";
|
|
35
35
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
36
36
|
import { fenceNodeModuleMutation, isNodeModuleValue, lowerNodeModuleIdentifier, lowerNodeModuleProperty, lowerRequireCacheElement, lowerRequireCacheHas, lowerRequireMainProperty } from "./lower-node-module.js";
|
|
37
|
+
import { lowerAbstractEquality } from "./abstract-equality.js";
|
|
37
38
|
/** A template piece's RAW text (String.raw's contract: escapes stay
|
|
38
39
|
* characters). 7's client AST ships no rawText at runtime (the typing
|
|
39
40
|
* declares it; the serialized node data omits it), so the raw span comes
|
|
@@ -143,6 +144,16 @@ function lowerExprInner(lowerer, expr) {
|
|
|
143
144
|
}
|
|
144
145
|
return { kind: "numLit", value, type: F64, loc };
|
|
145
146
|
}
|
|
147
|
+
if (ts.isBigIntLiteral(expr)) {
|
|
148
|
+
const spelling = expr.getText().replace(/_/g, "").replace(/n$/i, "");
|
|
149
|
+
return {
|
|
150
|
+
kind: "libCall",
|
|
151
|
+
fn: "bigint.parse",
|
|
152
|
+
args: [{ kind: "strLit", value: spelling, type: STRING, loc }],
|
|
153
|
+
type: BIGINT_T,
|
|
154
|
+
loc,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
146
157
|
if (expr.kind === ts.SyntaxKind.TrueKeyword) {
|
|
147
158
|
return { kind: "boolLit", value: true, type: BOOL, loc };
|
|
148
159
|
}
|
|
@@ -583,11 +594,12 @@ function lowerExprInner(lowerer, expr) {
|
|
|
583
594
|
operand = operand.value;
|
|
584
595
|
}
|
|
585
596
|
const FOLD = {
|
|
586
|
-
f64: "number", string: "string", bool: "boolean", func: "function",
|
|
597
|
+
f64: "number", bigint: "bigint", string: "string", bool: "boolean", func: "function",
|
|
587
598
|
array: "object", object: "object", record: "object",
|
|
588
599
|
symbol: "symbol",
|
|
589
600
|
map: "object", set: "object", promise: "object", bytes: "object",
|
|
590
601
|
regexp: "object", generator: "object", classval: "function",
|
|
602
|
+
moduleNs: "object",
|
|
591
603
|
undefinedT: "undefined", nullT: "object",
|
|
592
604
|
};
|
|
593
605
|
const folded = FOLD[operand.type.kind];
|
|
@@ -639,13 +651,22 @@ function lowerExprInner(lowerer, expr) {
|
|
|
639
651
|
if (expr.text === "arguments" && lowerer.ctx.argumentsLocal) {
|
|
640
652
|
return { kind: "varRef", localId: lowerer.ctx.argumentsLocal.id, type: DYN, loc };
|
|
641
653
|
}
|
|
642
|
-
// A
|
|
643
|
-
//
|
|
644
|
-
//
|
|
654
|
+
// A compiler-projected adapter as a VALUE: the adapter has no
|
|
655
|
+
// runtime function object (its calls rewrite directly) — call it
|
|
656
|
+
// through its immutable binding instead.
|
|
645
657
|
{
|
|
646
658
|
const sym = lowerer.resolveValueSymbol(expr);
|
|
647
|
-
|
|
648
|
-
|
|
659
|
+
const projection = sym ? lowerer.staticCallables.get(sym) : undefined;
|
|
660
|
+
if (projection?.kind === "promisified-exec-file" || projection?.kind === "promisified-builtin") {
|
|
661
|
+
lowerer.unsupported("SC1090", expr, `a promisified builtin as a value (call '${expr.text}' directly)`);
|
|
662
|
+
}
|
|
663
|
+
if (projection?.kind === "builtin-function") {
|
|
664
|
+
if (!isJsSourceFile(expr.getSourceFile())) {
|
|
665
|
+
const callable = lowerer.lowerBuiltinCallableValue(projection, loc);
|
|
666
|
+
if (callable)
|
|
667
|
+
return callable;
|
|
668
|
+
}
|
|
669
|
+
lowerer.unsupported("SC1090", expr, `a builtin function alias as an escaping value (call '${expr.text}' directly)`);
|
|
649
670
|
}
|
|
650
671
|
}
|
|
651
672
|
// Union-typed bindings read through tsc's control-flow narrowing:
|
|
@@ -799,17 +820,12 @@ function lowerExprInner(lowerer, expr) {
|
|
|
799
820
|
if (sig && lowerer.isTopLevelFnSymbol(expr)) {
|
|
800
821
|
// A declared function used as a value: a zero-capture closure. The
|
|
801
822
|
// backend interns one per function so `f === f` holds (JS identity).
|
|
802
|
-
// The value's type is the completed ABI signature
|
|
803
|
-
//
|
|
823
|
+
// The value's type is the completed ABI signature; optional/default
|
|
824
|
+
// slots and typed rest arrays pass the value fence first.
|
|
804
825
|
lowerer.noteEdge(sig.name);
|
|
805
826
|
// dynRest slots stay out of the VALUE type's param list (fn.length
|
|
806
827
|
// semantics); the rest marker carries the trailing dyn-array ABI.
|
|
807
|
-
const funcType =
|
|
808
|
-
kind: "func",
|
|
809
|
-
params: sig.params.filter((p) => p.mode !== "dynRest").map((p) => p.type),
|
|
810
|
-
ret: sig.returnType,
|
|
811
|
-
...(sig.params.some((p) => p.mode === "dynRest") ? { rest: true } : {}),
|
|
812
|
-
};
|
|
828
|
+
const funcType = funcTypeFromParamShapes(sig.params, sig.returnType);
|
|
813
829
|
lowerer.requireExactArityValue(expr, expr, sig.params, funcType);
|
|
814
830
|
return { kind: "closure", fnName: sig.name, captures: [], type: funcType, loc };
|
|
815
831
|
}
|
|
@@ -869,6 +885,11 @@ function lowerExprInner(lowerer, expr) {
|
|
|
869
885
|
if (isJsSourceFile(expr.getSourceFile())) {
|
|
870
886
|
return { kind: "strLit", value: `[builtin ${bi.module}.${bi.member}]`, type: STRING, loc };
|
|
871
887
|
}
|
|
888
|
+
{
|
|
889
|
+
const callable = lowerer.lowerBuiltinCallableValue(bi, loc);
|
|
890
|
+
if (callable)
|
|
891
|
+
return callable;
|
|
892
|
+
}
|
|
872
893
|
if (builtinModuleFnOf(lowerer, bi.module, bi.member)) {
|
|
873
894
|
lowerer.unsupported("SC1090", expr, `library functions as values (call '${expr.text}' directly)`);
|
|
874
895
|
}
|
|
@@ -879,7 +900,12 @@ function lowerExprInner(lowerer, expr) {
|
|
|
879
900
|
// the namespace object has no representation — members lower at
|
|
880
901
|
// their access sites only. The CommonJS namespace binding
|
|
881
902
|
// (`const lib = require("./lib.js")`) gets the same fence.
|
|
882
|
-
|
|
903
|
+
const builtinNamespace = lowerer.builtinNamespaceModuleOf(expr);
|
|
904
|
+
if (builtinNamespace !== null) {
|
|
905
|
+
const type = { kind: "moduleNs", moduleId: `builtin:${builtinNamespace}` };
|
|
906
|
+
return { kind: "moduleNsRef", moduleId: type.moduleId, type, loc };
|
|
907
|
+
}
|
|
908
|
+
if (lowerer.cjsLocalModuleBindingOf(expr)) {
|
|
883
909
|
lowerer.unsupported("SC1090", expr, `module namespace objects as values (access '${expr.text}' members directly)`);
|
|
884
910
|
}
|
|
885
911
|
if (lowerer.islandGlobalFnOf(expr)) {
|
|
@@ -931,11 +957,14 @@ function lowerExprInner(lowerer, expr) {
|
|
|
931
957
|
// type-mapper.ts pins the one concrete signature `(value: string) =>
|
|
932
958
|
// primitive`; direct calls `String(x)` never reach here — the call
|
|
933
959
|
// lowering intercepts them with the wider static coercions).
|
|
934
|
-
|
|
960
|
+
const jsPrimitiveCtorSelector = isJsSourceFile(expr.getSourceFile()) &&
|
|
961
|
+
expr.parent !== undefined &&
|
|
962
|
+
ts.isArrowFunction(expr.parent) &&
|
|
963
|
+
expr.parent.body === expr;
|
|
935
964
|
if ((expr.text === "String" || expr.text === "Number" || expr.text === "Boolean") &&
|
|
936
|
-
!isJsSourceFile(expr.getSourceFile()) &&
|
|
965
|
+
(!isJsSourceFile(expr.getSourceFile()) || jsPrimitiveCtorSelector) &&
|
|
937
966
|
lowerer.isStdlibSymbol(lowerer.checker.getSymbolAtLocation(expr))) {
|
|
938
|
-
return primitiveCtorClosure(lowerer, expr.text, loc);
|
|
967
|
+
return primitiveCtorClosure(lowerer, expr.text, loc, jsPrimitiveCtorSelector);
|
|
939
968
|
}
|
|
940
969
|
// The lib fence's IDENTIFIER chokepoint: the real standard library
|
|
941
970
|
// resolves names the old minimal ambient world never declared
|
|
@@ -960,7 +989,6 @@ function lowerExprInner(lowerer, expr) {
|
|
|
960
989
|
// The families with a WHY: each hint states what makes the
|
|
961
990
|
// surface genuinely non-static (or what to use instead).
|
|
962
991
|
const globalHints = {
|
|
963
|
-
BigInt: "arbitrary-precision integers have no static representation — f64 is the one number type (Number.MAX_SAFE_INTEGER bounds exact integers)",
|
|
964
992
|
Proxy: "property-access metaprogramming has no static lowering (every property read must resolve at compile time)",
|
|
965
993
|
Reflect: "reflective property access has no static lowering — read and call members directly",
|
|
966
994
|
Intl: "locale- and ICU-backed behavior lives outside the static runtime (the localeCompare stance: code-unit order, no collation/locale data) — what lowers: the composed new Intl.NumberFormat(\"en-US\").format(x) and x.toLocaleString(\"en-US\") with default options",
|
|
@@ -1072,6 +1100,15 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1072
1100
|
// representation (ambient namespaces compile to Node's
|
|
1073
1101
|
// ReferenceError instead — the object never exists at runtime).
|
|
1074
1102
|
{
|
|
1103
|
+
const moduleNs = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
1104
|
+
if (moduleNs?.kind === "moduleNs") {
|
|
1105
|
+
return { kind: "moduleNsRef", moduleId: moduleNs.moduleId, type: moduleNs, loc };
|
|
1106
|
+
}
|
|
1107
|
+
const builtinNs = lowerer.builtinNamespaceModuleOf(expr);
|
|
1108
|
+
if (builtinNs !== null) {
|
|
1109
|
+
const type = { kind: "moduleNs", moduleId: `builtin:${builtinNs}` };
|
|
1110
|
+
return { kind: "moduleNsRef", moduleId: type.moduleId, type, loc };
|
|
1111
|
+
}
|
|
1075
1112
|
const ns = lowerNsIdentifierValue(lowerer, expr);
|
|
1076
1113
|
if (ns)
|
|
1077
1114
|
return ns;
|
|
@@ -2957,6 +2994,9 @@ export function ensureBool(lowerer, e, node) {
|
|
|
2957
2994
|
if (e.type.kind === "f64" || e.type.kind === "string") {
|
|
2958
2995
|
return { kind: "toBool", operand: e, type: BOOL, loc: e.loc };
|
|
2959
2996
|
}
|
|
2997
|
+
if (e.type.kind === "bigint") {
|
|
2998
|
+
return { kind: "libCall", fn: "bigint.truthy", args: [e], type: BOOL, loc: e.loc };
|
|
2999
|
+
}
|
|
2960
3000
|
if (e.type.kind === "dyn") {
|
|
2961
3001
|
// ToBoolean over the checked-dynamic tree (`if (pkg)` on a JSON.parse result): every
|
|
2962
3002
|
// dyn kind has a JS-exact answer — the truthy dynTest reads the kind
|
|
@@ -3072,10 +3112,10 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3072
3112
|
const receiver = lowerer.lowerExpr(expr.expression);
|
|
3073
3113
|
return { kind: "libCall", fn: "child.killed", args: [receiver], type: BOOL, loc };
|
|
3074
3114
|
}
|
|
3075
|
-
if (name === "on" || name === "kill" || name === "unref") {
|
|
3115
|
+
if (name === "on" || name === "once" || name === "kill" || name === "unref") {
|
|
3076
3116
|
lowerer.unsupported("SC1090", expr, `child methods as values (call '${name}' directly)`);
|
|
3077
3117
|
}
|
|
3078
|
-
lowerer.noLowering(`ChildProcess.${name}`, expr, "on(\"exit\" | \"error\", cb), pid, exitCode, killed, kill(signal?), and unref() are the supported ChildProcess members", lowerer.checker.getSymbolAtLocation(expr.name));
|
|
3118
|
+
lowerer.noLowering(`ChildProcess.${name}`, expr, "on/once(\"exit\" | \"close\" | \"error\", cb), pid, exitCode, killed, kill(signal?), and unref() are the supported ChildProcess members", lowerer.checker.getSymbolAtLocation(expr.name));
|
|
3079
3119
|
}
|
|
3080
3120
|
if (kind === "spawnRes") {
|
|
3081
3121
|
// The spawnSync-result reads. status is the interned `number | null`
|
|
@@ -3125,7 +3165,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3125
3165
|
if (name === "isFile" || name === "isDirectory") {
|
|
3126
3166
|
lowerer.unsupported("SC1090", expr, `Stats methods as values (call '${name}' directly)`);
|
|
3127
3167
|
}
|
|
3128
|
-
lowerer.noLowering(`Stats.${name}`, expr, "isFile(), isDirectory(), isSymbolicLink(), size, blocks, nlink, atimeMs, and
|
|
3168
|
+
lowerer.noLowering(`Stats.${name}`, expr, "isFile(), isDirectory(), isSymbolicLink(), dev, ino, size, blocks, nlink, atimeMs, mtimeMs, and ctimeMs are the supported Stats members", lowerer.checker.getSymbolAtLocation(expr.name));
|
|
3129
3169
|
}
|
|
3130
3170
|
if (kind === "date") {
|
|
3131
3171
|
const methods = new Set([
|
|
@@ -3166,22 +3206,30 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3166
3206
|
// serialization: lowercased hostname, `:port` appended exactly when
|
|
3167
3207
|
// a non-default port is present (scr_url_host — Node-exact,
|
|
3168
3208
|
// opaque-path URLs answer ""); `hostname` is the stored port-less
|
|
3169
|
-
// host field verbatim
|
|
3170
|
-
|
|
3171
|
-
// never sees one).
|
|
3172
|
-
if (name === "protocol" || name === "pathname" || name === "href" || name === "host" || name === "hostname" || name === "search") {
|
|
3209
|
+
// host field verbatim, including IPv6 brackets.
|
|
3210
|
+
if (name === "protocol" || name === "origin" || name === "username" || name === "password" || name === "pathname" || name === "href" || name === "host" || name === "hostname" || name === "port" || name === "search" || name === "hash") {
|
|
3173
3211
|
const receiver = lowerer.lowerExpr(expr.expression);
|
|
3174
3212
|
const fn = name === "protocol"
|
|
3175
3213
|
? "url.protocol"
|
|
3176
|
-
: name === "
|
|
3177
|
-
? "url.
|
|
3178
|
-
: name === "
|
|
3179
|
-
? "url.
|
|
3180
|
-
: name === "
|
|
3181
|
-
? "url.
|
|
3182
|
-
: name === "
|
|
3183
|
-
? "url.
|
|
3184
|
-
: "
|
|
3214
|
+
: name === "origin"
|
|
3215
|
+
? "url.origin"
|
|
3216
|
+
: name === "username"
|
|
3217
|
+
? "url.username"
|
|
3218
|
+
: name === "password"
|
|
3219
|
+
? "url.password"
|
|
3220
|
+
: name === "pathname"
|
|
3221
|
+
? "url.pathname"
|
|
3222
|
+
: name === "host"
|
|
3223
|
+
? "url.host"
|
|
3224
|
+
: name === "hostname"
|
|
3225
|
+
? "url.hostname"
|
|
3226
|
+
: name === "port"
|
|
3227
|
+
? "url.port"
|
|
3228
|
+
: name === "search"
|
|
3229
|
+
? "url.search"
|
|
3230
|
+
: name === "hash"
|
|
3231
|
+
? "url.hash"
|
|
3232
|
+
: "url.href";
|
|
3185
3233
|
return { kind: "libCall", fn, args: [receiver], type: STRING, loc: locOf(expr) };
|
|
3186
3234
|
}
|
|
3187
3235
|
// `u.searchParams`: the LIVE cached view (one identity per URL —
|
|
@@ -3194,7 +3242,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3194
3242
|
if (name === "toString" || name === "toJSON") {
|
|
3195
3243
|
lowerer.unsupported("SC1090", expr, `URL methods as values (call '${name}' directly)`);
|
|
3196
3244
|
}
|
|
3197
|
-
lowerer.noLowering(`URL.${name}`, expr, "protocol, pathname, href, host, hostname, search, searchParams, and toString() are the supported URL members", lowerer.checker.getSymbolAtLocation(expr.name));
|
|
3245
|
+
lowerer.noLowering(`URL.${name}`, expr, "protocol, origin, username, password, pathname, href, host, hostname, port, search, hash, searchParams, and toString() are the supported URL members", lowerer.checker.getSymbolAtLocation(expr.name));
|
|
3198
3246
|
}
|
|
3199
3247
|
if (kind === "searchParams") {
|
|
3200
3248
|
const SEARCH_PARAMS_METHODS = new Set(["get", "getAll", "set", "append", "delete", "has", "sort", "toString", "forEach", "keys", "values", "entries"]);
|
|
@@ -4863,6 +4911,15 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
4863
4911
|
export function ensureString(lowerer, e, node) {
|
|
4864
4912
|
if (e.type.kind === "string")
|
|
4865
4913
|
return e;
|
|
4914
|
+
if (e.type.kind === "bigint") {
|
|
4915
|
+
return {
|
|
4916
|
+
kind: "libCall",
|
|
4917
|
+
fn: "bigint.toString",
|
|
4918
|
+
args: [e, { kind: "numLit", value: 10, type: F64, loc: e.loc }],
|
|
4919
|
+
type: STRING,
|
|
4920
|
+
loc: e.loc,
|
|
4921
|
+
};
|
|
4922
|
+
}
|
|
4866
4923
|
if (e.type.kind === "dyn") {
|
|
4867
4924
|
// String(u) / `${u}`: a runtime dispatch over the dyn kind — Node's
|
|
4868
4925
|
// String() exactly (undefined/null texts, JS number formatting,
|
|
@@ -4892,7 +4949,7 @@ export function ensureString(lowerer, e, node) {
|
|
|
4892
4949
|
// JS would print "[object Object]" and friends — narrow first.
|
|
4893
4950
|
const def = lowerer.unions.get(e.type.unionId);
|
|
4894
4951
|
const stringable = def?.arms.every((a) => a.kind === "undefinedT" || a.kind === "nullT" ||
|
|
4895
|
-
a.kind === "string" || a.kind === "f64" || a.kind === "bool");
|
|
4952
|
+
a.kind === "string" || a.kind === "f64" || a.kind === "bigint" || a.kind === "bool");
|
|
4896
4953
|
if (stringable) {
|
|
4897
4954
|
return { kind: "toString", operand: e, type: STRING, loc: e.loc };
|
|
4898
4955
|
}
|
|
@@ -5171,6 +5228,9 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
5171
5228
|
if (raw.type.kind === "jsval") {
|
|
5172
5229
|
return { kind: "jsOp", op: "neg", args: [raw], type: JSVAL, loc };
|
|
5173
5230
|
}
|
|
5231
|
+
if (raw.type.kind === "bigint") {
|
|
5232
|
+
return { kind: "libCall", fn: "bigint.neg", args: [raw], type: BIGINT_T, loc };
|
|
5233
|
+
}
|
|
5174
5234
|
const operand = lowerOptionalNumber(lowerer, raw, loc, expr.operand);
|
|
5175
5235
|
if (operand.type.kind !== "f64")
|
|
5176
5236
|
lowerer.unsupported("SC1043", expr);
|
|
@@ -5201,7 +5261,18 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
5201
5261
|
}
|
|
5202
5262
|
case ts.SyntaxKind.TildeToken: {
|
|
5203
5263
|
// `~x`: ToInt32, complement, back to f64 (JS-exact, incl. NaN → -1).
|
|
5204
|
-
const
|
|
5264
|
+
const raw = lowerer.lowerExpr(expr.operand);
|
|
5265
|
+
if (raw.type.kind === "bigint") {
|
|
5266
|
+
return { kind: "libCall", fn: "bigint.not", args: [raw], type: BIGINT_T, loc };
|
|
5267
|
+
}
|
|
5268
|
+
// A checked-dynamic value retains enough JavaScript structure to
|
|
5269
|
+
// run exact ToNumber, including the object valueOf/toString
|
|
5270
|
+
// protocol. This is the static `any`/JS-lane answer for idioms
|
|
5271
|
+
// such as `while (~index)`, where inference may have widened an
|
|
5272
|
+
// otherwise numeric slot to the checked-dynamic tree.
|
|
5273
|
+
const operand = raw.type.kind === "dyn"
|
|
5274
|
+
? { kind: "libCall", fn: "dyn.toNumberCoerce", args: [raw], type: F64, loc }
|
|
5275
|
+
: lowerOptionalNumber(lowerer, raw, loc, expr.operand);
|
|
5205
5276
|
if (operand.type.kind !== "f64")
|
|
5206
5277
|
lowerer.unsupported("SC1043", expr);
|
|
5207
5278
|
return { kind: "unary", op: "~", operand, type: F64, loc };
|
|
@@ -5490,23 +5561,10 @@ export function lowerBinary(lowerer, expr) {
|
|
|
5490
5561
|
const nullTest = lowerLooseNullCompare(lowerer, expr, loc);
|
|
5491
5562
|
if (nullTest)
|
|
5492
5563
|
return nullTest;
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
{
|
|
5498
|
-
const negated = op === ts.SyntaxKind.ExclamationEqualsToken;
|
|
5499
|
-
const left = lowerer.lowerExpr(expr.left);
|
|
5500
|
-
const right = lowerer.lowerExpr(expr.right);
|
|
5501
|
-
if (left.type.kind === "string" && right.type.kind === "string") {
|
|
5502
|
-
return { kind: "strEq", negated, left, right, type: BOOL, loc };
|
|
5503
|
-
}
|
|
5504
|
-
if ((left.type.kind === "f64" && right.type.kind === "f64") ||
|
|
5505
|
-
(left.type.kind === "bool" && right.type.kind === "bool")) {
|
|
5506
|
-
return { kind: "bin", op: negated ? "!==" : "===", left, right, type: BOOL, loc };
|
|
5507
|
-
}
|
|
5508
|
-
}
|
|
5509
|
-
lowerer.unsupported("SC1040", expr);
|
|
5564
|
+
const loose = lowerAbstractEquality(lowerer, lowerer.lowerExpr(expr.left), lowerer.lowerExpr(expr.right), op === ts.SyntaxKind.ExclamationEqualsToken, loc);
|
|
5565
|
+
if (loose)
|
|
5566
|
+
return loose;
|
|
5567
|
+
lowerer.unsupported("SC1040", expr, undefined, "object-to-primitive loose equality can call user-defined valueOf/toString methods — compare explicit primitive conversions instead");
|
|
5510
5568
|
}
|
|
5511
5569
|
if (op === ts.SyntaxKind.AmpersandAmpersandToken || op === ts.SyntaxKind.BarBarToken) {
|
|
5512
5570
|
if (op === ts.SyntaxKind.BarBarToken) {
|
|
@@ -5530,6 +5588,15 @@ export function lowerBinary(lowerer, expr) {
|
|
|
5530
5588
|
if (left.kind === "unitLit") {
|
|
5531
5589
|
return op === ts.SyntaxKind.BarBarToken ? right : left;
|
|
5532
5590
|
}
|
|
5591
|
+
// JS objects and symbols are always truthy. In `ref || fallback`
|
|
5592
|
+
// the fallback is therefore unreachable and the result is the
|
|
5593
|
+
// already-evaluated left value — the browser-fallback idiom used by
|
|
5594
|
+
// packages for `process.argv || []` and `process.env || {}`. The
|
|
5595
|
+
// operand itself remains in the IR, preserving reads/calls that
|
|
5596
|
+
// produce the reference; only the unreachable right lowering drops.
|
|
5597
|
+
if (op === ts.SyntaxKind.BarBarToken && REF_TRUTHY_KINDS.has(left.type.kind)) {
|
|
5598
|
+
return left;
|
|
5599
|
+
}
|
|
5533
5600
|
if (left.type.kind === "dyn" || right.type.kind === "dyn") {
|
|
5534
5601
|
// A checked-dynamic operand (`fn.name || '<anonymous>'` —
|
|
5535
5602
|
// test/common's _mustCallInner): both sides live in the checked-dynamic tree and
|
|
@@ -5877,6 +5944,73 @@ export function lowerBinary(lowerer, expr) {
|
|
|
5877
5944
|
if (left.type.kind === "jsval" || right.type.kind === "jsval") {
|
|
5878
5945
|
return lowerAnyBinaryInIsland(lowerer, expr, left, right, loc);
|
|
5879
5946
|
}
|
|
5947
|
+
if (left.type.kind === "bigint" && right.type.kind === "bigint") {
|
|
5948
|
+
const binary = {
|
|
5949
|
+
[ts.SyntaxKind.PlusToken]: "bigint.add",
|
|
5950
|
+
[ts.SyntaxKind.MinusToken]: "bigint.sub",
|
|
5951
|
+
[ts.SyntaxKind.AsteriskToken]: "bigint.mul",
|
|
5952
|
+
[ts.SyntaxKind.SlashToken]: "bigint.div",
|
|
5953
|
+
[ts.SyntaxKind.PercentToken]: "bigint.mod",
|
|
5954
|
+
[ts.SyntaxKind.AsteriskAsteriskToken]: "bigint.pow",
|
|
5955
|
+
[ts.SyntaxKind.AmpersandToken]: "bigint.and",
|
|
5956
|
+
[ts.SyntaxKind.BarToken]: "bigint.or",
|
|
5957
|
+
[ts.SyntaxKind.CaretToken]: "bigint.xor",
|
|
5958
|
+
[ts.SyntaxKind.LessThanLessThanToken]: "bigint.shl",
|
|
5959
|
+
[ts.SyntaxKind.GreaterThanGreaterThanToken]: "bigint.shr",
|
|
5960
|
+
};
|
|
5961
|
+
const fn = binary[op];
|
|
5962
|
+
if (fn)
|
|
5963
|
+
return { kind: "libCall", fn, args: [left, right], type: BIGINT_T, loc };
|
|
5964
|
+
if (op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
5965
|
+
op === ts.SyntaxKind.ExclamationEqualsEqualsToken) {
|
|
5966
|
+
const equal = { kind: "libCall", fn: "bigint.eq", args: [left, right], type: BOOL, loc };
|
|
5967
|
+
return op === ts.SyntaxKind.ExclamationEqualsEqualsToken
|
|
5968
|
+
? { kind: "unary", op: "!", operand: equal, type: BOOL, loc }
|
|
5969
|
+
: equal;
|
|
5970
|
+
}
|
|
5971
|
+
if (op === ts.SyntaxKind.LessThanToken || op === ts.SyntaxKind.LessThanEqualsToken ||
|
|
5972
|
+
op === ts.SyntaxKind.GreaterThanToken || op === ts.SyntaxKind.GreaterThanEqualsToken) {
|
|
5973
|
+
const cmp = { kind: "libCall", fn: "bigint.cmp", args: [left, right], type: F64, loc };
|
|
5974
|
+
const zero = { kind: "numLit", value: 0, type: F64, loc };
|
|
5975
|
+
const cmpOp = op === ts.SyntaxKind.LessThanToken ? "<"
|
|
5976
|
+
: op === ts.SyntaxKind.LessThanEqualsToken ? "<="
|
|
5977
|
+
: op === ts.SyntaxKind.GreaterThanToken ? ">" : ">=";
|
|
5978
|
+
return { kind: "bin", op: cmpOp, left: cmp, right: zero, type: BOOL, loc };
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5981
|
+
if ((left.type.kind === "bigint" && right.type.kind === "f64") ||
|
|
5982
|
+
(left.type.kind === "f64" && right.type.kind === "bigint")) {
|
|
5983
|
+
if (op === ts.SyntaxKind.LessThanToken || op === ts.SyntaxKind.LessThanEqualsToken ||
|
|
5984
|
+
op === ts.SyntaxKind.GreaterThanToken || op === ts.SyntaxKind.GreaterThanEqualsToken) {
|
|
5985
|
+
const big = left.type.kind === "bigint" ? left : right;
|
|
5986
|
+
const num = left.type.kind === "f64" ? left : right;
|
|
5987
|
+
const cmp = { kind: "libCall", fn: "bigint.cmpNumber", args: [big, num], type: F64, loc };
|
|
5988
|
+
const cmpLocal = lowerer.declareHiddenLocal("%bigcmp", F64);
|
|
5989
|
+
const cmpRef = { kind: "varRef", localId: cmpLocal.id, type: F64, loc };
|
|
5990
|
+
const unordered = {
|
|
5991
|
+
kind: "bin", op: "===", left: cmpRef,
|
|
5992
|
+
right: { kind: "numLit", value: 2, type: F64, loc }, type: BOOL, loc,
|
|
5993
|
+
};
|
|
5994
|
+
const zero = { kind: "numLit", value: 0, type: F64, loc };
|
|
5995
|
+
const leftBig = left.type.kind === "bigint";
|
|
5996
|
+
const cmpOp = leftBig
|
|
5997
|
+
? op === ts.SyntaxKind.LessThanToken ? "<" : op === ts.SyntaxKind.LessThanEqualsToken ? "<=" : op === ts.SyntaxKind.GreaterThanToken ? ">" : ">="
|
|
5998
|
+
: op === ts.SyntaxKind.LessThanToken ? ">" : op === ts.SyntaxKind.LessThanEqualsToken ? ">=" : op === ts.SyntaxKind.GreaterThanToken ? "<" : "<=";
|
|
5999
|
+
const result = {
|
|
6000
|
+
kind: "logical", op: "&&",
|
|
6001
|
+
left: { kind: "unary", op: "!", operand: unordered, type: BOOL, loc },
|
|
6002
|
+
right: { kind: "bin", op: cmpOp, left: cmpRef, right: zero, type: BOOL, loc },
|
|
6003
|
+
type: BOOL, loc,
|
|
6004
|
+
};
|
|
6005
|
+
return {
|
|
6006
|
+
kind: "seqExpr",
|
|
6007
|
+
stmts: [{ kind: "varDecl", localId: cmpLocal.id, init: cmp, loc }],
|
|
6008
|
+
result,
|
|
6009
|
+
type: BOOL,
|
|
6010
|
+
loc,
|
|
6011
|
+
};
|
|
6012
|
+
}
|
|
6013
|
+
}
|
|
5880
6014
|
// An unchecked array read keeps its undefined arm in the IR even when
|
|
5881
6015
|
// the checker typed the binding as `string`. An optional string is not
|
|
5882
6016
|
// itself a string operand for `+`: `undefined + 1` and
|
|
@@ -6158,6 +6292,9 @@ export function lowerBinary(lowerer, expr) {
|
|
|
6158
6292
|
if (idLeft.type.kind === "classval" && idRight.type.kind === "classval") {
|
|
6159
6293
|
return { kind: "bin", op: negated ? "!==" : "===", left: idLeft, right: idRight, type: BOOL, loc };
|
|
6160
6294
|
}
|
|
6295
|
+
if (idLeft.type.kind === "moduleNs" && idRight.type.kind === "moduleNs") {
|
|
6296
|
+
return { kind: "bin", op: negated ? "!==" : "===", left: idLeft, right: idRight, type: BOOL, loc };
|
|
6297
|
+
}
|
|
6161
6298
|
if ((idLeft.type.kind === "array" ||
|
|
6162
6299
|
idLeft.type.kind === "map" ||
|
|
6163
6300
|
idLeft.type.kind === "set" ||
|
|
@@ -6390,6 +6527,7 @@ function typeofAnswer(arm) {
|
|
|
6390
6527
|
case "undefinedT": return "undefined";
|
|
6391
6528
|
case "func": return "function";
|
|
6392
6529
|
case "symbol": return "symbol";
|
|
6530
|
+
case "bigint": return "bigint";
|
|
6393
6531
|
case "nullT":
|
|
6394
6532
|
case "array":
|
|
6395
6533
|
case "map":
|
|
@@ -6409,7 +6547,10 @@ function typeofAnswer(arm) {
|
|
|
6409
6547
|
case "httpClientReq":
|
|
6410
6548
|
case "secureCtx":
|
|
6411
6549
|
case "fsWatcher":
|
|
6550
|
+
case "cryptoHash":
|
|
6551
|
+
case "cryptoHmac":
|
|
6412
6552
|
case "childStream":
|
|
6553
|
+
case "childWriter":
|
|
6413
6554
|
case "procStream":
|
|
6414
6555
|
case "object":
|
|
6415
6556
|
case "record":
|
|
@@ -7260,10 +7401,10 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
7260
7401
|
// Compile-time-known STRING keys fold — literals, and the same
|
|
7261
7402
|
// const/enum-literal and template folding computed property keys get
|
|
7262
7403
|
// (foldedStringKeyOf); runtime-valued keys keep the fence.
|
|
7263
|
-
// NUMERIC literal keys answer on ARRAY receivers
|
|
7264
|
-
//
|
|
7265
|
-
//
|
|
7266
|
-
//
|
|
7404
|
+
// NUMERIC literal keys answer on ARRAY receivers through the shared
|
|
7405
|
+
// presence query. Arrays retain holes independently from length, and
|
|
7406
|
+
// noncanonical numeric keys live in their ordinary-property table, so
|
|
7407
|
+
// a length comparison is not an honest `in` answer.
|
|
7267
7408
|
{
|
|
7268
7409
|
let kNode = expr.left;
|
|
7269
7410
|
while (ts.isParenthesizedExpression(kNode))
|
|
@@ -7271,12 +7412,14 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
7271
7412
|
if (ts.isNumericLiteral(kNode) && lowerer.mapTypeOf(lowerer.typeOf(expr.right))?.kind === "array") {
|
|
7272
7413
|
const recvArr = lowerer.lowerExpr(expr.right);
|
|
7273
7414
|
if (recvArr.type.kind === "array") {
|
|
7274
|
-
const len = { kind: "arrIntrinsic", method: "length", receiver: recvArr, args: [], type: F64, loc };
|
|
7275
7415
|
const n = Number(kNode.text);
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7416
|
+
return {
|
|
7417
|
+
kind: "arrayHas",
|
|
7418
|
+
arr: recvArr,
|
|
7419
|
+
index: { kind: "numLit", value: n, type: F64, loc },
|
|
7420
|
+
type: BOOL,
|
|
7421
|
+
loc,
|
|
7422
|
+
};
|
|
7280
7423
|
}
|
|
7281
7424
|
}
|
|
7282
7425
|
}
|
|
@@ -8912,32 +9055,40 @@ function lowerStreamObjectProperty(lowerer, expr) {
|
|
|
8912
9055
|
return lowerStreamProperty(lowerer, expr, info);
|
|
8913
9056
|
}
|
|
8914
9057
|
/** The primitive-constructor closure (`String`/`Number`/`Boolean` as a
|
|
8915
|
-
* VALUE): interns one synthesized module function per constructor
|
|
8916
|
-
*
|
|
8917
|
-
*
|
|
8918
|
-
* (`(
|
|
8919
|
-
*
|
|
8920
|
-
*
|
|
8921
|
-
* every reference the SAME immortal closure,
|
|
8922
|
-
* compares like JS function identity. */
|
|
8923
|
-
function primitiveCtorClosure(lowerer, name, loc) {
|
|
9058
|
+
* VALUE): interns one synthesized module function per constructor/ABI and
|
|
9059
|
+
* returns the zero-capture closure over it. Typed sources use the mapped
|
|
9060
|
+
* `(value: string) => primitive` signature; a recognized JavaScript
|
|
9061
|
+
* concise-arrow selector (`() => String`, the picocolors fallback) takes
|
|
9062
|
+
* dyn so its ordinary coercion signature survives inference residue. The
|
|
9063
|
+
* dyn bodies run exact ToString/ToNumber/ToBoolean, including object hooks.
|
|
9064
|
+
* Interning makes every reference under one ABI the SAME immortal closure,
|
|
9065
|
+
* so `opt.type === String` compares like JS function identity. */
|
|
9066
|
+
function primitiveCtorClosure(lowerer, name, loc, dynamicInput) {
|
|
8924
9067
|
const ret = name === "String" ? STRING : name === "Number" ? F64 : BOOL;
|
|
8925
|
-
const
|
|
8926
|
-
|
|
9068
|
+
const input = dynamicInput ? DYN : STRING;
|
|
9069
|
+
const fnT = funcOf([input], ret);
|
|
9070
|
+
const key = `${name}:${dynamicInput ? "dyn" : "string"}`;
|
|
9071
|
+
let fnName = lowerer.primitiveCtorFns.get(key);
|
|
8927
9072
|
if (!fnName) {
|
|
8928
|
-
fnName = `%builtin.${name}`;
|
|
8929
|
-
lowerer.primitiveCtorFns.set(
|
|
8930
|
-
const
|
|
8931
|
-
const value =
|
|
8932
|
-
?
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
9073
|
+
fnName = `%builtin.${name}${dynamicInput ? ".dyn" : ""}`;
|
|
9074
|
+
lowerer.primitiveCtorFns.set(key, fnName);
|
|
9075
|
+
const v = { kind: "varRef", localId: "v.0", type: input, loc };
|
|
9076
|
+
const value = dynamicInput
|
|
9077
|
+
? name === "String"
|
|
9078
|
+
? { kind: "libCall", fn: "dyn.toStringCoerce", args: [v], type: STRING, loc }
|
|
9079
|
+
: name === "Number"
|
|
9080
|
+
? { kind: "libCall", fn: "dyn.toNumberCoerce", args: [v], type: F64, loc }
|
|
9081
|
+
: { kind: "dynTest", test: "truthy", value: v, type: BOOL, loc }
|
|
9082
|
+
: name === "String"
|
|
9083
|
+
? v
|
|
9084
|
+
: name === "Number"
|
|
9085
|
+
? { kind: "libCall", fn: "num.fromString", args: [v], type: F64, loc }
|
|
9086
|
+
: { kind: "strEq", negated: true, left: v, right: { kind: "strLit", value: "", type: STRING, loc }, type: BOOL, loc };
|
|
8936
9087
|
const fn = {
|
|
8937
9088
|
name: fnName,
|
|
8938
|
-
params: [{ localId: "v.0", name: "value", type:
|
|
9089
|
+
params: [{ localId: "v.0", name: "value", type: input }],
|
|
8939
9090
|
returnType: ret,
|
|
8940
|
-
locals: [{ id: "v.0", name: "value", type:
|
|
9091
|
+
locals: [{ id: "v.0", name: "value", type: input, mutable: false }],
|
|
8941
9092
|
body: [{ kind: "return", value, loc }],
|
|
8942
9093
|
loc,
|
|
8943
9094
|
};
|