@scriptc/compiler 0.0.29 → 0.0.31

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 (49) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +5 -13
  2. package/dist/backend/emission/emit-async.d.ts +1 -0
  3. package/dist/backend/emission/emit-async.js +27 -1
  4. package/dist/backend/emission/emit-async.js.map +1 -1
  5. package/dist/backend/emission/emit-exprs.js +109 -18
  6. package/dist/backend/emission/emit-exprs.js.map +1 -1
  7. package/dist/backend/emission/emitter.d.ts +1 -0
  8. package/dist/backend/emission/emitter.js +25 -3
  9. package/dist/backend/emission/emitter.js.map +1 -1
  10. package/dist/backend/llvm/emitter.js +152 -0
  11. package/dist/backend/llvm/emitter.js.map +1 -1
  12. package/dist/backend/mangle.d.ts +1 -0
  13. package/dist/backend/mangle.js +3 -0
  14. package/dist/backend/mangle.js.map +1 -1
  15. package/dist/diagnostics/diagnostic.d.ts +23 -1
  16. package/dist/diagnostics/diagnostic.js +34 -0
  17. package/dist/diagnostics/diagnostic.js.map +1 -1
  18. package/dist/frontend/lowering/lower-calls.d.ts +3 -1
  19. package/dist/frontend/lowering/lower-calls.js +201 -37
  20. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  21. package/dist/frontend/lowering/lower-containers.d.ts +6 -5
  22. package/dist/frontend/lowering/lower-containers.js +27 -13
  23. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  24. package/dist/frontend/lowering/lower-exprs.d.ts +11 -1
  25. package/dist/frontend/lowering/lower-exprs.js +398 -49
  26. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  27. package/dist/frontend/lowering/lower-server.d.ts +5 -0
  28. package/dist/frontend/lowering/lower-server.js +105 -55
  29. package/dist/frontend/lowering/lower-server.js.map +1 -1
  30. package/dist/frontend/lowering/lower-stmts.js +74 -11
  31. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  32. package/dist/frontend/lowering/lowerer.d.ts +50 -12
  33. package/dist/frontend/lowering/lowerer.js +84 -15
  34. package/dist/frontend/lowering/lowerer.js.map +1 -1
  35. package/dist/index.js +35 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/ir/nodes.d.ts +52 -19
  38. package/dist/ir/nodes.js +2 -2
  39. package/dist/ir/nodes.js.map +1 -1
  40. package/dist/ir/validate.js +67 -9
  41. package/dist/ir/validate.js.map +1 -1
  42. package/dist/library/profile.d.ts +33 -0
  43. package/dist/library/profile.js +161 -3
  44. package/dist/library/profile.js.map +1 -1
  45. package/dist/library/sidecar.d.ts +3 -2
  46. package/dist/library/sidecar.js +7 -3
  47. package/dist/library/sidecar.js.map +1 -1
  48. package/package.json +2 -2
  49. package/surface-manifest.json +1 -1
@@ -20,7 +20,7 @@ import { lowerStreamUnderscoreAssign, streamClassAliasDecl, streamSidesOf } from
20
20
  import { lowerHttpResPropertyAssignment, lowerHttpServerTimeoutAssignment, lowerServerCloseOverrideAssignment } from "./lower-server.js";
21
21
  import { builtinMemberRequireDecl, builtinNamespaceDestructureModuleOf, createRequireBindingDecl, createRequireCalleeFileOf, createRequireNamespaceDecl, textCodecBindingDecl } from "./lower-builtins.js";
22
22
  import { lowerEnumDeclaration } from "./lower-enums.js";
