@scriptc/compiler 0.1.4 → 0.1.6
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 +75 -11
- package/dist/backend/c/c-emitter.d.ts +5 -1
- package/dist/backend/c/c-emitter.js +22 -9
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.d.ts +2 -2
- package/dist/backend/c/exprs.js +298 -27
- package/dist/backend/c/exprs.js.map +1 -1
- package/dist/backend/c/stmts.js +5 -3
- package/dist/backend/c/stmts.js.map +1 -1
- package/dist/backend/c/types.d.ts +2 -3
- package/dist/backend/c/types.js +8 -1
- package/dist/backend/c/types.js.map +1 -1
- package/dist/backend/c/walkers.js +1 -1
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/link-plan.d.ts +1 -0
- package/dist/backend/link-plan.js +2 -1
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/dyn.js +1 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +25 -9
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -2
- package/dist/backend/llvm/expr-bytes.js +22 -17
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -0
- package/dist/backend/llvm/expr-containers.js +58 -4
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +6 -2
- package/dist/backend/llvm/expr-primitives.js +22 -7
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +20 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +53 -10
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +4 -3
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +65 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +2 -0
- package/dist/backend/native-toolchain.js +2 -1
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/targets.d.ts +3 -0
- package/dist/backend/targets.js +13 -0
- package/dist/backend/targets.js.map +1 -1
- package/dist/coverage/surface-manifest.js +12 -5
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +2 -0
- package/dist/executable/executable-cache.js +3 -1
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +3 -3
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.d.ts +8 -0
- package/dist/frontend/lowering/array-indexed-mutation.js +176 -0
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +1 -1
- package/dist/frontend/lowering/containers/bytes.js +6 -5
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +14 -6
- package/dist/frontend/lowering/containers/string-and-regexp.js +420 -34
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +8 -0
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/indexed-comparison.d.ts +6 -0
- package/dist/frontend/lowering/indexed-comparison.js +30 -0
- package/dist/frontend/lowering/indexed-comparison.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +5 -6
- package/dist/frontend/lowering/lower-builtins.js +24 -16
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +3 -2
- package/dist/frontend/lowering/lower-calls.js +522 -89
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +5 -29
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +15 -11
- package/dist/frontend/lowering/lower-containers.js +588 -146
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +12 -0
- package/dist/frontend/lowering/lower-exprs.js +145 -11
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +17 -6
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +2 -4
- package/dist/frontend/lowering/lower-server.js +288 -32
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +4 -4
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.js +37 -2
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/optional-arguments.d.ts +9 -1
- package/dist/frontend/lowering/optional-arguments.js +67 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.d.ts +3 -1
- package/dist/frontend/lowering/pairs-snapshot.js +12 -4
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +10 -14
- package/dist/frontend/lowering/surfaces.js +50 -28
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +6 -0
- package/dist/frontend/npm-static-prune.js +203 -0
- package/dist/frontend/npm-static-prune.js.map +1 -0
- package/dist/frontend/npm-static-prune.test.d.ts +1 -0
- package/dist/frontend/npm-static-prune.test.js +48 -0
- package/dist/frontend/npm-static-prune.test.js.map +1 -0
- package/dist/frontend/npm.js +7 -6
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.js +15 -4
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance.js +8 -3
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/type-mapper.js +16 -5
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +13 -41
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +5 -3
- package/dist/ir/analysis.js +25 -11
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +50 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.d.ts +17 -0
- package/dist/ir/constant-tables.js +99 -0
- package/dist/ir/constant-tables.js.map +1 -0
- package/dist/ir/constant-tables.test.d.ts +1 -0
- package/dist/ir/constant-tables.test.js +78 -0
- package/dist/ir/constant-tables.test.js.map +1 -0
- package/dist/ir/integer-ranges.d.ts +13 -0
- package/dist/ir/integer-ranges.js +122 -0
- package/dist/ir/integer-ranges.js.map +1 -0
- package/dist/ir/integer-ranges.test.d.ts +1 -0
- package/dist/ir/integer-ranges.test.js +63 -0
- package/dist/ir/integer-ranges.test.js.map +1 -0
- package/dist/ir/ir.d.ts +56 -35
- package/dist/ir/ir.js +9 -1
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +6 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.d.ts +8 -0
- package/dist/ir/scalar-records.js +216 -0
- package/dist/ir/scalar-records.js.map +1 -0
- package/dist/ir/scalar-records.test.d.ts +1 -0
- package/dist/ir/scalar-records.test.js +142 -0
- package/dist/ir/scalar-records.test.js.map +1 -0
- package/dist/ir/validate.js +135 -34
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.d.ts +1 -0
- package/dist/ir/validate.test.js +48 -0
- package/dist/ir/validate.test.js.map +1 -0
- package/dist/library/cache-primitives.d.ts +1 -1
- package/dist/library/cache-primitives.js +3 -3
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +11 -4
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/library-cache.js +0 -1
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +3 -3
- package/dist/library/library-cache.test.js.map +1 -1
- package/package.json +17 -17
- package/surface-manifest.json +90 -45
|
@@ -164,10 +164,22 @@ export declare function lowerRecordKeyRead(lowerer: Lowerer, expr: ts.ElementAcc
|
|
|
164
164
|
* around the read are erased here because this context handles the missing
|
|
165
165
|
* arm instead of consuming it as the asserted type. */
|
|
166
166
|
export declare function lowerAbsenceProbe(lowerer: Lowerer, node: ts.Expression): IrExpr | null;
|
|
167
|
+
/** `a[i] op= rhs` over native arrays and byte views. A compound assignment
|
|
168
|
+
* evaluates the receiver and index, reads the old element, evaluates rhs,
|
|
169
|
+
* then writes. Capture each stage so a call in the index or rhs cannot
|
|
170
|
+
* change the target or the value used by the operator. The expression yields
|
|
171
|
+
* the computed value before a typed array or Buffer coerces it for storage. */
|
|
172
|
+
export declare function lowerElementCompound(lowerer: Lowerer, expr: ts.BinaryExpression, op: CompoundOp): IrExpr;
|
|
167
173
|
/** `a[i] = v` in statement position → arraySet (element writes, like local
|
|
168
174
|
* assignment, produce no value in our subset). */
|
|
169
175
|
export declare function lowerElementWrite(lowerer: Lowerer, expr: ts.BinaryExpression): IrStmt;
|
|
170
176
|
export declare function ensureString(lowerer: Lowerer, e: IrExpr, node: ts.Node): IrExpr;
|
|
177
|
+
/** `new String(x)` (stdlib provenance, ≤1 argument) in a ToString
|
|
178
|
+
* position: the wrapper's only distinguishers are typeof and identity —
|
|
179
|
+
* neither is observable where the value immediately stringifies — so the
|
|
180
|
+
* span lowers as the argument's own ToString (`new String()` is "").
|
|
181
|
+
* Every other position keeps the wrapper-object constructor fence. */
|
|
182
|
+
export declare function stringWrapperToString(lowerer: Lowerer, node: ts.Expression): IrExpr | null;
|
|
171
183
|
export declare function lowerTemplate(lowerer: Lowerer, expr: ts.TemplateExpression): IrExpr;
|
|
172
184
|
/** `x as T`. Non-dyn inner values ordinarily erase; a record assertion
|
|
173
185
|
* changing monomorphic shape rebuilds through the established width-copy
|
|
@@ -11,11 +11,12 @@ import { pathToFileURL } from "node:url";
|
|
|
11
11
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
12
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
|
-
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";
|
|
14
|
+
import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstOf, builtinModulesArrayLit, builtinModuleFnOf, COMPOUND_ASSIGN_OPS, ISLAND_SURFACE, isChildSurfaceMember, MAP_METHODS, NARROW_FIRST, SET_METHODS, STRING_INDEX_METHODS, STR_METHODS, UNSUPPORTED_EXPR, sideEffectFreeOptionValue, stdlibGlobalNameOf } from "./surfaces.js";
|
|
15
15
|
import { blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag } from "../../diagnostics/diagnostic.js";
|
|
16
16
|
import { PoisonError, dynUndefinedExpr, jsFuncNameOf, neverTaintedJsType, nodeThrowExpr, own } from "./lowerer.js";
|
|
17
|
-
import { lowerNpmStaticSafeIndexRead, lowerSafeIndexRead, strCharsCall } from "./lower-containers.js";
|
|
18
|
-
import { arrayValueStore } from "./array-values.js";
|
|
17
|
+
import { lowerNpmStaticSafeIndexRead, lowerSafeIndexRead, strCharsCall, tryLowerNumericIndexRead } from "./lower-containers.js";
|
|
18
|
+
import { arrayValueRead, arrayValueStore } from "./array-values.js";
|
|
19
|
+
import { tryLowerIndexedComparison } from "./indexed-comparison.js";
|
|
19
20
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
20
21
|
import { unsupportedModuleFeatureOf } from "../builtin-modules.js";
|
|
21
22
|
import { fenceEnumObjectValue, lowerEnumAccess } from "./lower-enums.js";
|
|
@@ -35,6 +36,7 @@ import { conditionalSpreadOf, foldedStringKeyOf } from "./expressions/object-lit
|
|
|
35
36
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
36
37
|
import { fenceNodeModuleMutation, isNodeModuleValue, lowerNodeModuleIdentifier, lowerNodeModuleProperty, lowerRequireCacheElement, lowerRequireCacheHas, lowerRequireMainProperty } from "./lower-node-module.js";
|
|
37
38
|
import { lowerAbstractEquality } from "./abstract-equality.js";
|
|
39
|
+
import { coerceStringSearchValue, defaultAfterUndefined, lowerStaticallyUndefinedArgument } from "./optional-arguments.js";
|
|
38
40
|
/** A template piece's RAW text (String.raw's contract: escapes stay
|
|
39
41
|
* characters). 7's client AST ships no rawText at runtime (the typing
|
|
40
42
|
* declares it; the serialized node data omits it), so the raw span comes
|
|
@@ -553,6 +555,18 @@ function lowerExprInner(lowerer, expr) {
|
|
|
553
555
|
return { kind: "strLit", value: "object", type: STRING, loc };
|
|
554
556
|
}
|
|
555
557
|
if (ts.isPropertyAccessExpression(expr.expression)) {
|
|
558
|
+
const member = expr.expression;
|
|
559
|
+
const prototype = member.expression;
|
|
560
|
+
if (STRING_INDEX_METHODS.has(member.name.text) && ts.isPropertyAccessExpression(prototype) &&
|
|
561
|
+
prototype.name.text === "prototype" && ts.isIdentifier(prototype.expression) &&
|
|
562
|
+
lowerer.isStdlibGlobal(prototype.expression, "String") && lowerer.isStdlibMember(member)) {
|
|
563
|
+
return { kind: "strLit", value: "function", type: STRING, loc };
|
|
564
|
+
}
|
|
565
|
+
if (member.name.text === "at" && ts.isPropertyAccessExpression(prototype) &&
|
|
566
|
+
prototype.name.text === "prototype" && ts.isIdentifier(prototype.expression) &&
|
|
567
|
+
lowerer.isStdlibGlobal(prototype.expression, "Array") && lowerer.isStdlibMember(member)) {
|
|
568
|
+
return { kind: "strLit", value: "function", type: STRING, loc };
|
|
569
|
+
}
|
|
556
570
|
const presence = lowerPromiseThenPresence(lowerer, expr.expression, { kind: "strLit", value: "function", type: STRING, loc });
|
|
557
571
|
if (presence !== null)
|
|
558
572
|
return presence;
|
|
@@ -871,6 +885,12 @@ function lowerExprInner(lowerer, expr) {
|
|
|
871
885
|
if (bi.module === "module" && bi.member === "builtinModules") {
|
|
872
886
|
return builtinModulesArrayLit(loc);
|
|
873
887
|
}
|
|
888
|
+
if (bi.module === "http" && bi.member === "METHODS") {
|
|
889
|
+
return { kind: "libCall", fn: "http.methods", args: [], type: arrayOf(STRING), loc };
|
|
890
|
+
}
|
|
891
|
+
if (bi.module === "http" && bi.member === "STATUS_CODES") {
|
|
892
|
+
return { kind: "libCall", fn: "http.statusCodes", args: [], type: DYN, loc };
|
|
893
|
+
}
|
|
874
894
|
// tls.rootCertificates: a runtime-valued module constant (the
|
|
875
895
|
// cached bundled-CA array) — the one member read that lowers
|
|
876
896
|
// to a libCall instead of a baked literal.
|
|
@@ -3392,7 +3412,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
3392
3412
|
: { kind: "arrIntrinsic", method: "length", receiver, args: [], type: F64, loc: locOf(expr) };
|
|
3393
3413
|
}
|
|
3394
3414
|
if (kind === "string"
|
|
3395
|
-
? own(STR_METHODS, name) !== undefined || own(ISLAND_SURFACE.string, name) !== undefined
|
|
3415
|
+
? own(STR_METHODS, name) !== undefined || STRING_INDEX_METHODS.has(name) || own(ISLAND_SURFACE.string, name) !== undefined
|
|
3396
3416
|
: ARRAY_METHODS.has(name)) {
|
|
3397
3417
|
lowerer.unsupported("SC1090", expr, `${kind} methods as values (call '${name}' directly)`);
|
|
3398
3418
|
}
|
|
@@ -3804,6 +3824,11 @@ export function lowerOptionalNumber(lowerer, operand, loc, narrowedNode) {
|
|
|
3804
3824
|
if (operand.type.kind !== "union" || lowerer.armTag(operand.type.unionId, UNDEFINED_T) < 0)
|
|
3805
3825
|
return operand;
|
|
3806
3826
|
const directNumber = lowerer.stripUndefinedArm(operand.type).kind === "f64";
|
|
3827
|
+
if (directNumber) {
|
|
3828
|
+
const scalarRead = tryLowerNumericIndexRead(lowerer, operand, loc);
|
|
3829
|
+
if (scalarRead)
|
|
3830
|
+
return scalarRead;
|
|
3831
|
+
}
|
|
3807
3832
|
const checkerNumber = narrowedNode !== undefined && lowerer.mapTypeOf(lowerer.typeOf(narrowedNode))?.kind === "f64";
|
|
3808
3833
|
if (!directNumber && (!checkerNumber || lowerer.armTag(operand.type.unionId, F64) < 0))
|
|
3809
3834
|
return operand;
|
|
@@ -4582,6 +4607,78 @@ function tupleLiteralIndex(node) {
|
|
|
4582
4607
|
const n = Number(e.text);
|
|
4583
4608
|
return Number.isInteger(n) && n >= 0 ? n : null;
|
|
4584
4609
|
}
|
|
4610
|
+
/** `a[i] op= rhs` over native arrays and byte views. A compound assignment
|
|
4611
|
+
* evaluates the receiver and index, reads the old element, evaluates rhs,
|
|
4612
|
+
* then writes. Capture each stage so a call in the index or rhs cannot
|
|
4613
|
+
* change the target or the value used by the operator. The expression yields
|
|
4614
|
+
* the computed value before a typed array or Buffer coerces it for storage. */
|
|
4615
|
+
export function lowerElementCompound(lowerer, expr, op) {
|
|
4616
|
+
const target = expr.left;
|
|
4617
|
+
fenceNodeModuleMutation(lowerer, target, "assignment");
|
|
4618
|
+
const loc = locOf(expr);
|
|
4619
|
+
const receiverType = lowerer.mapTypeOf(lowerer.typeOf(target.expression));
|
|
4620
|
+
if (receiverType?.kind !== "array" && receiverType?.kind !== "bytes") {
|
|
4621
|
+
lowerer.unsupported("SC1090", target, "compound assignment to non-array elements");
|
|
4622
|
+
}
|
|
4623
|
+
let receiver = lowerer.lowerExpr(target.expression);
|
|
4624
|
+
if (receiver.type.kind === "union" && lowerer.armTag(receiver.type.unionId, UNDEFINED_T) >= 0) {
|
|
4625
|
+
const present = lowerer.stripUndefinedArm(receiver.type);
|
|
4626
|
+
const helper = present.kind === receiverType.kind
|
|
4627
|
+
? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(target.expression))
|
|
4628
|
+
: null;
|
|
4629
|
+
if (helper)
|
|
4630
|
+
receiver = { kind: "call", callee: helper, args: [receiver], type: present, loc: locOf(target.expression) };
|
|
4631
|
+
}
|
|
4632
|
+
if (receiver.type.kind !== receiverType.kind) {
|
|
4633
|
+
lowerer.unsupported("SC1090", target.expression, "compound assignment through a non-native array or byte view");
|
|
4634
|
+
}
|
|
4635
|
+
const index = lowerer.lowerExpr(target.argumentExpression);
|
|
4636
|
+
if (index.type.kind !== "f64")
|
|
4637
|
+
lowerer.unsupported("SC1090", target.argumentExpression, "indexing with non-number keys");
|
|
4638
|
+
const receiverLocal = lowerer.declareHiddenLocal("%compoundArray", receiver.type);
|
|
4639
|
+
const indexLocal = lowerer.declareHiddenLocal("%compoundIndex", F64);
|
|
4640
|
+
const receiverRef = () => varRef(receiverLocal.id, receiver.type, loc);
|
|
4641
|
+
const indexRef = () => varRef(indexLocal.id, F64, loc);
|
|
4642
|
+
const oldValue = receiver.type.kind === "array"
|
|
4643
|
+
? arrayValueRead(lowerer, receiverRef(), indexRef(), receiver.type.elem, locOf(target))
|
|
4644
|
+
: { kind: "bytesIntrinsic", method: "get", receiver: receiverRef(), args: [indexRef()], type: F64, loc: locOf(target) };
|
|
4645
|
+
const oldLocal = lowerer.declareHiddenLocal("%compoundOld", oldValue.type);
|
|
4646
|
+
const oldRef = () => varRef(oldLocal.id, oldValue.type, loc);
|
|
4647
|
+
const rhs = lowerer.lowerExpr(expr.right);
|
|
4648
|
+
const numericRhs = lowerOptionalNumber(lowerer, rhs, loc);
|
|
4649
|
+
const elementType = receiver.type.kind === "array" ? receiver.type.elem : F64;
|
|
4650
|
+
const valueType = elementType.kind === "union" && lowerer.armTag(elementType.unionId, UNDEFINED_T) >= 0
|
|
4651
|
+
? lowerer.stripUndefinedArm(elementType)
|
|
4652
|
+
: elementType;
|
|
4653
|
+
let computed;
|
|
4654
|
+
if (op === "+" && valueType.kind === "string") {
|
|
4655
|
+
computed = { kind: "strConcat", left: lowerer.ensureString(oldRef(), target), right: lowerer.ensureString(rhs, expr.right), type: STRING, loc };
|
|
4656
|
+
}
|
|
4657
|
+
else if (valueType.kind === "f64" && numericRhs.type.kind === "f64") {
|
|
4658
|
+
computed = { kind: "bin", op, left: lowerOptionalNumber(lowerer, oldRef(), loc), right: numericRhs, type: F64, loc };
|
|
4659
|
+
}
|
|
4660
|
+
else {
|
|
4661
|
+
lowerer.unsupported("SC1043", expr);
|
|
4662
|
+
}
|
|
4663
|
+
const resultLocal = lowerer.declareHiddenLocal("%compoundResult", computed.type);
|
|
4664
|
+
const resultRef = () => varRef(resultLocal.id, computed.type, loc);
|
|
4665
|
+
const write = receiver.type.kind === "array"
|
|
4666
|
+
? arrayValueStore(lowerer, receiverRef(), indexRef(), resultRef(), receiver.type.elem, loc)
|
|
4667
|
+
: { kind: "bytesSet", arr: receiverRef(), index: indexRef(), value: resultRef(), loc };
|
|
4668
|
+
return {
|
|
4669
|
+
kind: "seqExpr",
|
|
4670
|
+
stmts: [
|
|
4671
|
+
{ kind: "varDecl", localId: receiverLocal.id, init: receiver, loc },
|
|
4672
|
+
{ kind: "varDecl", localId: indexLocal.id, init: index, loc },
|
|
4673
|
+
{ kind: "varDecl", localId: oldLocal.id, init: oldValue, loc },
|
|
4674
|
+
{ kind: "varDecl", localId: resultLocal.id, init: computed, loc },
|
|
4675
|
+
write,
|
|
4676
|
+
],
|
|
4677
|
+
result: resultRef(),
|
|
4678
|
+
type: computed.type,
|
|
4679
|
+
loc,
|
|
4680
|
+
};
|
|
4681
|
+
}
|
|
4585
4682
|
/** `a[i] = v` in statement position → arraySet (element writes, like local
|
|
4586
4683
|
* assignment, produce no value in our subset). */
|
|
4587
4684
|
export function lowerElementWrite(lowerer, expr) {
|
|
@@ -4953,6 +5050,18 @@ export function ensureString(lowerer, e, node) {
|
|
|
4953
5050
|
if (stringable) {
|
|
4954
5051
|
return { kind: "toString", operand: e, type: STRING, loc: e.loc };
|
|
4955
5052
|
}
|
|
5053
|
+
// Runtime-optional locals can retain their stored union after the
|
|
5054
|
+
// checker has narrowed this use to a primitive arm. Validate that
|
|
5055
|
+
// arm before converting it; an unguarded object arm stays fenced.
|
|
5056
|
+
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
5057
|
+
if (narrowed &&
|
|
5058
|
+
(narrowed.kind === "string" || narrowed.kind === "f64" ||
|
|
5059
|
+
narrowed.kind === "bool" || narrowed.kind === "bigint")) {
|
|
5060
|
+
const helper = lowerer.narrowedArmHelper(e.type.unionId, narrowed, e.loc);
|
|
5061
|
+
if (helper) {
|
|
5062
|
+
return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
4956
5065
|
lowerer.unsupported("SC1090", node, `string conversions of unions with object arms (${NARROW_FIRST})`);
|
|
4957
5066
|
}
|
|
4958
5067
|
if (e.type.kind === "symbol") {
|
|
@@ -5004,7 +5113,7 @@ export function ensureString(lowerer, e, node) {
|
|
|
5004
5113
|
* neither is observable where the value immediately stringifies — so the
|
|
5005
5114
|
* span lowers as the argument's own ToString (`new String()` is "").
|
|
5006
5115
|
* Every other position keeps the wrapper-object constructor fence. */
|
|
5007
|
-
function stringWrapperToString(lowerer, node) {
|
|
5116
|
+
export function stringWrapperToString(lowerer, node) {
|
|
5008
5117
|
let e = node;
|
|
5009
5118
|
while (ts.isParenthesizedExpression(e))
|
|
5010
5119
|
e = e.expression;
|
|
@@ -5018,7 +5127,11 @@ function stringWrapperToString(lowerer, node) {
|
|
|
5018
5127
|
return null;
|
|
5019
5128
|
if (args.length === 0)
|
|
5020
5129
|
return { kind: "strLit", value: "", type: STRING, loc: locOf(e) };
|
|
5021
|
-
|
|
5130
|
+
const undefinedArg = lowerStaticallyUndefinedArgument(lowerer, args[0]);
|
|
5131
|
+
if (undefinedArg)
|
|
5132
|
+
return defaultAfterUndefined(undefinedArg, { kind: "strLit", value: "undefined", type: STRING, loc: locOf(e) });
|
|
5133
|
+
return lowerer.caughtToString(args[0]) ??
|
|
5134
|
+
coerceStringSearchValue(lowerer, lowerer.lowerExpr(args[0]), args[0], locOf(e));
|
|
5022
5135
|
}
|
|
5023
5136
|
export function lowerTemplate(lowerer, expr) {
|
|
5024
5137
|
const loc = locOf(expr);
|
|
@@ -5410,8 +5523,9 @@ export function lowerBinary(lowerer, expr) {
|
|
|
5410
5523
|
// globals, captured/boxed included); the RHS coerces into the binding's
|
|
5411
5524
|
// type exactly like statement position, and the expression's value is
|
|
5412
5525
|
// the coerced binding-typed value (representation change only — never
|
|
5413
|
-
// observably different from JS's raw-RHS yield).
|
|
5414
|
-
//
|
|
5526
|
+
// observably different from JS's raw-RHS yield). Indexed compounds
|
|
5527
|
+
// use a sequenced read/modify/write; other member targets and
|
|
5528
|
+
// destructuring targets stay fenced.
|
|
5415
5529
|
if (op === ts.SyntaxKind.EqualsToken && ts.isIdentifier(expr.left)) {
|
|
5416
5530
|
const target = lowerer.resolveWritable(expr.left);
|
|
5417
5531
|
if (!target) {
|
|
@@ -5423,6 +5537,10 @@ export function lowerBinary(lowerer, expr) {
|
|
|
5423
5537
|
lowerer.runtimeOptionalLocals.add(runtimeOptionalRoot);
|
|
5424
5538
|
return { kind: "assignExpr", localId: target.id, value, type: target.type, loc };
|
|
5425
5539
|
}
|
|
5540
|
+
const indexedCompound = COMPOUND_ASSIGN_OPS[op];
|
|
5541
|
+
if (indexedCompound !== undefined && ts.isElementAccessExpression(expr.left)) {
|
|
5542
|
+
return lowerElementCompound(lowerer, expr, indexedCompound);
|
|
5543
|
+
}
|
|
5426
5544
|
// `events.defaultMaxListeners = v` — the module-property write
|
|
5427
5545
|
// Node validates (validateNumber(n, 'defaultMaxListeners', 0)):
|
|
5428
5546
|
// the value crosses into the checked-dynamic tree and the runtime ladder throws
|
|
@@ -6171,6 +6289,9 @@ export function lowerBinary(lowerer, expr) {
|
|
|
6171
6289
|
case ts.SyntaxKind.EqualsEqualsEqualsToken:
|
|
6172
6290
|
case ts.SyntaxKind.ExclamationEqualsEqualsToken: {
|
|
6173
6291
|
const negated = op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
|
|
6292
|
+
const indexed = tryLowerIndexedComparison(lowerer, left, right, negated, loc);
|
|
6293
|
+
if (indexed)
|
|
6294
|
+
return indexed;
|
|
6174
6295
|
if (plainBothNum)
|
|
6175
6296
|
return { kind: "bin", op: negated ? "!==" : "===", left, right, type: BOOL, loc };
|
|
6176
6297
|
if (bothStr)
|
|
@@ -8739,7 +8860,20 @@ export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
|
8739
8860
|
// construction), typed as the index value armed with undefined under
|
|
8740
8861
|
// noUncheckedIndexedAccess (mirroring lowerRecordKeyRead).
|
|
8741
8862
|
if (target.container === "recordOvf") {
|
|
8742
|
-
let
|
|
8863
|
+
let obj = target.obj;
|
|
8864
|
+
if (obj.type.kind === "union" && ts.isPropertyAccessExpression(blame)) {
|
|
8865
|
+
const present = lowerer.stripUndefinedArm(obj.type);
|
|
8866
|
+
if (present.kind === "record") {
|
|
8867
|
+
obj = lowerer.runtimeOptionalPropertyReceiver(blame.expression, obj, present, target.field) ?? obj;
|
|
8868
|
+
}
|
|
8869
|
+
}
|
|
8870
|
+
if (obj.type.kind !== "record") {
|
|
8871
|
+
lowerer.unsupported("SC1090", blame, `reading '${target.field}' on a non-record receiver (narrow first)`);
|
|
8872
|
+
}
|
|
8873
|
+
const shape = lowerer.shapes.get(obj.type.shapeId);
|
|
8874
|
+
if (!shape?.indexValue)
|
|
8875
|
+
lowerer.unsupported("SC1090", blame, `reading '${target.field}' on a record without an index signature`);
|
|
8876
|
+
let t = shape.indexValue;
|
|
8743
8877
|
if (lowerer.program.getCompilerOptions().noUncheckedIndexedAccess) {
|
|
8744
8878
|
const armed = lowerer.withUndefinedArmOf(t);
|
|
8745
8879
|
if (!armed)
|
|
@@ -8748,8 +8882,8 @@ export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
|
8748
8882
|
}
|
|
8749
8883
|
return {
|
|
8750
8884
|
kind: "recordKeyGet",
|
|
8751
|
-
obj
|
|
8752
|
-
shapeId:
|
|
8885
|
+
obj,
|
|
8886
|
+
shapeId: obj.type.shapeId,
|
|
8753
8887
|
key: { kind: "strLit", value: target.field, type: STRING, loc },
|
|
8754
8888
|
overflowOnly: true,
|
|
8755
8889
|
type: t,
|