@scriptc/compiler 0.0.29 → 0.0.30

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 +196 -33
  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 +15 -11
  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 +366 -25
  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 +71 -9
  31. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  32. package/dist/frontend/lowering/lowerer.d.ts +24 -5
  33. package/dist/frontend/lowering/lowerer.js +28 -4
  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
@@ -3275,8 +3283,59 @@ export function lowerVarDecl(L, decl, isLet) {
3275
3283
  // subtyping (`const p: {a: number} = wider;`) is rejected, not coerced.
3276
3284
  init = L.coerceInto(decl.initializer, init, type);
3277
3285
  const local = L.declareLocal(decl.name, decl.name.text, type, isLet);
3286
+ if (runtimeOptional) {
3287
+ const runtimeOptionalRoot = L.runtimeOptionalRootOf(local);
3288
+ L.runtimeOptionalLocals.add(runtimeOptionalRoot);
3289
+ L.runtimeOptionalStorageLocals.add(runtimeOptionalRoot);
3290
+ }
3278
3291
  return { kind: "varDecl", localId: local.id, init, loc: locOf(decl) };
3279
3292
  }
3293
+ function immediatelyGuardedAbsenceProbe(L, decl) {
3294
+ if (decl.type || !ts.isIdentifier(decl.name) || !decl.initializer)
3295
+ return false;
3296
+ const statement = decl.parent?.parent;
3297
+ if (!statement || !ts.isVariableStatement(statement))
3298
+ return false;
3299
+ const container = statement.parent;
3300
+ const statements = ts.isBlock(container) || ts.isSourceFile(container) ? container.statements : null;
3301
+ if (!statements)
3302
+ return false;
3303
+ const index = statements.indexOf(statement);
3304
+ const next = index >= 0 ? statements[index + 1] : undefined;
3305
+ if (!next || !ts.isIfStatement(next))
3306
+ return false;
3307
+ let condition = next.expression;
3308
+ while (ts.isParenthesizedExpression(condition))
3309
+ condition = condition.expression;
3310
+ if (!ts.isPrefixUnaryExpression(condition) || condition.operator !== ts.SyntaxKind.ExclamationToken)
3311
+ return false;
3312
+ let operand = condition.operand;
3313
+ while (ts.isParenthesizedExpression(operand))
3314
+ operand = operand.expression;
3315
+ return ts.isIdentifier(operand) && L.resolveValueSymbol(operand) === L.resolveValueSymbol(decl.name);
3316
+ }
3317
+ function falsyExitRuntimeOptionalLocal(L, stmt) {
3318
+ if (stmt.elseStatement)
3319
+ return null;
3320
+ let condition = stmt.expression;
3321
+ while (ts.isParenthesizedExpression(condition))
3322
+ condition = condition.expression;
3323
+ if (!ts.isPrefixUnaryExpression(condition) || condition.operator !== ts.SyntaxKind.ExclamationToken)
3324
+ return null;
3325
+ let operand = condition.operand;
3326
+ while (ts.isParenthesizedExpression(operand))
3327
+ operand = operand.expression;
3328
+ if (!ts.isIdentifier(operand))
3329
+ return null;
3330
+ const local = L.resolveLocal(operand);
3331
+ if (!local || !L.runtimeOptionalLocals.has(L.runtimeOptionalRootOf(local)))
3332
+ return null;
3333
+ const exits = ts.isReturnStatement(stmt.thenStatement) || ts.isThrowStatement(stmt.thenStatement) ||
3334
+ (ts.isBlock(stmt.thenStatement) && stmt.thenStatement.statements.length > 0 &&
3335
+ (ts.isReturnStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1]) ||
3336
+ ts.isThrowStatement(stmt.thenStatement.statements[stmt.thenStatement.statements.length - 1])));
3337
+ return exits ? local : null;
3338
+ }
3280
3339
  /** JS-exact switch (see docs/ir.md): one shared lexical scope for all case
3281
3340
  * bodies, lazy source-order test evaluation, fall-through. tsc has already
3282
3341
  * checked case-test comparability (TS2678) — the kind check below is the
@@ -4261,6 +4320,9 @@ export function lowerExprStatement(L, expr) {
4261
4320
  if (!target)
4262
4321
  L.rejectUnresolved(expr.left, `assignment to '${expr.left.text}' (not a writable local or module global)`);
4263
4322
  const value = L.lowerExprExpecting(expr.right, target.type);
4323
+ const runtimeOptionalRoot = L.runtimeOptionalRootOf(target);
4324
+ if (L.runtimeOptionalStorageLocals.has(runtimeOptionalRoot))
4325
+ L.runtimeOptionalLocals.add(runtimeOptionalRoot);
4264
4326
  return { kind: "assign", localId: target.id, value, loc: locOf(expr) };
4265
4327
  }
4266
4328
  if (opKind === ts.SyntaxKind.QuestionQuestionEqualsToken) {