23
- import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerGroupsProjection, matchResultNamedGroupsOf, probeLower, pureReemittable, symbolFieldInfo } from "./lower-exprs.js";
23
+ import { abstractPropertyDeclOf, aliasTypeofNarrows, isMatchSliceType, lowerAbsenceProbe, lowerGroupsProjection, matchResultNamedGroupsOf, probeLower, pureReemittable, runtimeOptionalTrueIds, symbolFieldInfo, withRuntimeOptionalNarrowed } from "./lower-exprs.js";
24
24
  import { checkerPanicDiag, isCheckerPanic, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
25
25
  import { isParseArgsDynTypeName, isUnitOnlyTsType, unitOnlyUnion } from "../types.js";
26
26
  import { canonicalBuiltinModule, isRelativeSpecifier } from "../shared.js";
@@ -704,16 +704,19 @@ export function lowerStmt(L, stmt) {
704
704
  // then-branch lowers under what a TRUE condition proves, the
705
705
  // else-branch under a FALSE one — the var/let alias narrowing the
706
706
  // checker only performs for consts (aliasTypeofNarrows).
707
- const then = L.narrowingAliases(aliasTypeofNarrows(L, stmt.expression, true), () => L.lowerScopedBlock(stmt.thenStatement));
707
+ const then = L.narrowingAliases(aliasTypeofNarrows(L, stmt.expression, true), () => withRuntimeOptionalNarrowed(L, runtimeOptionalTrueIds(L, stmt.expression), () => L.lowerScopedBlock(stmt.thenStatement)));
708
708
  const else_ = stmt.elseStatement
709
709
  ? L.narrowingAliases(aliasTypeofNarrows(L, stmt.expression, false), () => L.lowerScopedBlock(stmt.elseStatement))
710
710
  : null;
711
+ const narrowedAfter = falsyExitRuntimeOptionalLocal(L, stmt);
712
+ if (narrowedAfter !== null)
713
+ L.runtimeOptionalLocals.delete(L.runtimeOptionalRootOf(narrowedAfter));
711
714
  return { kind: "if", cond, then, else_, loc: locOf(stmt) };
712
715
  }
713
716
  if (ts.isWhileStatement(stmt)) {
714
717
  const labels = L.takeLabels();
715
718
  const cond = L.lowerCondition(stmt.expression);
716
- const body = L.inCtl("loop", () => L.lowerScopedBlock(stmt.statement), labels);
719
+ const body = L.inCtl("loop", () => withRuntimeOptionalNarrowed(L, runtimeOptionalTrueIds(L, stmt.expression), () => L.lowerScopedBlock(stmt.statement)), labels);
717
720
  return { kind: "while", cond, body, ...(labels && { labels }), loc: locOf(stmt) };
718
721
  }
719
722
  if (ts.isDoStatement(stmt)) {
@@ -3054,7 +3057,9 @@ export function lowerVarDecl(L, decl, isLet) {
3054
3057
  // later references to this name don't produce cascading errors.
3055
3058
  let init;
3056
3059
  try {
3057
- init = L.lowerExpr(decl.initializer);
3060
+ init = immediatelyGuardedAbsenceProbe(L, decl)
3061
+ ? (lowerAbsenceProbe(L, decl.initializer) ?? L.lowerExpr(decl.initializer))
3062
+ : L.lowerExpr(decl.initializer);
3058
3063
  }
3059
3064
  catch (e) {
3060
3065
  if (e instanceof PoisonError) {
@@ -3134,14 +3139,17 @@ export function lowerVarDecl(L, decl, isLet) {
3134
3139
  }
3135
3140
  }
3136
3141
  }
3137
- // A JS binding holding an OOB-SAFE indexed read (`elem | undefined` —
3138
- // the --npm-static last-element probe) where the checker spells the
3139
- // bare element: the binding adopts the union — the idiom's next line
3140
- // is the truthiness guard, which narrows it right back.
3141
- if (type !== null && init.type.kind === "union" && isJsSourceFile(decl.getSourceFile()) &&
3142
+ // An unannotated binding holding an OOB-SAFE indexed read (`elem |
3143
+ // undefined`) where the checker spells the bare element: the binding
3144
+ // adopts the runtime-honest union. This covers both inferred package JS
3145
+ // and TypeScript's fresh-array probe idioms; an explicit annotation keeps
3146
+ // the caller's checked slot contract.
3147
+ let runtimeOptional = false;
3148
+ if (!decl.type && type !== null && init.type.kind === "union" &&
3142
3149
  L.armTag(init.type.unionId, UNDEFINED_T) >= 0 &&
3143
3150
  typeEquals(L.stripUndefinedArm(init.type), type)) {
3144
3151
  type = init.type;
3152
+ runtimeOptional = true;
3145
3153
  }
3146
3154
  // A JS binding whose checker type spells a FUNCTION but whose VALUE is
3147
3155
  // already checked-dynamic (`const cb = mustCall(fn)` — the helper's
@@ -3158,12 +3166,13 @@ export function lowerVarDecl(L, decl, isLet) {
3158
3166
  // adopt the initializer's type. Checker-`any[]` decls take the same
3159
3167
  // rule (`const tlds = Array.isArray(u) ? u : [u]` — tsc's readonly
3160
3168
  // Array.isArray quirk types the ternary any[], while the arms lower
3161
- // to the union's real array arm). Const only — an evolving-`any`
3169
+ // to the union's real array arm; readonly fixed-tuple narrows adopt
3170
+ // their tuple record likewise). Const only — an evolving-`any`
3162
3171
  // `let` may be reassigned a different shape later; genuine `any`
3163
3172
  // only — every other unmappable keeps its own diagnostic.
3164
3173
  if (type === null && !isLet &&
3165
3174
  ((L.typeOf(decl.name).flags & ts.TypeFlags.Any) !== 0 ||
3166
- (L.checkerAnyArray(decl.name) && init.type.kind === "array") ||
3175
+ (L.checkerAnyArray(decl.name) && L.isArrayValueType(init.type)) ||
3167
3176
  // JS declarations carry no annotations: an unmappable inferred
3168
3177
  // type (a union with a fence-folded arm — the typeof-'bigint'
3169
3178
  // dual-mode ternary) adopts the initializer's static type, the
@@ -3275,8 +3284,59 @@ export function lowerVarDecl(L, decl, isLet) {
3275
3284
  // subtyping (`const p: {a: number} = wider;`) is rejected, not coerced.
3276
3285
  init = L.coerceInto(decl.initializer, init, type);
3277
3286
  const local = L.declareLocal(decl.name, decl.name.text, type, isLet);
3287
+ if (runtimeOptional) {
3288
+ const runtimeOptionalRoot = L.runtimeOptionalRootOf(local);
3289
+ L.runtimeOptionalLocals.add(runtimeOptionalRoot);
3290
+ L.runtimeOptionalStorageLocals.add(runtimeOptionalRoot);
3291
+ }
3278
3292
  return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
3279
3293
  }
3294
+ function immediatelyGuardedAbsenceProbe(L, decl) {
3295
+ if (decl.type || !ts.isIdentifier(decl.name) || !decl.initializer)
3296
+ return false;
3297
+ const statement = decl.parent?.parent;
3298
+ if (!statement || !ts.isVariableStatement(statement))
3299
+ return false;
3300
+ const container = statement.parent;
3301
+ const statements = ts.isBlock(container) || ts.isSourceFile(container) ? container.statements : null;
3302
+ if (!statements)
3303
+ return false;
3304
+ const index = statements.indexOf(statement);
3305
+ const next = index >= 0 ? statements[index + 1] : undefined;
3306
+ if (!next || !ts.isIfStatement(next))
3307
+ return false;
3308
+ let condition = next.expression;
3309
+ while (ts.isParenthesizedExpression(condition))
3310
+ condition = condition.expression;
3311
+ if (!ts.isPrefixUnaryExpression(condition) || condition.operator !== ts.SyntaxKind.ExclamationToken)
3312
+ return false;
3313
+ let operand = condition.operand;
3314
+ while (ts.isParenthesizedExpression(operand))
3315
+ operand = operand.expression;
3316
+ return ts.isIdentifier(operand) && L.resolveValueSymbol(operand) === L.resolveValueSymbol(decl.name);
3317
+ }
3318
+ function falsyExitRuntimeOptionalLocal(L, stmt) {
3319
+ if (stmt.elseStatement)
3320
+ return null;
3321
+ let condition = stmt.expression;
3322
+ while (ts.isParenthesizedExpression(condition))
3323
+ condition = condition.expression;
3324
+ if (!ts.isPrefixUnaryExpression(condition) || condition.operator !== ts.SyntaxKind.ExclamationToken)
3325
+ return null;
3326
+ let operand = condition.operand;
3327
+ while (ts.isParenthesizedExpression(operand))
3328
+ operand = operand.expression;
3329
+ if (!ts.isIdentifier(operand))
3330
+ return null;
3331
+ const local = L.resolveLocal(operand);
3332
+ if (!local || !L.runtimeOptionalLocals.has(L.runtimeOptionalRootOf(local)))
3333
+ return null;
3334
+ const exits = ts.isReturnStatement(stmt.thenStatement) || ts.isThrowStatement(stmt.thenStatement) ||
3335
+ (ts.isBlock(stmt.thenStatement) && stmt.thenStatement.statements.length > 0 &&
3336
+ (ts.isReturnStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1]) ||
3337
+ ts.isThrowStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1])));
3338
+ return exits ? local : null;
3339
+ }
3280
3340
  /** JS-exact switch (see docs/ir.md): one shared lexical scope for all case
3281
3341
  * bodies, lazy source-order test evaluation, fall-through. tsc has already
3282
3342
  * checked case-test comparability (TS2678) — the kind check below is the
@@ -4261,6 +4321,9 @@ export function lowerExprStatement(L, expr) {
4261
4321
  if (!target)
4262
4322
  L.rejectUnresolved(expr.left, `assignment to '${expr.left.text}' (not a writable local or module global)`);
4263
4323
  const value = L.lowerExprExpecting(expr.right, target.type);
4324
+ const runtimeOptionalRoot = L.runtimeOptionalRootOf(target);
4325
+ if (L.runtimeOptionalStorageLocals.has(runtimeOptionalRoot))
4326
+ L.runtimeOptionalLocals.add(runtimeOptionalRoot);
4264
4327
  return { kind: "assign", localId: target.id, value, loc: locOf(expr) };
4265
4328
  }
4266
4329
  if (opKind === ts.SyntaxKind.QuestionQuestionEqualsToken) {