tsc-ts 0.0.5 → 0.0.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.
Files changed (171) hide show
  1. package/README.md +1 -1
  2. package/dist/api/compiler/ast.d.ts +10 -9
  3. package/dist/api/compiler/ast.js +22 -16
  4. package/dist/api/compiler/binder-utilities.js +2 -1
  5. package/dist/api/compiler/binder.js +9 -8
  6. package/dist/api/compiler/checker-calls.js +3 -2
  7. package/dist/api/compiler/checker-declaration-order.js +2 -1
  8. package/dist/api/compiler/checker-declarations.js +14 -14
  9. package/dist/api/compiler/checker-declared-types.d.ts +1 -1
  10. package/dist/api/compiler/checker-declared-types.js +12 -11
  11. package/dist/api/compiler/checker-decorators.js +3 -3
  12. package/dist/api/compiler/checker-deprecation.js +17 -18
  13. package/dist/api/compiler/checker-destructuring.d.ts +1 -1
  14. package/dist/api/compiler/checker-destructuring.js +3 -3
  15. package/dist/api/compiler/checker-elaboration.js +8 -7
  16. package/dist/api/compiler/checker-emit-resolver.d.ts +1 -1
  17. package/dist/api/compiler/checker-emit-resolver.js +5 -4
  18. package/dist/api/compiler/checker-grammar.js +18 -4
  19. package/dist/api/compiler/checker-heritage.d.ts +1 -1
  20. package/dist/api/compiler/checker-heritage.js +14 -13
  21. package/dist/api/compiler/checker-inference.d.ts +1 -1
  22. package/dist/api/compiler/checker-inference.js +9 -9
  23. package/dist/api/compiler/checker-javascript.d.ts +1 -1
  24. package/dist/api/compiler/checker-javascript.js +5 -4
  25. package/dist/api/compiler/checker-jsx.d.ts +1 -1
  26. package/dist/api/compiler/checker-jsx.js +4 -4
  27. package/dist/api/compiler/checker-literals.js +2 -2
  28. package/dist/api/compiler/checker-members.d.ts +5 -3
  29. package/dist/api/compiler/checker-members.js +75 -53
  30. package/dist/api/compiler/checker-modules.d.ts +1 -1
  31. package/dist/api/compiler/checker-modules.js +13 -13
  32. package/dist/api/compiler/checker-object-literals.d.ts +1 -1
  33. package/dist/api/compiler/checker-object-literals.js +11 -7
  34. package/dist/api/compiler/checker-overloads.d.ts +1 -1
  35. package/dist/api/compiler/checker-overloads.js +4 -3
  36. package/dist/api/compiler/checker-property-access.d.ts +1 -1
  37. package/dist/api/compiler/checker-property-access.js +2 -2
  38. package/dist/api/compiler/checker-services.js +2 -2
  39. package/dist/api/compiler/checker-signatures.d.ts +1 -1
  40. package/dist/api/compiler/checker-signatures.js +9 -8
  41. package/dist/api/compiler/checker-symbol-types.d.ts +2 -18
  42. package/dist/api/compiler/checker-symbol-types.js +22 -952
  43. package/dist/api/compiler/checker-symbols.d.ts +2 -2
  44. package/dist/api/compiler/checker-symbols.js +29 -27
  45. package/dist/api/compiler/checker-type-factory.d.ts +2 -2
  46. package/dist/api/compiler/checker-type-factory.js +57 -16
  47. package/dist/api/compiler/checker-type-nodes.d.ts +1 -1
  48. package/dist/api/compiler/checker-type-nodes.js +2 -2
  49. package/dist/api/compiler/checker-type-operators.d.ts +1 -1
  50. package/dist/api/compiler/checker-type-operators.js +5 -5
  51. package/dist/api/compiler/checker-types.d.ts +73 -7
  52. package/dist/api/compiler/checker-types.js +220 -43
  53. package/dist/api/compiler/checker-unused.d.ts +1 -1
  54. package/dist/api/compiler/checker-unused.js +3 -3
  55. package/dist/api/compiler/checker.d.ts +29 -8
  56. package/dist/api/compiler/checker.js +29 -9
  57. package/dist/api/compiler/diagnostics.d.ts +2 -8
  58. package/dist/api/compiler/diagnostics.js +4 -40
  59. package/dist/api/compiler/file-include.d.ts +35 -8
  60. package/dist/api/compiler/file-include.js +81 -18
  61. package/dist/api/compiler/file-loader.d.ts +33 -4
  62. package/dist/api/compiler/file-loader.js +90 -24
  63. package/dist/api/compiler/instantiation.d.ts +1 -1
  64. package/dist/api/compiler/instantiation.js +86 -50
  65. package/dist/api/compiler/link-tables.d.ts +69 -0
  66. package/dist/api/compiler/link-tables.js +236 -0
  67. package/dist/api/compiler/name-resolver.js +3 -3
  68. package/dist/api/compiler/node-builder-names.d.ts +1 -1
  69. package/dist/api/compiler/node-builder-names.js +12 -12
  70. package/dist/api/compiler/node-builder-pseudo.d.ts +1 -1
  71. package/dist/api/compiler/node-builder-pseudo.js +2 -1
  72. package/dist/api/compiler/node-builder.d.ts +1 -1
  73. package/dist/api/compiler/node-builder.js +16 -16
  74. package/dist/api/compiler/parallel-parse.d.ts +2 -0
  75. package/dist/api/compiler/parallel-parse.js +4 -0
  76. package/dist/api/compiler/parser.d.ts +33 -16
  77. package/dist/api/compiler/parser.js +95 -76
  78. package/dist/api/compiler/printer/emit-context.d.ts +5 -2
  79. package/dist/api/compiler/printer/emit-context.js +19 -13
  80. package/dist/api/compiler/program-checker.js +3 -0
  81. package/dist/api/compiler/program.js +9 -1
  82. package/dist/api/compiler/relations.d.ts +1 -1
  83. package/dist/api/compiler/relations.js +10 -10
  84. package/dist/api/compiler/symbol-accessibility.d.ts +1 -1
  85. package/dist/api/compiler/symbol-accessibility.js +123 -26
  86. package/dist/api/compiler/symbol.d.ts +45 -3
  87. package/dist/api/compiler/symbol.js +121 -10
  88. package/dist/api/compiler/transformers/alias-references.d.ts +1 -1
  89. package/dist/api/compiler/transformers/alias-references.js +2 -1
  90. package/dist/api/compiler/transformers/declarations-diagnostics.js +2 -1
  91. package/dist/api/compiler/transformers/declarations-pseudo.js +4 -2
  92. package/dist/api/compiler/transformers/declarations-syntactic.d.ts +1 -1
  93. package/dist/api/compiler/transformers/declarations-syntactic.js +9 -9
  94. package/dist/api/compiler/transformers/declarations-tracker.d.ts +1 -1
  95. package/dist/api/compiler/transformers/declarations-tracker.js +3 -2
  96. package/dist/api/compiler/transformers/declarations.js +6 -5
  97. package/dist/api/compiler/transformers/reference-resolver.d.ts +2 -1
  98. package/dist/api/compiler/transformers/reference-resolver.js +26 -24
  99. package/dist/api/compiler/transformers/subtree-facts.d.ts +1 -0
  100. package/dist/api/compiler/transformers/subtree-facts.js +7 -5
  101. package/dist/api/compiler/transformers/syntax-facts.d.ts +1 -0
  102. package/dist/api/compiler/transformers/syntax-facts.js +9 -5
  103. package/dist/api/compiler/transformers/type-serialization.js +12 -12
  104. package/package.json +9 -9
  105. package/src/compiler/ast.ts +27 -19
  106. package/src/compiler/binder-utilities.ts +2 -2
  107. package/src/compiler/binder.ts +15 -11
  108. package/src/compiler/checker-calls.ts +3 -3
  109. package/src/compiler/checker-declaration-order.ts +2 -2
  110. package/src/compiler/checker-declarations.ts +21 -14
  111. package/src/compiler/checker-declared-types.ts +12 -12
  112. package/src/compiler/checker-decorators.ts +3 -3
  113. package/src/compiler/checker-deprecation.ts +17 -21
  114. package/src/compiler/checker-destructuring.ts +3 -3
  115. package/src/compiler/checker-elaboration.ts +8 -8
  116. package/src/compiler/checker-emit-resolver.ts +5 -5
  117. package/src/compiler/checker-grammar.ts +17 -5
  118. package/src/compiler/checker-heritage.ts +21 -14
  119. package/src/compiler/checker-inference.ts +17 -9
  120. package/src/compiler/checker-javascript.ts +5 -5
  121. package/src/compiler/checker-jsx.ts +12 -8
  122. package/src/compiler/checker-literals.ts +2 -2
  123. package/src/compiler/checker-members.ts +91 -47
  124. package/src/compiler/checker-modules.ts +23 -13
  125. package/src/compiler/checker-object-literals.ts +22 -6
  126. package/src/compiler/checker-overloads.ts +6 -6
  127. package/src/compiler/checker-property-access.ts +2 -2
  128. package/src/compiler/checker-services.ts +2 -2
  129. package/src/compiler/checker-signatures.ts +9 -9
  130. package/src/compiler/checker-symbol-types.ts +20 -940
  131. package/src/compiler/checker-symbols.ts +42 -35
  132. package/src/compiler/checker-type-factory.ts +53 -16
  133. package/src/compiler/checker-type-nodes.ts +2 -2
  134. package/src/compiler/checker-type-operators.ts +13 -5
  135. package/src/compiler/checker-types.ts +223 -43
  136. package/src/compiler/checker-unused.ts +3 -3
  137. package/src/compiler/checker.ts +31 -9
  138. package/src/compiler/diagnostics.ts +5 -44
  139. package/src/compiler/file-include.ts +85 -17
  140. package/src/compiler/file-loader.ts +104 -35
  141. package/src/compiler/incremental.ts +39 -5
  142. package/src/compiler/instantiation.ts +99 -55
  143. package/src/compiler/link-tables.ts +245 -0
  144. package/src/compiler/name-resolver.ts +3 -3
  145. package/src/compiler/node-builder-names.ts +21 -19
  146. package/src/compiler/node-builder-pseudo.ts +2 -2
  147. package/src/compiler/node-builder.ts +24 -16
  148. package/src/compiler/parallel-check.ts +11 -8
  149. package/src/compiler/parallel-parse.ts +5 -0
  150. package/src/compiler/parse-thread.ts +0 -4
  151. package/src/compiler/parser.ts +120 -70
  152. package/src/compiler/printer/emit-context.ts +20 -15
  153. package/src/compiler/program-checker.ts +2 -0
  154. package/src/compiler/program.ts +8 -1
  155. package/src/compiler/relations.ts +10 -10
  156. package/src/compiler/symbol-accessibility.ts +120 -25
  157. package/src/compiler/symbol.ts +127 -9
  158. package/src/compiler/transformers/alias-references.ts +2 -2
  159. package/src/compiler/transformers/declarations-diagnostics.ts +2 -1
  160. package/src/compiler/transformers/declarations-pseudo.ts +7 -4
  161. package/src/compiler/transformers/declarations-syntactic.ts +17 -9
  162. package/src/compiler/transformers/declarations-tracker.ts +3 -3
  163. package/src/compiler/transformers/declarations.ts +6 -6
  164. package/src/compiler/transformers/reference-resolver.ts +37 -25
  165. package/src/compiler/transformers/subtree-facts.ts +13 -5
  166. package/src/compiler/transformers/syntax-facts.ts +10 -5
  167. package/src/compiler/transformers/type-serialization.ts +12 -12
  168. package/src/compiler/tsc-build.ts +17 -13
  169. package/src/compiler/tsc-cli.ts +9 -6
  170. package/src/compiler/tsc-compile.ts +16 -7
  171. package/src/compiler/tsc-watch.ts +94 -26
