@scriptc/compiler 0.1.6 → 0.1.7

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 (116) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +0 -1
  2. package/ambient/scriptc.d.ts +13 -5
  3. package/dist/backend/c/c-emitter.d.ts +5 -0
  4. package/dist/backend/c/c-emitter.js +15 -0
  5. package/dist/backend/c/c-emitter.js.map +1 -1
  6. package/dist/backend/c/exprs.js +45 -1
  7. package/dist/backend/c/exprs.js.map +1 -1
  8. package/dist/backend/c/stmts.js +25 -1
  9. package/dist/backend/c/stmts.js.map +1 -1
  10. package/dist/backend/c/walkers.js +2 -3
  11. package/dist/backend/c/walkers.js.map +1 -1
  12. package/dist/backend/debug-symbols.d.ts +8 -0
  13. package/dist/backend/debug-symbols.js +52 -0
  14. package/dist/backend/debug-symbols.js.map +1 -0
  15. package/dist/backend/link-plan.d.ts +1 -0
  16. package/dist/backend/link-plan.js +2 -0
  17. package/dist/backend/link-plan.js.map +1 -1
  18. package/dist/backend/linker.js +8 -0
  19. package/dist/backend/linker.js.map +1 -1
  20. package/dist/backend/llvm/blocks.d.ts +2 -0
  21. package/dist/backend/llvm/blocks.js +18 -2
  22. package/dist/backend/llvm/blocks.js.map +1 -1
  23. package/dist/backend/llvm/debug-info.d.ts +32 -0
  24. package/dist/backend/llvm/debug-info.js +203 -0
  25. package/dist/backend/llvm/debug-info.js.map +1 -0
  26. package/dist/backend/llvm/dyn.js +4 -10
  27. package/dist/backend/llvm/dyn.js.map +1 -1
  28. package/dist/backend/llvm/emitter.d.ts +2 -0
  29. package/dist/backend/llvm/emitter.js +49 -4
  30. package/dist/backend/llvm/emitter.js.map +1 -1
  31. package/dist/backend/llvm/expr-dynamic.js +10 -0
  32. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  33. package/dist/backend/llvm/lib-filesystem.js +29 -0
  34. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  35. package/dist/backend/llvm/lib-shared.js +8 -0
  36. package/dist/backend/llvm/lib-shared.js.map +1 -1
  37. package/dist/backend/llvm/split.js +4 -1
  38. package/dist/backend/llvm/split.js.map +1 -1
  39. package/dist/backend/llvm/split.test.js +26 -1
  40. package/dist/backend/llvm/split.test.js.map +1 -1
  41. package/dist/backend/native-toolchain.js +58 -8
  42. package/dist/backend/native-toolchain.js.map +1 -1
  43. package/dist/backend/native-toolchain.test.js +10 -0
  44. package/dist/backend/native-toolchain.test.js.map +1 -1
  45. package/dist/backend/source-locations.d.ts +12 -0
  46. package/dist/backend/source-locations.js +32 -0
  47. package/dist/backend/source-locations.js.map +1 -0
  48. package/dist/backend/source-locations.test.d.ts +1 -0
  49. package/dist/backend/source-locations.test.js +16 -0
  50. package/dist/backend/source-locations.test.js.map +1 -0
  51. package/dist/diagnostics/diagnostic.d.ts +4 -0
  52. package/dist/diagnostics/diagnostic.js +12 -0
  53. package/dist/diagnostics/diagnostic.js.map +1 -1
  54. package/dist/executable/executable-cache.js +28 -4
  55. package/dist/executable/executable-cache.js.map +1 -1
  56. package/dist/executable/executable-cache.test.js +23 -0
  57. package/dist/executable/executable-cache.test.js.map +1 -1
  58. package/dist/frontend/arguments-usage.d.ts +6 -0
  59. package/dist/frontend/arguments-usage.js +40 -0
  60. package/dist/frontend/arguments-usage.js.map +1 -0
  61. package/dist/frontend/binding-source.d.ts +4 -0
  62. package/dist/frontend/binding-source.js +18 -0
  63. package/dist/frontend/binding-source.js.map +1 -0
  64. package/dist/frontend/lowering/expressions/object-literals.js +13 -8
  65. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  66. package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
  67. package/dist/frontend/lowering/expressions/optional-chains.js +7 -6
  68. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  69. package/dist/frontend/lowering/lower-builtins.js +15 -4
  70. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  71. package/dist/frontend/lowering/lower-calls.d.ts +2 -9
  72. package/dist/frontend/lowering/lower-calls.js +140 -30
  73. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  74. package/dist/frontend/lowering/lower-exprs.js +116 -16
  75. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  76. package/dist/frontend/lowering/lower-island.d.ts +1 -1
  77. package/dist/frontend/lowering/lower-island.js +1 -1
  78. package/dist/frontend/lowering/lower-modules.js +19 -8
  79. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  80. package/dist/frontend/lowering/lower-stmts.js +4 -37
  81. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  82. package/dist/frontend/lowering/lowerer.js +14 -3
  83. package/dist/frontend/lowering/lowerer.js.map +1 -1
  84. package/dist/frontend/lowering/surfaces.d.ts +1 -1
  85. package/dist/frontend/lowering/surfaces.js +37 -6
  86. package/dist/frontend/lowering/surfaces.js.map +1 -1
  87. package/dist/frontend/program.d.ts +5 -0
  88. package/dist/frontend/program.js +216 -32
  89. package/dist/frontend/program.js.map +1 -1
  90. package/dist/frontend/program.test.d.ts +1 -0
  91. package/dist/frontend/program.test.js +117 -0
  92. package/dist/frontend/program.test.js.map +1 -0
  93. package/dist/frontend/type-mapper.d.ts +4 -2
  94. package/dist/frontend/type-mapper.js +249 -186
  95. package/dist/frontend/type-mapper.js.map +1 -1
  96. package/dist/frontend/type-mapper.test.d.ts +1 -0
  97. package/dist/frontend/type-mapper.test.js +86 -0
  98. package/dist/frontend/type-mapper.test.js.map +1 -0
  99. package/dist/index.d.ts +2 -1
  100. package/dist/index.js +7 -2
  101. package/dist/index.js.map +1 -1
  102. package/dist/ir/analysis.js +4 -2
  103. package/dist/ir/analysis.js.map +1 -1
  104. package/dist/ir/ir.d.ts +18 -12
  105. package/dist/ir/ir.js +3 -1
  106. package/dist/ir/ir.js.map +1 -1
  107. package/dist/ir/validate.js +14 -5
  108. package/dist/ir/validate.js.map +1 -1
  109. package/dist/library/compiler-self-identity.d.ts +1 -1
  110. package/dist/library/compiler-self-identity.js +31 -15
  111. package/dist/library/compiler-self-identity.js.map +1 -1
  112. package/dist/library/compiler-self-identity.test.d.ts +1 -0
  113. package/dist/library/compiler-self-identity.test.js +93 -0
  114. package/dist/library/compiler-self-identity.test.js.map +1 -0
  115. package/package.json +17 -17
  116. package/surface-manifest.json +120 -1
