@scriptc/compiler 0.0.33 → 0.0.35

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.
Files changed (133) hide show
  1. package/dist/backend/cc-cache.test.js +1091 -7
  2. package/dist/backend/cc-cache.test.js.map +1 -1
  3. package/dist/backend/cc.d.ts +109 -18
  4. package/dist/backend/cc.js +1057 -289
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/emission/emit-exprs.js +26 -1
  7. package/dist/backend/emission/emit-exprs.js.map +1 -1
  8. package/dist/backend/emission/emit-shapes.js +37 -4
  9. package/dist/backend/emission/emit-shapes.js.map +1 -1
  10. package/dist/backend/emission/emitter.d.ts +11 -2
  11. package/dist/backend/emission/emitter.js +11 -5
  12. package/dist/backend/emission/emitter.js.map +1 -1
  13. package/dist/backend/library-identity.d.ts +22 -0
  14. package/dist/backend/library-identity.js +103 -0
  15. package/dist/backend/library-identity.js.map +1 -0
  16. package/dist/backend/llvm/emitter.d.ts +3 -0
  17. package/dist/backend/llvm/emitter.js +35 -5
  18. package/dist/backend/llvm/emitter.js.map +1 -1
  19. package/dist/backend/llvm/shapes.d.ts +1 -0
  20. package/dist/backend/llvm/shapes.js +25 -1
  21. package/dist/backend/llvm/shapes.js.map +1 -1
  22. package/dist/backend/llvm/split.d.ts +43 -0
  23. package/dist/backend/llvm/split.js +227 -0
  24. package/dist/backend/llvm/split.js.map +1 -0
  25. package/dist/backend/llvm/split.test.d.ts +1 -0
  26. package/dist/backend/llvm/split.test.js +102 -0
  27. package/dist/backend/llvm/split.test.js.map +1 -0
  28. package/dist/backend/mangle.d.ts +1 -0
  29. package/dist/backend/mangle.js +3 -0
  30. package/dist/backend/mangle.js.map +1 -1
  31. package/dist/backend/object-localize.d.ts +5 -5
  32. package/dist/backend/object-localize.js +19 -16
  33. package/dist/backend/object-localize.js.map +1 -1
  34. package/dist/backend/object-localize.test.js +57 -13
  35. package/dist/backend/object-localize.test.js.map +1 -1
  36. package/dist/executable/early-cache.d.ts +86 -0
  37. package/dist/executable/early-cache.js +460 -0
  38. package/dist/executable/early-cache.js.map +1 -0
  39. package/dist/executable/early-cache.test.d.ts +1 -0
  40. package/dist/executable/early-cache.test.js +300 -0
  41. package/dist/executable/early-cache.test.js.map +1 -0
  42. package/dist/ffi/profile.d.ts +7 -2
  43. package/dist/ffi/profile.js +1 -0
  44. package/dist/ffi/profile.js.map +1 -1
  45. package/dist/frontend/input-tracker.d.ts +82 -0
  46. package/dist/frontend/input-tracker.js +380 -0
  47. package/dist/frontend/input-tracker.js.map +1 -0
  48. package/dist/frontend/input-tracker.test.d.ts +1 -0
  49. package/dist/frontend/input-tracker.test.js +137 -0
  50. package/dist/frontend/input-tracker.test.js.map +1 -0
  51. package/dist/frontend/lowering/lower-builtins.js +4 -10
  52. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  53. package/dist/frontend/lowering/lower-calls.js +169 -144
  54. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  55. package/dist/frontend/lowering/lower-classes.js +3 -0
  56. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  57. package/dist/frontend/lowering/lower-containers.js +66 -32
  58. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  59. package/dist/frontend/lowering/lower-exprs.js +89 -11
  60. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  61. package/dist/frontend/lowering/lower-inspect.js +45 -26
  62. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  63. package/dist/frontend/lowering/lower-island.js +3 -3
  64. package/dist/frontend/lowering/lower-island.js.map +1 -1
  65. package/dist/frontend/lowering/lower-mixins.js +1 -1
  66. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  67. package/dist/frontend/lowering/lower-modules.js +1 -1
  68. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  69. package/dist/frontend/lowering/lower-stmts.js +49 -4
  70. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  71. package/dist/frontend/lowering/lowerer.d.ts +73 -29
  72. package/dist/frontend/lowering/lowerer.js +588 -116
  73. package/dist/frontend/lowering/lowerer.js.map +1 -1
  74. package/dist/frontend/lowering/surfaces.js +1 -1
  75. package/dist/frontend/lowering/surfaces.js.map +1 -1
  76. package/dist/frontend/npm-static-rewrite.js +25 -26
  77. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  78. package/dist/frontend/npm-static.js +29 -30
  79. package/dist/frontend/npm-static.js.map +1 -1
  80. package/dist/frontend/npm-static.test.d.ts +1 -0
  81. package/dist/frontend/npm-static.test.js +15 -0
  82. package/dist/frontend/npm-static.test.js.map +1 -0
  83. package/dist/frontend/npm.js +5 -17
  84. package/dist/frontend/npm.js.map +1 -1
  85. package/dist/frontend/program.js +44 -19
  86. package/dist/frontend/program.js.map +1 -1
  87. package/dist/frontend/resolve.js +8 -29
  88. package/dist/frontend/resolve.js.map +1 -1
  89. package/dist/frontend/ts7/checker.d.ts +40 -2
  90. package/dist/frontend/ts7/checker.js +194 -32
  91. package/dist/frontend/ts7/checker.js.map +1 -1
  92. package/dist/frontend/ts7/program.js +17 -18
  93. package/dist/frontend/ts7/program.js.map +1 -1
  94. package/dist/frontend/types.d.ts +33 -0
  95. package/dist/frontend/types.js +134 -45
  96. package/dist/frontend/types.js.map +1 -1
  97. package/dist/index.d.ts +5 -2
  98. package/dist/index.js +458 -141
  99. package/dist/index.js.map +1 -1
  100. package/dist/ir/nodes.d.ts +27 -4
  101. package/dist/ir/nodes.js +28 -0
  102. package/dist/ir/nodes.js.map +1 -1
  103. package/dist/ir/serialize.d.ts +1 -1
  104. package/dist/ir/serialize.js +1 -1
  105. package/dist/ir/validate.js +37 -1
  106. package/dist/ir/validate.js.map +1 -1
  107. package/dist/library/early-cache.d.ts +65 -0
  108. package/dist/library/early-cache.js +361 -0
  109. package/dist/library/early-cache.js.map +1 -0
  110. package/dist/library/early-cache.test.d.ts +1 -0
  111. package/dist/library/early-cache.test.js +528 -0
  112. package/dist/library/early-cache.test.js.map +1 -0
  113. package/dist/library/implementation-identity.d.ts +23 -0
  114. package/dist/library/implementation-identity.js +84 -0
  115. package/dist/library/implementation-identity.js.map +1 -0
  116. package/dist/library/int-infer.js +14 -0
  117. package/dist/library/int-infer.js.map +1 -1
  118. package/dist/library/int-infer.test.js +21 -4
  119. package/dist/library/int-infer.test.js.map +1 -1
  120. package/dist/library/semantic-source.d.ts +13 -0
  121. package/dist/library/semantic-source.js +257 -0
  122. package/dist/library/semantic-source.js.map +1 -0
  123. package/dist/library/semantic-source.test.d.ts +1 -0
  124. package/dist/library/semantic-source.test.js +113 -0
  125. package/dist/library/semantic-source.test.js.map +1 -0
  126. package/dist/library/sidecar.d.ts +6 -0
  127. package/dist/library/sidecar.js +11 -0
  128. package/dist/library/sidecar.js.map +1 -1
  129. package/dist/startup-cache.d.ts +6 -0
  130. package/dist/startup-cache.js +6 -0
  131. package/dist/startup-cache.js.map +1 -0
  132. package/package.json +3 -2
  133. package/surface-manifest.json +1 -1