@@ -133,6 +133,7 @@ import {
133
133
  PropertyDeclaration,
134
134
  PropertySignatureDeclaration,
135
135
  QualifiedName,
136
+ ReferenceIdentifier,
136
137
  RegularExpressionLiteral,
137
138
  RestTypeNode,
138
139
  ReturnStatement,
@@ -311,6 +312,16 @@ export const enum ParseFlags {
311
312
  JSDoc = 1 << 5,
312
313
  }
313
314
 
315
+ /** How an identifier is used, which decides whether it holds a flow node. */
316
+ export const enum IdentifierUse {
317
+ /** An expression or another reference: a `ReferenceIdentifier`. */
318
+ Reference,
319
+ /** A declaration, property, property access or type name, whose flow node nothing reads: an `Identifier`. */
320
+ Name,
321
+ /** An object literal element's name: a name before `:`, `(` or `<`, a reference in a shorthand property. */
322
+ ElementName,
323
+ }
324
+
314
325
  /** What the scanner saw of the JSDoc comments preceding a token. */
315
326
  export const enum JSDocScannerInfo {
316
327
  None = 0,
@@ -491,7 +502,7 @@ export class Parser extends ScannerErrorReporter {
491
502
  signatureParameterFlags: ParseFlags;
492
503
 
493
504
  /** Parses JSDoc comments and, in JavaScript files, reparses their tags. */
494
- readonly jsdoc: JSDocParser;
505
+ jsdoc: JSDocParser;
495
506
  /**
496
507
  * Returned instead of `undefined` by hot element parsers: a `Node | undefined` result is boxed natively
497
508
  * for every node returned.
@@ -554,12 +565,15 @@ export class Parser extends ScannerErrorReporter {
554
565
  }
555
566
 
556
567
  /**
557
- * Frees the scanner's copy of the text once the parser is done. The parser and its scanner and
558
- * JSDoc parser refer to each other, so natively they're freed only by a cycle collection, which may
559
- * come much later.
568
+ * Frees the scanner's copy of the text once the parser is done, and drops the references back to
569
+ * this parser from its scanner and JSDoc parser. Natively, the parser is then freed as soon as its
570
+ * caller lets go of it, instead of at a cycle collection, which may come much later (on a parse
571
+ * thread, not before the thread exits).
560
572
  */
561
573
  release(): void {
562
574
  this.scanner.setText('');
575
+ this.scanner.setOnError(undefined);
576
+ this.jsdoc = releasedParser().jsdoc;
563
577
  }
564
578
 
565
579
  token(): SyntaxKind {
@@ -806,14 +820,10 @@ export class Parser extends ScannerErrorReporter {
806
820
  }
807
821
  collectExternalModuleReferences(result);
808
822
  if (result.isJS()) result.jsDiagnostics = attachFileToDiagnostics(this.jsDiagnostics, result);
809
- // Declaration files get their caches on first use (in a thread's copy once they may be shared,
810
- // `useThreadTextCaches`); the file's DiagnosticFile exists from here on, so reading it never
811
- // writes to the file. The scanner holds the text's code units unless a nested parse cut its text short.
812
- const scanner = this.scanner;
813
- if (result.isDeclarationFile) result.diagnosticFile();
814
- else if (scanner.text === result.text && scanner.end === result.text.length)
815
- result.computeCachesFromUnits(scanner.chars);
816
- else result.computeCaches();
823
+ // Files get their line starts on first use (in a thread's copy once they may be shared,
824
+ // `useThreadTextCaches`): most files are never pointed into by a diagnostic. The file's
825
+ // DiagnosticFile exists from here on, so reading it never writes to the file.
826
+ result.diagnosticFile();
817
827
  return result;
818
828
  }
819
829
 
@@ -1789,7 +1799,7 @@ export class Parser extends ScannerErrorReporter {
1789
1799
  }
1790
1800
 
1791
1801
  parseIdentifierUnlessAtSemicolon(): Identifier | undefined {
1792
- return this.canParseSemicolon() ? undefined : this.parseIdentifier();
1802
+ return this.canParseSemicolon() ? undefined : this.parseIdentifier(IdentifierUse.Name);
1793
1803
  }
1794
1804
 
1795
1805
  parseReturnStatement(): Statement {
@@ -2186,7 +2196,7 @@ export class Parser extends ScannerErrorReporter {
2186
2196
  // named `implements`.
2187
2197
  if (this.isBindingIdentifier() && !this.isImplementsClause()) {
2188
2198
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2189
- const id = this.createIdentifier(this.isBindingIdentifier());
2199
+ const id = this.createIdentifier(this.isBindingIdentifier(), IdentifierUse.Name);
2190
2200
  this.statementHasAwaitIdentifier = saveHasAwaitIdentifier;
2191
2201
  return id;
2192
2202
  }
@@ -2503,7 +2513,7 @@ export class Parser extends ScannerErrorReporter {
2503
2513
 
2504
2514
  parseInterfaceDeclaration(pos: number, jsdoc: JSDocScannerInfo, modifiers: ModifierList | undefined): Statement {
2505
2515
  this.parseExpected(SyntaxKind.InterfaceKeyword);
2506
- const name = this.parseIdentifier();
2516
+ const name = this.parseIdentifier(IdentifierUse.Name);
2507
2517
  const typeParameters = this.parseTypeParameters();
2508
2518
  const heritageClauses = this.parseHeritageClauses();
2509
2519
  const members = this.parseObjectTypeMembers();
@@ -2519,7 +2529,7 @@ export class Parser extends ScannerErrorReporter {
2519
2529
  parseTypeAliasDeclaration(pos: number, jsdoc: JSDocScannerInfo, modifiers: ModifierList | undefined): Statement {
2520
2530
  this.parseExpected(SyntaxKind.TypeKeyword);
2521
2531
  if (this.hasPrecedingLineBreak()) this.parseErrorAtCurrentToken(Diagnostics.Line_break_not_permitted_here);
2522
- const name = this.parseIdentifier();
2532
+ const name = this.parseIdentifier(IdentifierUse.Name);
2523
2533
  const typeParameters = this.parseTypeParameters();
2524
2534
  this.parseExpected(SyntaxKind.EqualsToken);
2525
2535
  const type =
@@ -2552,7 +2562,7 @@ export class Parser extends ScannerErrorReporter {
2552
2562
  parseEnumDeclaration(pos: number, jsdoc: JSDocScannerInfo, modifiers: ModifierList | undefined): Statement {
2553
2563
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2554
2564
  this.parseExpected(SyntaxKind.EnumKeyword);
2555
- const name = this.parseIdentifier();
2565
+ const name = this.parseIdentifier(IdentifierUse.Name);
2556
2566
  let members: NodeList;
2557
2567
  if (this.parseExpected(SyntaxKind.OpenBraceToken)) {
2558
2568
  const saveContextFlags = this.contextFlags;
@@ -2594,7 +2604,7 @@ export class Parser extends ScannerErrorReporter {
2594
2604
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2595
2605
  if (this.token() === SyntaxKind.GlobalKeyword) {
2596
2606
  // `global` names the global scope augmentation.
2597
- name = this.parseIdentifier();
2607
+ name = this.parseIdentifier(IdentifierUse.Name);
2598
2608
  keyword = SyntaxKind.GlobalKeyword;
2599
2609
  } else {
2600
2610
  name = this.parseLiteralExpression(true);
@@ -2627,7 +2637,7 @@ export class Parser extends ScannerErrorReporter {
2627
2637
  keyword: SyntaxKind,
2628
2638
  ): Node {
2629
2639
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2630
- const name = nested ? this.parseIdentifierName() : this.parseIdentifier();
2640
+ const name = nested ? this.parseIdentifierName(IdentifierUse.Name) : this.parseIdentifier(IdentifierUse.Name);
2631
2641
  let body: Node;
2632
2642
  if (this.parseOptional(SyntaxKind.DotToken)) {
2633
2643
  const implicitExport = new Token(SyntaxKind.ExportKeyword);
@@ -2660,7 +2670,7 @@ export class Parser extends ScannerErrorReporter {
2660
2670
  const afterImportPos = this.nodePos();
2661
2671
  // The identifier isn't parsed in an await context; the checker reports `await`.
2662
2672
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2663
- let identifier = this.isIdentifier() ? this.parseIdentifier() : undefined;
2673
+ let identifier = this.isIdentifier() ? this.parseIdentifier(IdentifierUse.Name) : undefined;
2664
2674
  let phaseModifier = SyntaxKind.Unknown;
2665
2675
  if (
2666
2676
  identifier !== undefined &&
@@ -2670,7 +2680,7 @@ export class Parser extends ScannerErrorReporter {
2670
2680
  (this.isIdentifier() || this.tokenAfterImportDefinitelyProducesImportDeclaration())
2671
2681
  ) {
2672
2682
  phaseModifier = SyntaxKind.TypeKeyword;
2673
- identifier = this.isIdentifier() ? this.parseIdentifier() : undefined;
2683
+ identifier = this.isIdentifier() ? this.parseIdentifier(IdentifierUse.Name) : undefined;
2674
2684
  } else if (identifier !== undefined && identifier.text === 'defer') {
2675
2685
  const shouldParseAsDeferModifier =
2676
2686
  this.token() === SyntaxKind.FromKeyword
@@ -2678,7 +2688,7 @@ export class Parser extends ScannerErrorReporter {
2678
2688
  : this.token() !== SyntaxKind.CommaToken && this.token() !== SyntaxKind.EqualsToken;
2679
2689
  if (shouldParseAsDeferModifier) {
2680
2690
  phaseModifier = SyntaxKind.DeferKeyword;
2681
- identifier = this.isIdentifier() ? this.parseIdentifier() : undefined;
2691
+ identifier = this.isIdentifier() ? this.parseIdentifier(IdentifierUse.Name) : undefined;
2682
2692
  }
2683
2693
  }
2684
2694
  if (
@@ -2809,7 +2819,7 @@ export class Parser extends ScannerErrorReporter {
2809
2819
  const pos = this.nodePos();
2810
2820
  this.parseExpected(SyntaxKind.AsteriskToken);
2811
2821
  this.parseExpected(SyntaxKind.AsKeyword);
2812
- const name = this.parseIdentifier();
2822
+ const name = this.parseIdentifier(IdentifierUse.Name);
2813
2823
  return this.finishNode(new NamespaceImport(name), pos);
2814
2824
  }
2815
2825
 
@@ -2850,9 +2860,9 @@ export class Parser extends ScannerErrorReporter {
2850
2860
  // import { type as as } from "mod"; - isTypeOnly: false, name: as, propertyName: type
2851
2861
  // import { type as as as } from "mod"; - isTypeOnly: true, name: as, propertyName: as
2852
2862
  if (this.token() === SyntaxKind.AsKeyword) {
2853
- const firstAs = this.parseIdentifierName();
2863
+ const firstAs = this.parseIdentifierName(IdentifierUse.Name);
2854
2864
  if (this.token() === SyntaxKind.AsKeyword) {
2855
- const secondAs = this.parseIdentifierName();
2865
+ const secondAs = this.parseIdentifierName(IdentifierUse.Name);
2856
2866
  if (this.canParseModuleExportName()) {
2857
2867
  // { type as as something }
2858
2868
  isTypeOnly = true;
@@ -2921,7 +2931,7 @@ export class Parser extends ScannerErrorReporter {
2921
2931
 
2922
2932
  parseModuleExportName(): Node {
2923
2933
  if (this.token() === SyntaxKind.StringLiteral) return this.parseLiteralExpression(false);
2924
- return this.parseIdentifierName();
2934
+ return this.parseIdentifierName(IdentifierUse.Name);
2925
2935
  }
2926
2936
 
2927
2937
  tryParseImportAttributes(): ImportAttributes | undefined {
@@ -2966,7 +2976,7 @@ export class Parser extends ScannerErrorReporter {
2966
2976
  this.parseExpected(SyntaxKind.AsKeyword);
2967
2977
  this.parseExpected(SyntaxKind.NamespaceKeyword);
2968
2978
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
2969
- const name = this.parseIdentifier();
2979
+ const name = this.parseIdentifier(IdentifierUse.Name);
2970
2980
  this.statementHasAwaitIdentifier = saveHasAwaitIdentifier;
2971
2981
  this.parseSemicolon();
2972
2982
  // Modifiers are kept so the grammar checker can report them.
@@ -3136,7 +3146,7 @@ export class Parser extends ScannerErrorReporter {
3136
3146
 
3137
3147
  parseTypeParameterOfInferType(): TypeParameterDeclaration {
3138
3148
  const pos = this.nodePos();
3139
- const name = this.parseIdentifier();
3149
+ const name = this.parseIdentifier(IdentifierUse.Name);
3140
3150
  const constraint = this.tryParseConstraintOfInferType();
3141
3151
  const result = new TypeParameterDeclaration(undefined, name, constraint, undefined, undefined);
3142
3152
  this.finishNode(result, pos);
@@ -3342,11 +3352,16 @@ export class Parser extends ScannerErrorReporter {
3342
3352
  return this.parseEntityName(true, Diagnostics.Type_expected);
3343
3353
  }
3344
3354
 
3345
- parseEntityName(allowReservedWords: boolean, diagnosticMessage: DiagnosticMessage | undefined): EntityName {
3355
+ /** An entity name; `use` is for its first identifier, the qualified names' right sides are names. */
3356
+ parseEntityName(
3357
+ allowReservedWords: boolean,
3358
+ diagnosticMessage: DiagnosticMessage | undefined,
3359
+ use: IdentifierUse = IdentifierUse.Name,
3360
+ ): EntityName {
3346
3361
  const pos = this.nodePos();
3347
3362
  let entity: Node = allowReservedWords
3348
- ? this.parseIdentifierNameWithDiagnostic(diagnosticMessage)
3349
- : this.parseIdentifierWithDiagnostic(diagnosticMessage, undefined);
3363
+ ? this.parseIdentifierNameWithDiagnostic(diagnosticMessage, use)
3364
+ : this.parseIdentifierWithDiagnostic(diagnosticMessage, undefined, use);
3350
3365
  while (this.parseOptional(SyntaxKind.DotToken)) {
3351
3366
  // A JSDoc-style generic; the checker reports the gap between the name and the type arguments.
3352
3367
  if (this.token() === SyntaxKind.LessThanToken) break;
@@ -3382,19 +3397,19 @@ export class Parser extends ScannerErrorReporter {
3382
3397
  // after it). Report a missing identifier right after the dot rather than on the next token.
3383
3398
  if (this.isKeywordStartingNextLine()) {
3384
3399
  this.parseErrorAt(this.nodePos(), this.nodePos(), Diagnostics.Identifier_expected);
3385
- return this.createMissingIdentifier();
3400
+ return this.createMissingIdentifier(IdentifierUse.Name);
3386
3401
  }
3387
3402
  if (this.token() === SyntaxKind.PrivateIdentifier) {
3388
3403
  this.parsePrivateIdentifier();
3389
3404
  this.parseErrorAt(this.nodePos(), this.nodePos(), Diagnostics.Identifier_expected);
3390
- return this.createMissingIdentifier();
3405
+ return this.createMissingIdentifier(IdentifierUse.Name);
3391
3406
  }
3392
3407
  if (allowIdentifierNames) {
3393
- if (allowUnicodeEscapeSequenceInIdentifierName) return this.parseIdentifierName();
3394
- return this.parseIdentifierNameErrorOnUnicodeEscapeSequence();
3408
+ if (allowUnicodeEscapeSequenceInIdentifierName) return this.parseIdentifierName(IdentifierUse.Name);
3409
+ return this.parseIdentifierNameErrorOnUnicodeEscapeSequence(IdentifierUse.Name);
3395
3410
  }
3396
3411
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
3397
- const id = this.parseIdentifier();
3412
+ const id = this.parseIdentifier(IdentifierUse.Name);
3398
3413
  this.statementHasAwaitIdentifier = saveHasAwaitIdentifier;
3399
3414
  return id;
3400
3415
  }
@@ -3408,14 +3423,26 @@ export class Parser extends ScannerErrorReporter {
3408
3423
  );
3409
3424
  }
3410
3425
 
3411
- newIdentifier(text: string): Identifier {
3426
+ /**
3427
+ * A new identifier of the class `use` calls for. Callers create it after the identifier's token, so
3428
+ * for an element name the current token tells a shorthand property from an assignment or a method.
3429
+ */
3430
+ newIdentifier(text: string, use: IdentifierUse = IdentifierUse.Reference): Identifier {
3412
3431
  this.identifierCount++;
3413
3432
  if (text === 'await') this.statementHasAwaitIdentifier = true;
3414
- return new Identifier(text);
3433
+ if (use === IdentifierUse.Name || (use === IdentifierUse.ElementName && this.isElementNameEnd()))
3434
+ return new Identifier(text);
3435
+ return new ReferenceIdentifier(text);
3415
3436
  }
3416
3437
 
3417
- createMissingIdentifier(): Identifier {
3418
- const result = this.newIdentifier('');
3438
+ /** Whether the current token ends an object literal element name that is not a shorthand property. */
3439
+ isElementNameEnd(): boolean {
3440
+ const token = this.token();
3441
+ return token === SyntaxKind.ColonToken || token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken;
3442
+ }
3443
+
3444
+ createMissingIdentifier(use: IdentifierUse = IdentifierUse.Reference): Identifier {
3445
+ const result = this.newIdentifier('', use);
3419
3446
  this.finishNode(result, this.nodePos());
3420
3447
  return result;
3421
3448
  }
@@ -3516,7 +3543,7 @@ export class Parser extends ScannerErrorReporter {
3516
3543
  parseImportAttribute(): Node {
3517
3544
  const pos = this.nodePos();
3518
3545
  let name: Node | undefined;
3519
- if (tokenIsIdentifierOrKeyword(this.token())) name = this.parseIdentifierName();
3546
+ if (tokenIsIdentifierOrKeyword(this.token())) name = this.parseIdentifierName(IdentifierUse.Name);
3520
3547
  else if (this.token() === SyntaxKind.StringLiteral) name = this.parseLiteralExpression(false);
3521
3548
  if (name !== undefined) this.parseExpected(SyntaxKind.ColonToken);
3522
3549
  else this.parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected);
@@ -3545,7 +3572,7 @@ export class Parser extends ScannerErrorReporter {
3545
3572
  parseTypeQuery(): TypeNode {
3546
3573
  const pos = this.nodePos();
3547
3574
  this.parseExpected(SyntaxKind.TypeOfKeyword);
3548
- const entityName = this.parseEntityName(true, undefined);
3575
+ const entityName = this.parseEntityName(true, undefined, IdentifierUse.Reference);
3549
3576
  // ASI: don't parse the next line's type arguments as part of an instantiation expression.
3550
3577
  const typeArguments = this.hasPrecedingLineBreak() ? undefined : this.parseTypeArguments();
3551
3578
  return this.finishNode(new TypeQueryNode(entityName, typeArguments), pos);
@@ -3588,7 +3615,7 @@ export class Parser extends ScannerErrorReporter {
3588
3615
 
3589
3616
  parseMappedTypeParameter(): TypeParameterDeclaration {
3590
3617
  const pos = this.nodePos();
3591
- const name = this.parseIdentifierName();
3618
+ const name = this.parseIdentifierName(IdentifierUse.Name);
3592
3619
  this.parseExpected(SyntaxKind.InKeyword);
3593
3620
  const type = this.parseType();
3594
3621
  const result = new TypeParameterDeclaration(undefined, name, type, undefined, undefined);
@@ -3641,7 +3668,7 @@ export class Parser extends ScannerErrorReporter {
3641
3668
  parseTypeParameter(): Node {
3642
3669
  const pos = this.nodePos();
3643
3670
  const modifiers = this.parseModifiersEx(false, true, false);
3644
- const name = this.parseIdentifier();
3671
+ const name = this.parseIdentifier(IdentifierUse.Name);
3645
3672
  let constraint: TypeNode | undefined;
3646
3673
  let expression: Expression | undefined;
3647
3674
  if (this.parseOptional(SyntaxKind.ExtendsKeyword)) {
@@ -3700,7 +3727,7 @@ export class Parser extends ScannerErrorReporter {
3700
3727
  const result = new ParameterDeclaration(
3701
3728
  modifiers,
3702
3729
  undefined,
3703
- this.createIdentifier(true),
3730
+ this.createIdentifier(true, IdentifierUse.Name),
3704
3731
  undefined,
3705
3732
  this.parseTypeAnnotation(),
3706
3733
  undefined,
@@ -3780,7 +3807,7 @@ export class Parser extends ScannerErrorReporter {
3780
3807
  if (this.isIdentifier()) {
3781
3808
  const state = this.beginSpeculation();
3782
3809
  const pos = this.nodePos();
3783
- const id = this.parseIdentifier();
3810
+ const id = this.parseIdentifier(IdentifierUse.Name);
3784
3811
  if (this.token() === SyntaxKind.IsKeyword && !this.hasPrecedingLineBreak()) {
3785
3812
  this.endSpeculation(state);
3786
3813
  this.nextToken();
@@ -3819,20 +3846,20 @@ export class Parser extends ScannerErrorReporter {
3819
3846
  return result;
3820
3847
  }
3821
3848
 
3822
- parsePropertyName(): Node {
3849
+ parsePropertyName(use: IdentifierUse = IdentifierUse.Name): Node {
3823
3850
  const saveHasAwaitIdentifier = this.statementHasAwaitIdentifier;
3824
- const prop = this.parsePropertyNameWorker(true);
3851
+ const prop = this.parsePropertyNameWorker(true, use);
3825
3852
  this.statementHasAwaitIdentifier = saveHasAwaitIdentifier;
3826
3853
  return prop;
3827
3854
  }
3828
3855
 
3829
- parsePropertyNameWorker(allowComputedPropertyNames: boolean): Node {
3856
+ parsePropertyNameWorker(allowComputedPropertyNames: boolean, use: IdentifierUse = IdentifierUse.Name): Node {
3830
3857
  const token = this.token();
3831
3858
  if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral || token === SyntaxKind.BigIntLiteral)
3832
3859
  return this.parseLiteralExpression(true);
3833
3860
  if (allowComputedPropertyNames && token === SyntaxKind.OpenBracketToken) return this.parseComputedPropertyName();
3834
3861
  if (token === SyntaxKind.PrivateIdentifier) return this.parsePrivateIdentifier();
3835
- return this.parseIdentifierName();
3862
+ return this.parseIdentifierName(use);
3836
3863
  }
3837
3864
 
3838
3865
  parseComputedPropertyName(): Node {
@@ -3944,7 +3971,7 @@ export class Parser extends ScannerErrorReporter {
3944
3971
  const pos = this.nodePos();
3945
3972
  const jsdoc = this.jsdocScannerInfo();
3946
3973
  const dotDotDotToken = this.parseOptionalToken(SyntaxKind.DotDotDotToken);
3947
- const name = this.parseIdentifierName();
3974
+ const name = this.parseIdentifierName(IdentifierUse.Name);
3948
3975
  const questionToken = this.parseOptionalToken(SyntaxKind.QuestionToken);
3949
3976
  this.parseExpected(SyntaxKind.ColonToken);
3950
3977
  const type = this.parseTupleElementType();
@@ -3980,7 +4007,7 @@ export class Parser extends ScannerErrorReporter {
3980
4007
  const pos = this.nodePos();
3981
4008
  const assertsModifier = this.parseExpectedToken(SyntaxKind.AssertsKeyword);
3982
4009
  const parameterName: Node =
3983
- this.token() === SyntaxKind.ThisKeyword ? this.parseThisTypeNode() : this.parseIdentifier();
4010
+ this.token() === SyntaxKind.ThisKeyword ? this.parseThisTypeNode() : this.parseIdentifier(IdentifierUse.Name);
3984
4011
  const type = this.parseOptional(SyntaxKind.IsKeyword) ? this.parseType() : undefined;
3985
4012
  return this.finishNode(new TypePredicateNode(assertsModifier, parameterName, type), pos);
3986
4013
  }
@@ -5092,11 +5119,11 @@ export class Parser extends ScannerErrorReporter {
5092
5119
  parseJsxAttributeName(): Node {
5093
5120
  const pos = this.nodePos();
5094
5121
  this.scanJsxIdentifier();
5095
- const attrName = this.parseIdentifierNameErrorOnUnicodeEscapeSequence();
5122
+ const attrName = this.parseIdentifierNameErrorOnUnicodeEscapeSequence(IdentifierUse.Name);
5096
5123
  if (this.parseOptional(SyntaxKind.ColonToken)) {
5097
5124
  this.scanJsxIdentifier();
5098
5125
  return this.finishNode(
5099
- new JsxNamespacedName(attrName, this.parseIdentifierNameErrorOnUnicodeEscapeSequence()),
5126
+ new JsxNamespacedName(attrName, this.parseIdentifierNameErrorOnUnicodeEscapeSequence(IdentifierUse.Name)),
5100
5127
  pos,
5101
5128
  );
5102
5129
  }
@@ -5227,7 +5254,7 @@ export class Parser extends ScannerErrorReporter {
5227
5254
  // An `import.*` meta property, such as `import.meta`.
5228
5255
  this.nextToken();
5229
5256
  this.nextToken();
5230
- const name = this.parseIdentifierName();
5257
+ const name = this.parseIdentifierName(IdentifierUse.Name);
5231
5258
  expression = this.finishNode(new MetaProperty(SyntaxKind.ImportKeyword, name), pos);
5232
5259
  if (name.text === 'defer') {
5233
5260
  if (this.token() === SyntaxKind.OpenParenToken || this.token() === SyntaxKind.LessThanToken)
@@ -5705,7 +5732,7 @@ export class Parser extends ScannerErrorReporter {
5705
5732
  return this.parseAccessorDeclaration(pos, jsdoc, modifiers, SyntaxKind.SetAccessor, ParseFlags.None);
5706
5733
  const asteriskToken = this.parseOptionalToken(SyntaxKind.AsteriskToken);
5707
5734
  const tokenIsIdentifier = this.isIdentifier();
5708
- const name = this.parsePropertyName();
5735
+ const name = this.parsePropertyName(IdentifierUse.ElementName);
5709
5736
  // The grammar checker reports optional property assignments, definite assignment assertions,
5710
5737
  // decorators and modifiers.
5711
5738
  let postfixToken = this.parseOptionalToken(SyntaxKind.QuestionToken);
@@ -5788,7 +5815,7 @@ export class Parser extends ScannerErrorReporter {
5788
5815
  const pos = this.nodePos();
5789
5816
  this.parseExpected(SyntaxKind.NewKeyword);
5790
5817
  if (this.parseOptional(SyntaxKind.DotToken)) {
5791
- const name = this.parseIdentifierName();
5818
+ const name = this.parseIdentifierName(IdentifierUse.Name);
5792
5819
  return this.finishNode(new MetaProperty(SyntaxKind.NewKeyword, name), pos);
5793
5820
  }
5794
5821
  const expressionPos = this.nodePos();
@@ -5847,10 +5874,10 @@ export class Parser extends ScannerErrorReporter {
5847
5874
 
5848
5875
  // Identifiers
5849
5876
 
5850
- parseIdentifierNameErrorOnUnicodeEscapeSequence(): Identifier {
5877
+ parseIdentifierNameErrorOnUnicodeEscapeSequence(use: IdentifierUse = IdentifierUse.Reference): Identifier {
5851
5878
  if (this.scanner.hasUnicodeEscape() || this.scanner.hasExtendedUnicodeEscape())
5852
5879
  this.parseErrorAtCurrentToken(Diagnostics.Unicode_escape_sequence_cannot_appear_here);
5853
- return this.createIdentifier(tokenIsIdentifierOrKeyword(this.token()));
5880
+ return this.createIdentifier(tokenIsIdentifierOrKeyword(this.token()), use);
5854
5881
  }
5855
5882
 
5856
5883
  parseBindingIdentifier(): Identifier {
@@ -5863,42 +5890,54 @@ export class Parser extends ScannerErrorReporter {
5863
5890
  this.isBindingIdentifier(),
5864
5891
  undefined,
5865
5892
  privateIdentifierDiagnosticMessage,
5893
+ IdentifierUse.Name,
5866
5894
  );
5867
5895
  this.statementHasAwaitIdentifier = saveHasAwaitIdentifier;
5868
5896
  return id;
5869
5897
  }
5870
5898
 
5871
- parseIdentifierName(): Identifier {
5872
- return this.parseIdentifierNameWithDiagnostic(undefined);
5899
+ parseIdentifierName(use: IdentifierUse = IdentifierUse.Reference): Identifier {
5900
+ return this.parseIdentifierNameWithDiagnostic(undefined, use);
5873
5901
  }
5874
5902
 
5875
- parseIdentifierNameWithDiagnostic(diagnosticMessage: DiagnosticMessage | undefined): Identifier {
5876
- return this.createIdentifierWithDiagnostic(tokenIsIdentifierOrKeyword(this.token()), diagnosticMessage, undefined);
5903
+ parseIdentifierNameWithDiagnostic(
5904
+ diagnosticMessage: DiagnosticMessage | undefined,
5905
+ use: IdentifierUse = IdentifierUse.Reference,
5906
+ ): Identifier {
5907
+ return this.createIdentifierWithDiagnostic(
5908
+ tokenIsIdentifierOrKeyword(this.token()),
5909
+ diagnosticMessage,
5910
+ undefined,
5911
+ use,
5912
+ );
5877
5913
  }
5878
5914
 
5879
- parseIdentifier(): Identifier {
5880
- return this.parseIdentifierWithDiagnostic(undefined, undefined);
5915
+ parseIdentifier(use: IdentifierUse = IdentifierUse.Reference): Identifier {
5916
+ return this.parseIdentifierWithDiagnostic(undefined, undefined, use);
5881
5917
  }
5882
5918
 
5883
5919
  parseIdentifierWithDiagnostic(
5884
5920
  diagnosticMessage: DiagnosticMessage | undefined,
5885
5921
  privateIdentifierDiagnosticMessage: DiagnosticMessage | undefined,
5922
+ use: IdentifierUse = IdentifierUse.Reference,
5886
5923
  ): Identifier {
5887
5924
  return this.createIdentifierWithDiagnostic(
5888
5925
  this.isIdentifier(),
5889
5926
  diagnosticMessage,
5890
5927
  privateIdentifierDiagnosticMessage,
5928
+ use,
5891
5929
  );
5892
5930
  }
5893
5931
 
5894
- createIdentifier(isIdentifier: boolean): Identifier {
5895
- return this.createIdentifierWithDiagnostic(isIdentifier, undefined, undefined);
5932
+ createIdentifier(isIdentifier: boolean, use: IdentifierUse = IdentifierUse.Reference): Identifier {
5933
+ return this.createIdentifierWithDiagnostic(isIdentifier, undefined, undefined, use);
5896
5934
  }
5897
5935
 
5898
5936
  createIdentifierWithDiagnostic(
5899
5937
  isIdentifier: boolean,
5900
5938
  diagnosticMessage: DiagnosticMessage | undefined,
5901
5939
  privateIdentifierDiagnosticMessage: DiagnosticMessage | undefined,
5940
+ use: IdentifierUse = IdentifierUse.Reference,
5902
5941
  ): Identifier {
5903
5942
  if (isIdentifier) {
5904
5943
  const pos = this.scanner.hasPrecedingJSDocLeadingAsterisks() ? this.scanner.getTokenStart() : this.nodePos();
@@ -5906,7 +5945,7 @@ export class Parser extends ScannerErrorReporter {
5906
5945
  const record = this.scanner.recordIdentifierValue(text);
5907
5946
  this.nextTokenWithoutCheck();
5908
5947
  if (record) this.identifierTexts.push(text);
5909
- const result = this.newIdentifier(text);
5948
+ const result = this.newIdentifier(text, use);
5910
5949
  this.finishNode(result, pos);
5911
5950
  return result;
5912
5951
  }
@@ -5916,7 +5955,7 @@ export class Parser extends ScannerErrorReporter {
5916
5955
  ? privateIdentifierDiagnosticMessage
5917
5956
  : Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies,
5918
5957
  );
5919
- return this.createIdentifier(true);
5958
+ return this.createIdentifier(true, use);
5920
5959
  }
5921
5960
  // Report at the current position only at the end of the file: elsewhere the error would land
5922
5961
  // incorrectly on embedded script tags.
@@ -5944,7 +5983,7 @@ export class Parser extends ScannerErrorReporter {
5944
5983
  } else {
5945
5984
  this.parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
5946
5985
  }
5947
- return this.createMissingIdentifier();
5986
+ return this.createMissingIdentifier(use);
5948
5987
  }
5949
5988
 
5950
5989
  internIdentifier(text: string): string {
@@ -6934,6 +6973,17 @@ export function forgetLazyJSDocFile(): void {
6934
6973
 
6935
6974
  const viableKeywordSuggestions = getViableKeywordSuggestions();
6936
6975
 
6976
+ // A parser whose JSDoc parser released parsers keep (`Parser.release`), created on first use.
6977
+ let releasedParserValue: Parser | undefined;
6978
+ function releasedParser(): Parser {
6979
+ let parser = releasedParserValue;
6980
+ if (parser === undefined) {
6981
+ parser = new Parser('/', '/', '', ScriptKind.TS, new ExternalModuleIndicatorOptions(false, false));
6982
+ releasedParserValue = parser;
6983
+ }
6984
+ return parser;
6985
+ }
6986
+
6937
6987
  function getSpaceSuggestion(expressionText: string): string {
6938
6988
  for (const keyword of viableKeywordSuggestions)
6939
6989
  if (expressionText.length > keyword.length + 2 && expressionText.startsWith(keyword))
@@ -12,6 +12,7 @@ import {
12
12
  VariableDeclaration,
13
13
  VariableStatement,
14
14
  } from '../ast.js';
15
+ import { ClusteredLinkTable } from '../link-tables.js';
15
16
  import { SyntaxKind } from '../syntax-kind.js';
16
17
  import { EmitFlags, GeneratedIdentifierFlags } from './emit-flags.js';
17
18
  import { AutoGenerateInfo } from './auto-generate.js';
@@ -135,8 +136,10 @@ export { AutoGenerateInfo, newAutoGenerateId } from './auto-generate.js';
135
136
  export class EmitContext extends NodeFactory {
136
137
  readonly autoGenerate: Map<Node, AutoGenerateInfo>;
137
138
  readonly textSource: Map<Node, Node>;
138
- readonly original: Map<Node, Node>;
139
- readonly emitNodes: Map<Node, EmitNode>;
139
+ /** The node each node was made from, by node id. */
140
+ readonly original: ClusteredLinkTable<Node>;
141
+ /** The emit data of nodes, by node id. */
142
+ readonly emitNodes: ClusteredLinkTable<EmitNode>;
140
143
  private lastLookup: Node | undefined;
141
144
  private lastEmitNode: EmitNode | undefined;
142
145
  readonly assignedNames: Map<Node, Node>;
@@ -150,8 +153,8 @@ export class EmitContext extends NodeFactory {
150
153
  super();
151
154
  this.autoGenerate = new Map<Node, AutoGenerateInfo>();
152
155
  this.textSource = new Map<Node, Node>();
153
- this.original = new Map<Node, Node>();
154
- this.emitNodes = new Map<Node, EmitNode>();
156
+ this.original = new ClusteredLinkTable<Node>();
157
+ this.emitNodes = new ClusteredLinkTable<EmitNode>();
155
158
  this.lastLookup = undefined;
156
159
  this.lastEmitNode = undefined;
157
160
  this.assignedNames = new Map<Node, Node>();
@@ -187,7 +190,7 @@ export class EmitContext extends NodeFactory {
187
190
  let emitNode = this.lookup(node);
188
191
  if (emitNode === undefined) {
189
192
  emitNode = new EmitNode();
190
- this.emitNodes.set(node, emitNode);
193
+ this.emitNodes.set(node.id, emitNode);
191
194
  this.lastLookup = node;
192
195
  this.lastEmitNode = emitNode;
193
196
  }
@@ -197,7 +200,7 @@ export class EmitContext extends NodeFactory {
197
200
  /** The emit data of `node`. The printer asks for several of a node's in a row, so the last answer is kept. */
198
201
  private lookup(node: Node): EmitNode | undefined {
199
202
  if (node === this.lastLookup) return this.lastEmitNode;
200
- const emitNode = this.emitNodes.get(node);
203
+ const emitNode = this.emitNodes.get(node.id);
201
204
  this.lastLookup = node;
202
205
  this.lastEmitNode = emitNode;
203
206
  return emitNode;
@@ -210,29 +213,31 @@ export class EmitContext extends NodeFactory {
210
213
  }
211
214
 
212
215
  setOriginalEx(node: Node, original: Node, allowOverwrite: boolean): void {
213
- const existing = this.original.get(node);
216
+ const existing = this.original.get(node.id);
214
217
  if (existing === undefined) {
215
- this.original.set(node, original);
218
+ this.original.set(node.id, original);
216
219
  const emitNode = this.lookup(original);
217
220
  if (emitNode !== undefined) this.emitNode(node).copyFrom(emitNode);
218
- } else if (allowOverwrite) this.original.set(node, original);
221
+ } else if (allowOverwrite) this.original.set(node.id, original);
219
222
  else if (existing !== original) throw new Error('Original node already set.');
220
223
  }
221
224
 
222
225
  unsetOriginal(node: Node): boolean {
223
- return this.original.delete(node);
226
+ if (this.original.get(node.id) === undefined) return false;
227
+ this.original.set(node.id, undefined);
228
+ return true;
224
229
  }
225
230
 
226
231
  getOriginal(node: Node): Node | undefined {
227
- return this.original.get(node);
232
+ return this.original.get(node.id);
228
233
  }
229
234
 
230
235
  /** The node at the end of the chain of original nodes. */
231
236
  mostOriginal(node: Node): Node {
232
- let original = this.original.get(node);
237
+ let original = this.original.get(node.id);
233
238
  while (original !== undefined) {
234
239
  node = original;
235
- original = this.original.get(node);
240
+ original = this.original.get(node.id);
236
241
  }
237
242
  return node;
238
243
  }
@@ -260,7 +265,7 @@ export class EmitContext extends NodeFactory {
260
265
  return name;
261
266
  let node = info.node!;
262
267
  const id = info.id;
263
- let original = this.original.get(node);
268
+ let original = this.original.get(node.id);
264
269
  while (original !== undefined) {
265
270
  node = original;
266
271
  if (node instanceof Identifier || node instanceof PrivateIdentifier) {
@@ -275,7 +280,7 @@ export class EmitContext extends NodeFactory {
275
280
  continue;
276
281
  }
277
282
  }
278
- original = this.original.get(node);
283
+ original = this.original.get(node.id);
279
284
  }
280
285
  return node;
281
286
  }
@@ -425,6 +425,8 @@ class Directives {
425
425
  private readonly byLine = new Map<number, { pos: number; end: number; kind: CommentDirectiveKind }>();
426
426
 
427
427
  constructor(readonly file: SourceFile) {
428
+ // Most files have no directives, and need no line starts.
429
+ if (file.commentDirectives.length === 0) return;
428
430
  const lineStarts = file.diagnosticFile().getLineStarts();
429
431
  for (const directive of file.commentDirectives) {
430
432
  const line = computeLineOfPosition(lineStarts, directive.pos);
@@ -152,12 +152,19 @@ export class Program implements OutputPathsHost {
152
152
  this.includeProcessor = processed.includeProcessor;
153
153
  for (const diagnostic of previous.programDiagnosticsList) this.programDiagnosticsList.push(diagnostic);
154
154
  for (const path of previous.emitBlockingPaths) this.emitBlockingPaths.add(path);
155
- this.symlinks = previous.symlinks;
155
+ // The files and include reasons it takes from a program shared with checker threads are immutable, and
156
+ // so is that program's symlink cache: this one computes its own then (`getSymlinkCache`).
157
+ this.shared = previous.shared;
158
+ if (!previous.shared) this.symlinks = previous.symlinks;
159
+ // The same files are emitted, so the common source directory is the same. Its diagnostics are those
160
+ // `previous` was created with (`IncludeProcessor.copy`).
161
+ this.commonSourceDirectoryValue = previous.commonSourceDirectoryValue;
156
162
  } else {
157
163
  this.processed = (loader ?? new FileLoader(host, commandLine)).load();
158
164
  this.includeProcessor = this.processed.includeProcessor;
159
165
  this.verifyCompilerOptions();
160
166
  }
167
+ this.includeProcessor.noteProgramCreated();
161
168
  }
162
169
 
163
170
  /**