@@ -127,6 +127,25 @@ function jsoncSyntaxError(text) {
127
127
  return e instanceof Error ? e.message : String(e);
128
128
  }
129
129
  }
130
+ /** Preserve TypeScript 5.9's computed synthetic-default permission from the
131
+ * project's own module settings. Preflight later forces ESNext/Bundler for
132
+ * scriptc's checker, so those forced options must not decide which source
133
+ * import forms were legal in the original project. */
134
+ function projectAllowsSyntheticDefaultImports(options) {
135
+ const explicitSyntheticDefaultImports = options["allowSyntheticDefaultImports"];
136
+ if (explicitSyntheticDefaultImports !== undefined)
137
+ return explicitSyntheticDefaultImports === true;
138
+ const moduleKind = options["module"];
139
+ const explicitEsModuleInterop = options["esModuleInterop"];
140
+ const esModuleInterop = explicitEsModuleInterop !== undefined
141
+ ? explicitEsModuleInterop === true
142
+ : moduleKind === ts.ModuleKind.Node16 ||
143
+ moduleKind === ts.ModuleKind.Node18 ||
144
+ moduleKind === ts.ModuleKind.Node20 ||
145
+ moduleKind === ts.ModuleKind.NodeNext ||
146
+ moduleKind === ts.ModuleKind.Preserve;
147
+ return esModuleInterop || moduleKind === ts.ModuleKind.System || options["moduleResolution"] === ts.ModuleResolutionKind.Bundler;
148
+ }
130
149
  /** The project's tsconfig adoption in the 7 world: tsgo's own config parser
131
150
  * (extends chains resolved server-side), the ADOPTED_OPTIONS subset taken,
132
151
  * the rest forced, the strictNullChecks floor enforced. */