@@ -1823,7 +1823,7 @@ export function lowerTernary(L, expr, expected) {
1823
1823
  const argIdent = c.arguments[0];
1824
1824
  const sym = L.resolveValueSymbol(argIdent);
1825
1825
  const t = L.checker.getTypeAtLocation(argIdent);
1826
- const constituents = t.isUnionType() ? t.getTypes() : [];
1826
+ const constituents = t.isUnionType() ? ts.constituentTypes(t) : [];
1827
1827
  const nonArray = constituents.filter((a) => !L.checker.isArrayType(a) && !L.checker.isTupleType(a));
1828
1828
  const mapped = L.mapTypeOf(t);
1829
1829
  const armCount = mapped?.kind === "union" ? L.arrayValueTags(mapped.unionId).length : 0;
@@ -2453,6 +2453,8 @@ export function droppableStatic(e) {
2453
2453
  return e.elems.every(droppableStatic);
2454
2454
  case "recordLit":
2455
2455
  return e.fields.every((f) => droppableStatic(f.value));
2456
+ case "recordClone":
2457
+ return droppableStatic(e.source) && e.overrides.every((f) => droppableStatic(f.value));
2456
2458
  case "closure":
2457
2459
  return true;
2458
2460
  default:
@@ -3753,7 +3755,7 @@ export function lowerArrayLiteral(L, expr, expected) {
3753
3755
  * for effect and are not stored. Null for every other target. */
3754
3756
  function settledDropNames(L, tsType) {
3755
3757
  let names = null;
3756
- const parts = tsType.isUnionType() ? tsType.getTypes() : [tsType];
3758
+ const parts = tsType.isUnionType() ? ts.constituentTypes(tsType) : [tsType];
3757
3759
  for (const part of parts) {
3758
3760
  const sym = part.getSymbol();
3759
3761
  if (!sym ||
@@ -3830,7 +3832,7 @@ function literalKeySpellingOf(t) {
3830
3832
  return String(t.value);
3831
3833
  if (t.isUnionType()) {
3832
3834
  let out = null;
3833
- for (const arm of t.getTypes()) {
3835
+ for (const arm of ts.constituentTypes(t)) {
3834
3836
  const s = arm.isStringLiteralType() ? arm.value : arm.isNumberLiteralType() ? String(arm.value) : null;
3835
3837
  if (s === null || (out !== null && s !== out))
3836
3838
  return null;
@@ -4181,7 +4183,7 @@ function literalUnionArmOf(L, expr, tsType, recordArms) {
4181
4183
  * equal or width-liftable. */
4182
4184
  const fits = (litT, ftT) => {
4183
4185
  if (ftT.isUnionType())
4184
- return ftT.getTypes().some((a) => fits(litT, a));
4186
+ return ts.constituentTypes(ftT).some((a) => fits(litT, a));
4185
4187
  if (ftT.isStringLiteralType())
4186
4188
  return litT.isStringLiteralType() && litT.value === ftT.value;
4187
4189
  if (ftT.isNumberLiteralType())
@@ -4203,7 +4205,7 @@ function literalUnionArmOf(L, expr, tsType, recordArms) {
4203
4205
  };
4204
4206
  const armShapeIds = new Set(recordArms.map((a) => a.shapeId));
4205
4207
  const candidates = new Set();
4206
- for (const member of tsType.getTypes()) {
4208
+ for (const member of ts.constituentTypes(tsType)) {
4207
4209
  const mMapped = L.mapTypeOf(member);
4208
4210
  if (mMapped?.kind !== "record" || !armShapeIds.has(mMapped.shapeId) || candidates.has(mMapped.shapeId))
4209
4211
  continue;
@@ -4348,7 +4350,7 @@ export function lowerObjectLiteral(L, expr) {
4348
4350
  // slot's field types (`lanIp: string | null`), which the literal's own
4349
4351
  // type narrows away (a field written as `lanIp: null` types as bare
4350
4352
  // `null`, which maps to nothing on its own).
4351
- if (tsType.isUnionType() && tsType.getTypes().some((t) => t.getSymbol()?.name === "PromiseLike")) {
4353
+ if (tsType.isUnionType() && ts.constituentTypes(tsType).some((t) => t.getSymbol()?.name === "PromiseLike")) {
4352
4354
  tsType = L.checker.getAwaitedType(tsType) ?? tsType;
4353
4355
  }
4354
4356
  let mapped = L.mapTypeOf(tsType);
@@ -4378,7 +4380,7 @@ export function lowerObjectLiteral(L, expr) {
4378
4380
  if (ctxShape && !ctxShape.indexValue && !ctxShape.tuple) {
4379
4381
  const names = new Set(ctxShape.fields.map((f) => f.name));
4380
4382
  const ctxHasProp = (name) => {
4381
- const members = tsType.isUnionType() ? tsType.getTypes() : [tsType];
4383
+ const members = tsType.isUnionType() ? ts.constituentTypes(tsType) : [tsType];
4382
4384
  return members.some((m) => L.checker.getPropertyOfType(m, name) !== undefined);
4383
4385
  };
4384
4386
  const extraOf = (text) => !names.has(text) && !ctxHasProp(text);
@@ -4527,6 +4529,66 @@ export function lowerObjectLiteral(L, expr) {
4527
4529
  }
4528
4530
  }
4529
4531
  const fieldTypes = new Map(shape.fields.map((f) => [f.name, f.type]));
4532
+ // The clone probe may lower the leading spread before declining (a
4533
+ // static `as` cast can make the checker-visible shape match while its
4534
+ // erased IR value keeps a wider shape). Reuse that exact value in the
4535
+ // ordinary spread path so lowering still happens once.
4536
+ let leadingSpreadLowered = null;
4537
+ // The overwhelmingly common immutable-update form over a record:
4538
+ // `{ ...model, changed, other: value }`. The historic lowering expanded
4539
+ // the spread into one recordGet per untouched field at EVERY site, then
4540
+ // the backends inlined all of those retains and stores into the caller.
4541
+ // A 178-field model updated hundreds of times consequently produced a
4542
+ // half-million-line LLVM function. Keep the same evaluation/ownership
4543
+ // semantics in one compact IR node: source first, explicit overrides in
4544
+ // source order, and one backend clone helper per shape.
4545
+ //
4546
+ // Stay deliberately narrow. Tuple/index/accessor shapes, conditional or
4547
+ // multiple spreads, spread-after-explicit order, and shape-changing width
4548
+ // copies retain their existing lowering and diagnostics.
4549
+ if (!isJsSourceFile(expr.getSourceFile()) &&
4550
+ !shape.indexValue &&
4551
+ !shape.tuple &&
4552
+ !shapeHasAccessorSlots(shape) &&
4553
+ expr.properties.length >= 2 &&
4554
+ ts.isSpreadAssignment(expr.properties[0]) &&
4555
+ !conditionalSpreadOf(expr.properties[0].expression) &&
4556
+ expr.properties.slice(1).every((p) => (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) &&
4557
+ p.name !== undefined &&
4558
+ (ts.isIdentifier(p.name) ||
4559
+ ts.isStringLiteral(p.name) ||
4560
+ ts.isNumericLiteral(p.name) ||
4561
+ (ts.isComputedPropertyName(p.name) && literalComputedKey(L, p.name) !== null)))) {
4562
+ const spread = expr.properties[0];
4563
+ const props = expr.properties.slice(1);
4564
+ const names = props.map((p) => propNameText(L, p.name));
4565
+ const unique = new Set(names);
4566
+ const sourceType = L.mapTypeOf(L.typeOf(spread.expression));
4567
+ if (sourceType?.kind === "record" &&
4568
+ sourceType.shapeId === type.shapeId &&
4569
+ unique.size === names.length &&
4570
+ names.every((name) => fieldTypes.has(name))) {
4571
+ const source = L.lowerExpr(spread.expression);
4572
+ if (source.type.kind === "record" && source.type.shapeId === type.shapeId) {
4573
+ const overrides = [];
4574
+ for (let i = 0; i < props.length; i++) {
4575
+ const p = props[i];
4576
+ const name = names[i];
4577
+ const fieldType = fieldTypes.get(name);
4578
+ const valueNode = ts.isPropertyAssignment(p) ? p.initializer : p;
4579
+ let value = ts.isPropertyAssignment(p)
4580
+ ? L.lowerExpr(p.initializer)
4581
+ : L.lowerShorthandValue(p);
4582
+ value = L.coerceInto(valueNode, value, fieldType);
4583
+ if (!typeEquals(value.type, fieldType))
4584
+ L.badType(valueNode, L.typeOf(valueNode));
4585
+ overrides.push({ name, value });
4586
+ }
4587
+ return { kind: "recordClone", source, overrides, type, loc };
4588
+ }
4589
+ leadingSpreadLowered = source;
4590
+ }
4591
+ }
4530
4592
  // A PURE index-signature target with spreads — `{ ...process.env }`,
4531
4593
  // `{ ...process.env, ...extraEnv }`, `{ ...env, PATH: p }` (the
4532
4594
  // spawn-env pattern): the field-by-field desugar below cannot
@@ -4743,7 +4805,11 @@ export function lowerObjectLiteral(L, expr) {
4743
4805
  let srcNode = prop.expression;
4744
4806
  while (ts.isParenthesizedExpression(srcNode))
4745
4807
  srcNode = srcNode.expression;
4746
- const srcLowered = ts.isIdentifier(srcNode) ? null : L.lowerExpr(srcNode);
4808
+ const srcLowered = prop === expr.properties[0] && leadingSpreadLowered !== null
4809
+ ? leadingSpreadLowered
4810
+ : ts.isIdentifier(srcNode)
4811
+ ? null
4812
+ : L.lowerExpr(srcNode);
4747
4813
  const srcType = srcLowered ? srcLowered.type : L.mapTypeOf(L.typeOf(srcNode));
4748
4814
  // `...options.installConfig` — a spread of `Partial<X> | undefined`
4749
4815
  // (the optional-options merge idiom `{ ...DEFAULTS, ...overrides }`):
@@ -5889,7 +5955,12 @@ export function lowerRecordKeyRead(L, expr, shapeId, shape, includeUndefined = f
5889
5955
  if (dk.type.kind !== "string") {
5890
5956
  L.unsupported("SC1090", keyNode, "indexing records with non-string or non-number keys");
5891
5957
  }
5892
- return L.maybeNarrow({ kind: "dynKeyGet", key: dk, value: obj, type: DYN, loc }, expr);
5958
+ const read = { kind: "dynKeyGet", key: dk, value: obj, type: DYN, loc };
5959
+ // Absence probes must keep the checked-dynamic undefined produced by
5960
+ // a missing key. The ordinary read narrows to the checker's declared
5961
+ // index value (and therefore validates it); ===/!==, ||, and ?? need
5962
+ // to observe the missing value instead of throwing during that check.
5963
+ return includeUndefined ? read : L.maybeNarrow(read, expr);
5893
5964
  }
5894
5965
  if (litKey !== null) {
5895
5966
  const field = shape.fields.find((f) => f.name === litKey);
@@ -5970,6 +6041,13 @@ export function lowerAbsenceProbe(L, node) {
5970
6041
  const target = L.fieldTarget(expr);
5971
6042
  if (target?.container !== "recordOvf")
5972
6043
  return null;
6044
+ // A JS file-scope object-literal global is record-shaped to the
6045
+ // checker but stored in the checked-dynamic tree to preserve object
6046
+ // identity. Reuse the normal dyn-aware field read; constructing a
6047
+ // recordKeyGet here would give the validator a dyn receiver.
6048
+ if (target.obj.type.kind === "dyn") {
6049
+ return L.fieldGetExpr(target, locOf(expr), expr);
6050
+ }
5973
6051
  if (target.fieldType.kind === "union" &&
5974
6052
  L.armTag(target.fieldType.unionId, UNDEFINED_T) >= 0) {
5975
6053
  return null;
@@ -7561,7 +7639,7 @@ function errorRootedObjectOf(L, t) {
7561
7639
  if (rooted(direct))
7562
7640
  return direct;
7563
7641
  if (t.isIntersectionType()) {
7564
- for (const part of t.getTypes()) {
7642
+ for (const part of ts.constituentTypes(t)) {
7565
7643
  const m = L.mapTypeOf(part);
7566
7644
  if (rooted(m))
7567
7645
  return m;
@@ -7816,7 +7894,7 @@ function aliasTypeofArmOf(L, e, strip) {
7816
7894
  const arm = def.arms[tags[0]];
7817
7895
  // The checker-side arm: the union part whose (widened) mapping IS
7818
7896
  // the proven IR arm — what typeOf answers inside the branch.
7819
- const parts = valT.isUnionType() ? valT.getTypes() : [valT];
7897
+ const parts = valT.isUnionType() ? ts.constituentTypes(valT) : [valT];
7820
7898
  const tsArm = parts.find((p) => {
7821
7899
  const m = L.mapTypeOf(L.checker.getBaseTypeOfLiteralType(p));
7822
7900
  return m !== null && typeEquals(m, arm);