@@ -148,6 +167,9 @@ function adoptProjectConfig7(host, entryPath) {
148
167
  if (value !== undefined)
149
168
  adopted[key] = value;
150
169
  }
170
+ if (projectAllowsSyntheticDefaultImports(parsed.options)) {
171
+ adopted["allowSyntheticDefaultImports"] = true;
172
+ }
151
173
  // TS 7 accepts `paths`, but no longer accepts `baseUrl` as a compiler
152
174
  // option. Translate the established baseUrl+paths spelling into absolute
153
175
  // targets: the synthesized config lives beside the entry rather than the
@@ -374,7 +396,10 @@ function createRequireProgramRoots7(program) {
374
396
  target = npm.typesFile;
375
397
  }
376
398
  }
377
- if (target === null || target.endsWith(".json"))
399
+ // A directory's package.json may point at a native addon. Keep it
400
+ // out of TypeScript's source roots so the require call can report
401
+ // the native-addon boundary instead of an unsupported-file error.
402
+ if (target === null || target.endsWith(".json") || target.endsWith(".node"))
378
403
  return "skip";
379
404
  const normalized = tsgoPath(resolve(target));
380
405
  if (!known.has(normalized))
@@ -384,6 +409,41 @@ function createRequireProgramRoots7(program) {
384
409
  }
385
410
  return [...roots].sort();
386
411
  }
412
+ /** Classify the explicitly selected installed package's own sources. */
413
+ export function entryPackageFilePredicate(entryPath) {
414
+ const entryFile = tsgoPath(entryPath);
415
+ const installedAt = entryFile.lastIndexOf("/node_modules/");
416
+ const prefix = installedAt < 0
417
+ ? null
418
+ : entryFile.slice(0, installedAt) + "/node_modules/" + npmPackageNameOf(entryFile) + "/";
419
+ return (file) => {
420
+ const normalized = tsgoPath(file);
421
+ return normalized === entryFile || (prefix !== null && normalized.startsWith(prefix) &&
422
+ !normalized.slice(prefix.length).split("/").includes("node_modules"));
423
+ };
424
+ }
425
+ /** maxNodeModuleJsDepth omits even relative JS imports within an installed
426
+ * entry's own package. Add those sources as roots to the existing discovery
427
+ * fixpoint without raising the checker depth for other packages. */
428
+ function entryPackageProgramRoots7(program, entryPath) {
429
+ if (!isNodeModulesPath(entryPath))
430
+ return [];
431
+ const belongsToEntry = entryPackageFilePredicate(entryPath);
432
+ const roots = new Set();
433
+ for (const sf of program.getSourceFiles()) {
434
+ if (sf.isDeclarationFile || !belongsToEntry(sf.fileName))
435
+ continue;
436
+ for (const specifier of sf.imports) {
437
+ if (!ts.isStringLiteralLike(specifier))
438
+ continue;
439
+ const target = resolveProjectModule(sf.fileName, specifier.text);
440
+ if (target !== null && belongsToEntry(target) && isJsSourceFileName(target) &&
441
+ program.getSourceFile(target) === undefined)
442
+ roots.add(target);
443
+ }
444
+ }
445
+ return [...roots].sort();
446
+ }
387
447
  function loadProgram7(host, entryPath, externalTypes = new Map()) {
388
448
  const config = adoptProjectConfig7(host, entryPath);
389
449
  const configuredPaths = config.options["paths"];
@@ -425,6 +485,7 @@ function loadProgram7(host, entryPath, externalTypes = new Map()) {
425
485
  let program = ts.createProgram([...programRoots, overridesDtsPath()], options, host);
426
486
  for (let pass = 0; pass < 32; pass++) {
427
487
  const candidates = [
488
+ ...entryPackageProgramRoots7(program, entryPath),
428
489
  ...createRequireProgramRoots7(program),
429
490
  ...forkTargetPaths(program, program.getSourceFiles()),
430
491
  ];
@@ -663,25 +724,134 @@ function requiresOf7(stmt) {
663
724
  }
664
725
  return out;
665
726
  }
727
+ /** The exact `Object.defineProperty(exports|module.exports, "__esModule",
728
+ * { value: true })` interop stamp (shared by preflight and the no-op lowering). */
729
+ export function isEsModuleStamp(expr) {
730
+ if (!ts.isCallExpression(expr) || expr.questionDotToken !== undefined)
731
+ return false;
732
+ const callee = expr.expression;
733
+ if (!ts.isPropertyAccessExpression(callee) ||
734
+ !ts.isIdentifier(callee.expression) ||
735
+ callee.expression.text !== "Object" ||
736
+ !ts.isIdentifier(callee.name) ||
737
+ callee.name.text !== "defineProperty") {
738
+ return false;
739
+ }
740
+ if (expr.arguments.length !== 3)
741
+ return false;
742
+ const [recv, nameArg, desc] = expr.arguments;
743
+ const isExports = (ts.isIdentifier(recv) && recv.text === "exports") ||
744
+ (ts.isPropertyAccessExpression(recv) &&
745
+ ts.isIdentifier(recv.expression) &&
746
+ recv.expression.text === "module" &&
747
+ ts.isIdentifier(recv.name) &&
748
+ recv.name.text === "exports");
749
+ if (!isExports)
750
+ return false;
751
+ if (!ts.isStringLiteral(nameArg) || nameArg.text !== "__esModule")
752
+ return false;
753
+ if (!ts.isObjectLiteralExpression(desc) || desc.properties.length !== 1)
754
+ return false;
755
+ const p = desc.properties[0];
756
+ return (ts.isPropertyAssignment(p) &&
757
+ ts.isIdentifier(p.name) &&
758
+ p.name.text === "value" &&
759
+ p.initializer.kind === ts.SyntaxKind.TrueKeyword);
760
+ }
761
+ /** Plain CommonJS prologue writes only publish values; in particular,
762
+ * publishing a hoisted function does not invoke its body. Later runnable
763
+ * statements may call the export or mutate its receiver, and still need
764
+ * the conservative TDZ scan over the whole prefix. */
765
+ function pureCjsExport7(program, stmt) {
766
+ const cjs = cjsExportAssignmentOf(stmt);
767
+ if (cjs === null)
768
+ return false;
769
+ const sf = stmt.getSourceFile();
770
+ const plainMember = (left) => {
771
+ if (!ts.isPropertyAccessExpression(left) || left.questionDotToken)
772
+ return false;
773
+ // A replacement export can have setters or non-writable function
774
+ // properties. Only the wrapper's original object gets this exception.
775
+ if (sf.statements.some((s) => cjsExportAssignmentOf(s)?.kind === "table"))
776
+ return false;
777
+ if (left.name.text === "__proto__" || left.name.text === "__esModule")
778
+ return false;
779
+ let receiver = left.expression;
780
+ if (isModuleExportsAccess(receiver)) {
781
+ receiver = receiver.expression;
782
+ return ts.isIdentifier(receiver) && !sourceBinding7(program, receiver);
783
+ }
784
+ return ts.isIdentifier(receiver) && receiver.text === "exports" && !sourceBinding7(program, receiver);
785
+ };
786
+ if (cjs.kind === "member") {
787
+ if (!plainMember(cjs.expr.left))
788
+ return false;
789
+ }
790
+ else {
791
+ const receiver = cjs.expr.left.expression;
792
+ if (sourceBinding7(program, receiver))
793
+ return false;
794
+ }
795
+ let value = cjs.expr.right;
796
+ // tsc emits chains such as exports.A = exports.B = void 0.
797
+ while (ts.isBinaryExpression(value) && value.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
798
+ if (!plainMember(value.left))
799
+ return false;
800
+ value = value.right;
801
+ }
802
+ if (ts.isVoidExpression(value) && ts.isNumericLiteral(value.expression))
803
+ return true;
804
+ if (ts.isStringLiteralLike(value) || ts.isNumericLiteral(value) ||
805
+ value.kind === ts.SyntaxKind.TrueKeyword || value.kind === ts.SyntaxKind.FalseKeyword ||
806
+ value.kind === ts.SyntaxKind.NullKeyword)
807
+ return true;
808
+ if (!ts.isIdentifier(value))
809
+ return false;
810
+ if (value.text === "undefined" && !sourceBinding7(program, value))
811
+ return true;
812
+ const checker = program.getTypeChecker();
813
+ const symbol = checker.getSymbolAtLocation(value);
814
+ return symbol !== undefined && checker.declarationsOf(symbol).some((decl) => ts.isFunctionDeclaration(decl) && decl.parent === stmt.parent);
815
+ }
816
+ function sourceBinding7(program, ident) {
817
+ const checker = program.getTypeChecker();
818
+ const symbol = checker.getSymbolAtLocation(ident);
819
+ return symbol !== undefined && checker.declarationsOf(symbol).some((decl) => !decl.getSourceFile().isDeclarationFile && !ts.isSourceFile(decl));
820
+ }
821
+ function purePrefixDecl7(decl) {
822
+ const init = decl.initializer;
823
+ return init === undefined || requireSpecOf7(init) !== null ||
824
+ ts.isStringLiteralLike(init) || ts.isNumericLiteral(init) ||
825
+ init.kind === ts.SyntaxKind.TrueKeyword || init.kind === ts.SyntaxKind.FalseKeyword ||
826
+ init.kind === ts.SyntaxKind.NullKeyword;
827
+ }
666
828
  /** True for top-level statements that cannot run user code: directives,
667
829
  * empty statements, hoisted declarations, require statements themselves,
668
- * and literal-initialized variables. A require preceded ONLY by these can
669
- * never have its bindings observed early — nothing above it executes. */
670
- function purePrefixStmt7(s) {
830
+ * literal-initialized variables, and CommonJS function-export prologues.
831
+ * A require preceded ONLY by these cannot observe its own bindings early;
832
+ * require cycles are checked separately by the module graph fences. */
833
+ function purePrefixStmt7(program, s) {
671
834
  if (ts.isEmptyStatement(s) || ts.isFunctionDeclaration(s))
672
835
  return true;
673
836
  if (ts.isExpressionStatement(s) && ts.isStringLiteral(s.expression))
674
837
  return true; // directive
675
838
  if (isRequireStatement7(s))
676
839
  return true;
840
+ if (isCjsJsFile7(s.getSourceFile())) {
841
+ if (ts.isExpressionStatement(s) && isEsModuleStamp(s.expression)) {
842
+ const call = s.expression;
843
+ const object = call.expression.expression;
844
+ let receiver = call.arguments[0];
845
+ if (ts.isPropertyAccessExpression(receiver))
846
+ receiver = receiver.expression;
847
+ if (!sourceBinding7(program, object) && ts.isIdentifier(receiver) && !sourceBinding7(program, receiver))
848
+ return true;
849
+ }
850
+ if (pureCjsExport7(program, s))
851
+ return true;
852
+ }
677
853
  if (ts.isVariableStatement(s)) {
678
- return s.declarationList.declarations.every((d) => d.initializer === undefined ||
679
- requireSpecOf7(d.initializer) !== null ||
680
- ts.isStringLiteralLike(d.initializer) ||
681
- ts.isNumericLiteral(d.initializer) ||
682
- d.initializer.kind === ts.SyntaxKind.TrueKeyword ||
683
- d.initializer.kind === ts.SyntaxKind.FalseKeyword ||
684
- d.initializer.kind === ts.SyntaxKind.NullKeyword);
854
+ return s.declarationList.declarations.every(purePrefixDecl7);
685
855
  }
686
856
  return false;
687
857
  }
@@ -700,7 +870,7 @@ function purePrefixStmt7(s) {
700
870
  * (The CheckerFacade memoizes symbol queries, and 7's client dedupes
701
871
  * symbol identity by server handle, so the Map-keyed-by-Symbol discipline
702
872
  * carries over from the 5.9.3 original unchanged.) */
703
- function requireTdzRisk7(program, sf, k, decl) {
873
+ function requireTdzRisk7(program, sf, k, decl, precedingDecls) {
704
874
  const checker = program.getTypeChecker();
705
875
  const bound = [];
706
876
  if (ts.isIdentifier(decl.name))
@@ -756,12 +926,15 @@ function requireTdzRisk7(program, sf, k, decl) {
756
926
  // These are the exact roots the TDZ analysis scans eagerly. Their files
757
927
  // are phase-managed already, so warm their deferred identifiers as one
758
928
  // symbol-only batch instead of paying one IPC query per occurrence.
759
- checker.prefetchSymbolRoots(stmts.slice(0, k).filter((stmt) => !ts.isFunctionDeclaration(stmt)));
760
- for (let i = 0; i < k && hit === null; i++) {
761
- const s = stmts[i];
762
- if (ts.isFunctionDeclaration(s))
763
- continue;
764
- scan(s);
929
+ const roots = [
930
+ ...stmts.slice(0, k).filter((stmt) => !ts.isFunctionDeclaration(stmt)),
931
+ ...precedingDecls,
932
+ ];
933
+ checker.prefetchSymbolRoots(roots);
934
+ for (const root of roots) {
935
+ if (hit !== null)
936
+ break;
937
+ scan(root);
765
938
  }
766
939
  while (hit === null && work.length > 0) {
767
940
  // A scanned reference can make a hoisted declaration's body reachable
@@ -1681,6 +1854,12 @@ export function checkPreflightTs7(entryPath, sharedHost) {
1681
1854
  function preflight7(load) {
1682
1855
  const { program, entry } = load;
1683
1856
  const diags = [...load.configDiags];
1857
+ // An explicit entry can itself live in an installed package. Its own
1858
+ // source files are program code, including relative barrels and sibling
1859
+ // modules; their location must not silently erase the module graph.
1860
+ // Match the full installed directory, not just the package name, and
1861
+ // exclude nested installations so dependencies keep their npm policy.
1862
+ const entryPackageFile = entryPackageFilePredicate(entry.fileName);
1684
1863
  // Workspace-linked packages register BEFORE the tsc gate. Their files
1685
1864
  // live at realpaths OUTSIDE node_modules (the monorepo-tool symlink
1686
1865
  // shape), so nothing path-shaped marks them as npm surface — yet their
@@ -1808,6 +1987,7 @@ function preflight7(load) {
1808
1987
  * pass above), suppressed here unless --npm-static opted them into being
1809
1988
  * program modules. */
1810
1989
  const islandJsFile = (file) => isJsSourceFileName(file) &&
1990
+ !entryPackageFile(file) &&
1811
1991
  npmStaticPackageOfPath(file) === null &&
1812
1992
  (isNodeModulesPath(file) || workspacePackageOfPath(file) !== null);
1813
1993
  const nodeModulesJsSuppressed = (d) => d.fileName !== undefined && islandJsFile(d.fileName);
@@ -1914,7 +2094,7 @@ function preflight7(load) {
1914
2094
  .filter((sf) => sf.fileName !== ambient &&
1915
2095
  !sf.isDeclarationFile &&
1916
2096
  !sf.fileName.endsWith(".json") &&
1917
- (!isNodeModulesPath(sf.fileName) || npmStaticPackageOfPath(sf.fileName) !== null) &&
2097
+ (!isNodeModulesPath(sf.fileName) || entryPackageFile(sf.fileName) || npmStaticPackageOfPath(sf.fileName) !== null) &&
1918
2098
  !islandJsFile(sf.fileName));
1919
2099
  const userFiles = npmStaticActive()
1920
2100
  ? planNpmStaticReexports(program, entry, programFiles, [...createRequireProgramRoots7(program), ...forkTargetPaths(program, program.getSourceFiles())], (sf, spec) => resolveImport7(program, sf, spec) ?? npmStaticDepSf7(program, sf, spec))
@@ -2245,17 +2425,13 @@ function preflight7(load) {
2245
2425
  // surface and the lowering keys the same tables
2246
2426
  // (builtinNamespaceModuleOf's default-import twin). JS sources
2247
2427
  // always (Node never asks for interop flags); TS sources when the
2248
- // adopted interop knobs made the checker accept the spelling
2249
- // (the `import os from 'os'` spelling under esModuleInterop — the
2250
- // program TYPECHECKED, so the form is the project's own legal
2251
- // dialect). A TS project without interop flags keeps the fence:
2252
- // the SC1012 wording beats the raw TS1259 at the same site. The
2253
- // callable module objects (assert, events, test) stay allowed
2254
- // everywhere.
2255
- const opts = program.getCompilerOptions();
2256
- const interopOn = opts.esModuleInterop === true || opts.allowSyntheticDefaultImports === true;
2428
+ // project's explicit or implied synthetic-default permission accepts
2429
+ // the spelling. A TS project without that permission keeps the
2430
+ // SC1012 fence. The callable module objects (assert, events, test)
2431
+ // stay allowed everywhere.
2432
+ const syntheticDefaultsOn = program.getCompilerOptions().allowSyntheticDefaultImports === true;
2257
2433
  const defaultOk = builtinDefaultImportModule(spec) !== null ||
2258
- ((isJsSourceFileName(sf.fileName) || interopOn) && canonicalBuiltinModule(spec) !== null);
2434
+ ((isJsSourceFileName(sf.fileName) || syntheticDefaultsOn) && canonicalBuiltinModule(spec) !== null);
2259
2435
  if (clause.name && !isJson && dep === null && !defaultOk) {
2260
2436
  diags.push(unsupportedDiag("SC1012", locOf7(clause.name)));
2261
2437
  }
@@ -2304,7 +2480,7 @@ function preflight7(load) {
2304
2480
  const stmts = sf.statements;
2305
2481
  let firstRunnable = -1;
2306
2482
  stmts.forEach((s, i) => {
2307
- if (firstRunnable < 0 && !purePrefixStmt7(s))
2483
+ if (firstRunnable < 0 && !purePrefixStmt7(program, s))
2308
2484
  firstRunnable = i;
2309
2485
  });
2310
2486
  for (let k = 0; k < stmts.length; k++) {
@@ -2381,8 +2557,16 @@ function preflight7(load) {
2381
2557
  diags.push(unsupportedDiag("SC1012", loc, "require() of JSON modules"));
2382
2558
  continue;
2383
2559
  }
2384
- const tdzName = firstRunnable >= 0 && firstRunnable < k && req.decl
2385
- ? requireTdzRisk7(program, sf, k, req.decl)
2560
+ // Earlier declarators run too: `const x = read(), dep =
2561
+ // require('./dep')` must not lose the guard merely because both
2562
+ // initializers share one VariableStatement.
2563
+ const precedingDecls = req.decl && ts.isVariableStatement(stmt)
2564
+ ? stmt.declarationList.declarations.slice(0, stmt.declarationList.declarations.indexOf(req.decl))
2565
+ : [];
2566
+ const prefixCanRun = (firstRunnable >= 0 && firstRunnable < k) ||
2567
+ precedingDecls.some((decl) => !purePrefixDecl7(decl));
2568
+ const tdzName = prefixCanRun && req.decl
2569
+ ? requireTdzRisk7(program, sf, k, req.decl, precedingDecls)
2386
2570
  : null;
2387
2571
  if (tdzName !== null) {
2388
2572
  diags.push(unsupportedDiag("SC1013", loc, `require() below code that can reach its binding '${tdzName}' (Node initializes the binding AT the require and throws ReferenceError on any earlier access, which is not modeled — move the require above the code that can run first)`));