tsc-ts 0.0.6 → 0.0.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 (71) hide show
  1. package/dist/api/compiler/ast.d.ts +57 -18
  2. package/dist/api/compiler/ast.js +134 -39
  3. package/dist/api/compiler/binder-utilities.js +2 -2
  4. package/dist/api/compiler/binder.js +6 -6
  5. package/dist/api/compiler/checker-calls.js +4 -4
  6. package/dist/api/compiler/checker-contextual.js +1 -1
  7. package/dist/api/compiler/checker-emit-helpers.d.ts +2 -1
  8. package/dist/api/compiler/checker-emit-helpers.js +5 -4
  9. package/dist/api/compiler/checker-grammar.js +5 -5
  10. package/dist/api/compiler/checker-inference.d.ts +20 -10
  11. package/dist/api/compiler/checker-inference.js +48 -25
  12. package/dist/api/compiler/checker-members.d.ts +27 -0
  13. package/dist/api/compiler/checker-members.js +165 -0
  14. package/dist/api/compiler/checker-modules.d.ts +14 -0
  15. package/dist/api/compiler/checker-modules.js +73 -1
  16. package/dist/api/compiler/checker.d.ts +16 -0
  17. package/dist/api/compiler/checker.js +17 -0
  18. package/dist/api/compiler/diagnostics.js +9 -5
  19. package/dist/api/compiler/parallel-parse.js +3 -1
  20. package/dist/api/compiler/parser.js +33 -23
  21. package/dist/api/compiler/printer/factory-base.js +8 -8
  22. package/dist/api/compiler/printer/factory.js +4 -4
  23. package/dist/api/compiler/printer/printer.js +6 -6
  24. package/dist/api/compiler/program-checker.d.ts +5 -0
  25. package/dist/api/compiler/program-checker.js +11 -1
  26. package/dist/api/compiler/relations.js +8 -3
  27. package/dist/api/compiler/reparser.js +13 -5
  28. package/dist/api/compiler/transformers/class-fields.js +3 -3
  29. package/dist/api/compiler/transformers/commonjs-module.js +3 -3
  30. package/dist/api/compiler/transformers/declarations-pseudo.js +2 -2
  31. package/dist/api/compiler/transformers/module.js +2 -2
  32. package/dist/api/compiler/transformers/optional-chain.js +3 -3
  33. package/dist/api/compiler/transformers/subtree-facts.js +2 -2
  34. package/dist/api/compiler/transformers/tagged-template.js +2 -2
  35. package/dist/api/compiler/transformers/type-eraser.js +2 -2
  36. package/dist/api/compiler/transformers/visitor-base.js +3 -3
  37. package/dist/api/compiler/tsconfig.js +2 -2
  38. package/package.json +8 -8
  39. package/src/compiler/ast.ts +184 -59
  40. package/src/compiler/binder-utilities.ts +2 -1
  41. package/src/compiler/binder.ts +11 -5
  42. package/src/compiler/checker-calls.ts +5 -3
  43. package/src/compiler/checker-contextual.ts +1 -1
  44. package/src/compiler/checker-emit-helpers.ts +5 -4
  45. package/src/compiler/checker-grammar.ts +5 -3
  46. package/src/compiler/checker-inference.ts +49 -25
  47. package/src/compiler/checker-members.ts +164 -0
  48. package/src/compiler/checker-modules.ts +92 -1
  49. package/src/compiler/checker.ts +19 -0
  50. package/src/compiler/decoder.ts +5 -4
  51. package/src/compiler/diagnostics.ts +10 -5
  52. package/src/compiler/encoder.ts +10 -5
  53. package/src/compiler/parallel-parse.ts +3 -1
  54. package/src/compiler/parser.ts +53 -23
  55. package/src/compiler/printer/factory-base.ts +14 -7
  56. package/src/compiler/printer/factory.ts +5 -3
  57. package/src/compiler/printer/printer.ts +8 -6
  58. package/src/compiler/program-checker.ts +10 -1
  59. package/src/compiler/relations.ts +10 -2
  60. package/src/compiler/reparser.ts +14 -4
  61. package/src/compiler/transformers/class-fields.ts +12 -2
  62. package/src/compiler/transformers/commonjs-module.ts +3 -2
  63. package/src/compiler/transformers/declarations-pseudo.ts +2 -1
  64. package/src/compiler/transformers/declarations.ts +1 -1
  65. package/src/compiler/transformers/module.ts +2 -1
  66. package/src/compiler/transformers/optional-chain.ts +5 -2
  67. package/src/compiler/transformers/subtree-facts.ts +2 -1
  68. package/src/compiler/transformers/tagged-template.ts +2 -2
  69. package/src/compiler/transformers/type-eraser.ts +2 -1
  70. package/src/compiler/transformers/visitor-base.ts +10 -5
  71. package/src/compiler/tsconfig.ts +2 -1
@@ -186,6 +186,11 @@ import {
186
186
  YieldExpression,
187
187
  BigIntLiteral,
188
188
  Identifier,
189
+ propertyAssignmentPostfixToken,
190
+ propertyAssignmentType,
191
+ callQuestionDotToken,
192
+ propertyAssignmentModifiers,
193
+ callTypeArguments,
189
194
  } from './ast.js';
190
195
  import { getJSDoc } from './parser.js';
191
196
  import { SyntaxKind } from './syntax-kind.js';
@@ -883,8 +888,8 @@ function childrenPropertyMask(node: Node): number {
883
888
  case SyntaxKind.CallExpression:
884
889
  return node instanceof CallExpression
885
890
  ? ((node as CallExpression).expression !== undefined ? 1 : 0) |
886
- ((node as CallExpression).questionDotToken !== undefined ? 2 : 0) |
887
- ((node as CallExpression).typeArguments !== undefined ? 4 : 0) |
891
+ (callQuestionDotToken(node as CallExpression) !== undefined ? 2 : 0) |
892
+ (callTypeArguments(node as CallExpression) !== undefined ? 4 : 0) |
888
893
  ((node as CallExpression).arguments !== undefined ? 8 : 0)
889
894
  : 0;
890
895
  case SyntaxKind.NewExpression:
@@ -938,10 +943,10 @@ function childrenPropertyMask(node: Node): number {
938
943
  return node instanceof SpreadAssignment ? ((node as SpreadAssignment).expression !== undefined ? 1 : 0) : 0;
939
944
  case SyntaxKind.PropertyAssignment:
940
945
  return node instanceof PropertyAssignment
941
- ? (hasModifiers((node as PropertyAssignment).modifiers) ? 1 : 0) |
946
+ ? (hasModifiers(propertyAssignmentModifiers(node as PropertyAssignment)) ? 1 : 0) |
942
947
  ((node as PropertyAssignment).name !== undefined ? 2 : 0) |
943
- ((node as PropertyAssignment).postfixToken !== undefined ? 4 : 0) |
944
- ((node as PropertyAssignment).type !== undefined ? 8 : 0) |
948
+ (propertyAssignmentPostfixToken(node as PropertyAssignment) !== undefined ? 4 : 0) |
949
+ (propertyAssignmentType(node as PropertyAssignment) !== undefined ? 8 : 0) |
945
950
  ((node as PropertyAssignment).initializer !== undefined ? 16 : 0)
946
951
  : 0;
947
952
  case SyntaxKind.ShorthandPropertyAssignment:
@@ -494,7 +494,9 @@ export class ParseSession {
494
494
  }
495
495
 
496
496
  private post(i: number, chunk: LoadMessage): void {
497
- this.workers[i]!.postMessage(chunk);
497
+ // Published, the chunk reaches the thread by pointer: copying its names into the message took the
498
+ // main thread 25-45 us per chunk, which during config read delays the matching of root files.
499
+ this.workers[i]!.postMessage(publish(chunk));
498
500
  this.outstanding[i] = this.outstanding[i]! + 1;
499
501
  if (chunk.kinds[0] === LoadKind.Library && largeLibraries.has(chunk.names[0]!)) this.blocked[i] = true;
500
502
  this.busy++;
@@ -6,6 +6,7 @@
6
6
  // for (const statement of file.statements.nodes) console.log(statement.kind);
7
7
  // ```
8
8
  import {
9
+ appendToList,
9
10
  ArrayLiteralExpression,
10
11
  ArrayTypeNode,
11
12
  ArrowFunction,
@@ -38,6 +39,11 @@ import {
38
39
  DeleteExpression,
39
40
  DoStatement,
40
41
  ElementAccessExpression,
42
+ emptyCommentDirectives,
43
+ emptyDiagnostics,
44
+ emptyFileReferences,
45
+ emptyNodes,
46
+ emptyPragmas,
41
47
  EmptyStatement,
42
48
  EnumDeclaration,
43
49
  EnumMember,
@@ -193,6 +199,8 @@ import {
193
199
  type Expression,
194
200
  type Statement,
195
201
  type TypeNode,
202
+ newCallExpression,
203
+ newPropertyAssignment,
196
204
  } from './ast.js';
197
205
  import {
198
206
  OperatorPrecedence,
@@ -392,6 +400,11 @@ function appendRange(to: Node[], from: readonly Node[], start: number, end: numb
392
400
  for (let i = start; i < end; i += 1) to.push(from[i]!);
393
401
  }
394
402
 
403
+ // The nodes of every empty parsed list. A list's nodes are pushed into a new `[]`, which natively
404
+ // reserves room for its first elements (112 bytes); a parsed list never changes, so an empty one
405
+ // keeps this shared array instead and its builder is freed.
406
+ const emptyListNodes: Node[] = [];
407
+
395
408
  /** Parses `text` as the file `fileName`. The script kind defaults to the one implied by the extension. */
396
409
  export function parseSourceFile(fileName: string, text: string, options?: ParseOptions): SourceFile {
397
410
  const path = options === undefined ? fileName : options.path;
@@ -759,11 +772,11 @@ export class Parser extends ScannerErrorReporter {
759
772
  // Nodes
760
773
 
761
774
  newNodeList(pos: number, end: number, nodes: Node[]): NodeList {
762
- return new NodeList(pos, end, nodes);
775
+ return new NodeList(pos, end, nodes.length === 0 ? emptyListNodes : nodes);
763
776
  }
764
777
 
765
778
  newModifierList(pos: number, end: number, nodes: Node[]): ModifierList {
766
- return new ModifierList(pos, end, nodes, modifiersToFlags(nodes));
779
+ return new ModifierList(pos, end, nodes.length === 0 ? emptyListNodes : nodes, modifiersToFlags(nodes));
767
780
  }
768
781
 
769
782
  finishNode(node: Node, pos: number): Node {
@@ -839,7 +852,8 @@ export class Parser extends ScannerErrorReporter {
839
852
  }
840
853
 
841
854
  finishSourceFile(result: SourceFile, isDeclarationFile: boolean): void {
842
- result.commentDirectives = this.scanner.getCommentDirectives();
855
+ const commentDirectives = this.scanner.getCommentDirectives();
856
+ result.commentDirectives = commentDirectives.length === 0 ? emptyCommentDirectives : commentDirectives;
843
857
  result.pragmas = getCommentPragmas(this.sourceText);
844
858
  this.processPragmasIntoFields(result);
845
859
  result.diagnostics = attachFileToDiagnostics(this.diagnostics, result);
@@ -857,9 +871,12 @@ export class Parser extends ScannerErrorReporter {
857
871
  // The table stays with the parser: when top-level await reparsing produces a second source
858
872
  // file, it finishes with the same table, which still holds the JSDoc of retained statements.
859
873
  result.jsDocs = this.jsDocTable;
860
- const clones = this.reparsedClones.slice();
861
- clones.sort(compareNodePositions);
862
- result.reparsedClones = clones;
874
+ if (this.reparsedClones.length === 0) result.reparsedClones = emptyNodes;
875
+ else {
876
+ const clones = this.reparsedClones.slice();
877
+ clones.sort(compareNodePositions);
878
+ result.reparsedClones = clones;
879
+ }
863
880
  setExternalModuleIndicator(result);
864
881
  }
865
882
 
@@ -5520,12 +5537,13 @@ export class Parser extends ScannerErrorReporter {
5520
5537
  const isOptionalChain = questionDotToken !== undefined || this.tryReparseOptionalChain(expression);
5521
5538
  expression = this.checkJSSyntax(
5522
5539
  this.finishNode(
5523
- new CallExpression(
5540
+ newCallExpression(
5524
5541
  expression,
5525
5542
  questionDotToken,
5526
5543
  typeArguments,
5527
5544
  argumentList,
5528
5545
  isOptionalChain ? NodeFlags.OptionalChain : NodeFlags.None,
5546
+ (this.contextFlags & NodeFlags.JavaScriptFile) !== 0,
5529
5547
  ),
5530
5548
  pos,
5531
5549
  ),
@@ -5753,7 +5771,14 @@ export class Parser extends ScannerErrorReporter {
5753
5771
  } else {
5754
5772
  this.parseExpected(SyntaxKind.ColonToken);
5755
5773
  const initializer = this.parseAssignmentExpressionOrHigherAllowIn();
5756
- node = new PropertyAssignment(modifiers, name, postfixToken, undefined, initializer);
5774
+ node = newPropertyAssignment(
5775
+ modifiers,
5776
+ name,
5777
+ postfixToken,
5778
+ undefined,
5779
+ initializer,
5780
+ (this.contextFlags & NodeFlags.JavaScriptFile) !== 0,
5781
+ );
5757
5782
  }
5758
5783
  return this.finishWithJSDoc(node, pos, jsdoc);
5759
5784
  }
@@ -6802,9 +6827,9 @@ export class Parser extends ScannerErrorReporter {
6802
6827
 
6803
6828
  processPragmasIntoFields(file: SourceFile): void {
6804
6829
  file.checkJsDirective = undefined;
6805
- file.referencedFiles = [];
6806
- file.typeReferenceDirectives = [];
6807
- file.libReferenceDirectives = [];
6830
+ file.referencedFiles = emptyFileReferences;
6831
+ file.typeReferenceDirectives = emptyFileReferences;
6832
+ file.libReferenceDirectives = emptyFileReferences;
6808
6833
  for (const pragma of file.pragmas) {
6809
6834
  switch (pragma.name) {
6810
6835
  case 'reference': {
@@ -6823,15 +6848,20 @@ export class Parser extends ScannerErrorReporter {
6823
6848
  resolutionMode !== undefined
6824
6849
  ? this.parseResolutionMode(resolutionMode.value, resolutionMode.pos, resolutionMode.end)
6825
6850
  : ModuleKind.None;
6826
- file.typeReferenceDirectives.push(
6851
+ file.typeReferenceDirectives = appendToList(
6852
+ file.typeReferenceDirectives,
6827
6853
  new FileReference(types.pos, types.end, types.value, parsed, isPreserved),
6828
6854
  );
6829
6855
  } else if (lib !== undefined) {
6830
- file.libReferenceDirectives.push(
6856
+ file.libReferenceDirectives = appendToList(
6857
+ file.libReferenceDirectives,
6831
6858
  new FileReference(lib.pos, lib.end, lib.value, ModuleKind.None, isPreserved),
6832
6859
  );
6833
6860
  } else if (path !== undefined) {
6834
- file.referencedFiles.push(new FileReference(path.pos, path.end, path.value, ModuleKind.None, isPreserved));
6861
+ file.referencedFiles = appendToList(
6862
+ file.referencedFiles,
6863
+ new FileReference(path.pos, path.end, path.value, ModuleKind.None, isPreserved),
6864
+ );
6835
6865
  } else {
6836
6866
  this.parseErrorAt(pragma.range.pos, pragma.range.end, Diagnostics.Invalid_reference_directive_syntax);
6837
6867
  }
@@ -7042,8 +7072,8 @@ function typeHasBlockingError(node: TypeNode | undefined): boolean {
7042
7072
  return node !== undefined && typeHasArrowFunctionBlockingParseError(node);
7043
7073
  }
7044
7074
 
7045
- function attachFileToDiagnostics(diagnostics: Diagnostic[], file: SourceFile): Diagnostic[] {
7046
- if (diagnostics.length === 0) return diagnostics;
7075
+ function attachFileToDiagnostics(diagnostics: Diagnostic[], file: SourceFile): readonly Diagnostic[] {
7076
+ if (diagnostics.length === 0) return emptyDiagnostics;
7047
7077
  const diagnosticFile = file.diagnosticFile();
7048
7078
  for (const d of diagnostics) {
7049
7079
  d.file = diagnosticFile;
@@ -7354,12 +7384,12 @@ function nextTokenIsNotColon(p: Parser): boolean {
7354
7384
 
7355
7385
  // Pragmas
7356
7386
 
7357
- function getCommentPragmas(sourceText: string): Pragma[] {
7358
- const pragmas: Pragma[] = [];
7387
+ function getCommentPragmas(sourceText: string): readonly Pragma[] {
7359
7388
  const ranges = getLeadingCommentRanges(sourceText, 0);
7360
- if (ranges !== undefined)
7361
- for (const range of ranges) extractPragmas(range, sourceText.substring(range.pos, range.end), pragmas);
7362
- return pragmas;
7389
+ if (ranges === undefined) return emptyPragmas;
7390
+ const pragmas: Pragma[] = [];
7391
+ for (const range of ranges) extractPragmas(range, sourceText.substring(range.pos, range.end), pragmas);
7392
+ return pragmas.length === 0 ? emptyPragmas : pragmas;
7363
7393
  }
7364
7394
 
7365
7395
  function extractPragmas(range: CommentRange, text: string, pragmas: Pragma[]): void {
@@ -7528,9 +7558,9 @@ function collectModuleReferences(file: SourceFile, node: Statement, inAmbientMod
7528
7558
  ) {
7529
7559
  const nameText = getText((node as ModuleDeclaration).name);
7530
7560
  if (file.externalModuleIndicator !== undefined || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
7531
- file.moduleAugmentations.push((node as ModuleDeclaration).name);
7561
+ file.moduleAugmentations = appendToList(file.moduleAugmentations, (node as ModuleDeclaration).name);
7532
7562
  } else if (!inAmbientModule) {
7533
- file.ambientModuleNames.push(nameText);
7563
+ file.ambientModuleNames = appendToList(file.ambientModuleNames, nameText);
7534
7564
  const body = (node as ModuleDeclaration).body;
7535
7565
  if (body !== undefined) {
7536
7566
  const statements = getStatements(body);
@@ -199,6 +199,13 @@ import {
199
199
  type Node,
200
200
  type NodeList,
201
201
  type Token,
202
+ propertyAssignmentPostfixToken,
203
+ propertyAssignmentType,
204
+ callQuestionDotToken,
205
+ propertyAssignmentModifiers,
206
+ callTypeArguments,
207
+ newCallExpression,
208
+ newPropertyAssignment,
202
209
  } from '../ast.js';
203
210
  import type { SyntaxKind } from '../syntax-kind.js';
204
211
 
@@ -359,12 +366,12 @@ export abstract class NodeFactoryBase {
359
366
  ): CallExpression {
360
367
  if (
361
368
  expression !== node.expression ||
362
- questionDotToken !== node.questionDotToken ||
363
- typeArguments !== node.typeArguments ||
369
+ questionDotToken !== callQuestionDotToken(node) ||
370
+ typeArguments !== callTypeArguments(node) ||
364
371
  args !== node.arguments ||
365
372
  flags !== node.flags
366
373
  ) {
367
- const updated = new CallExpression(expression, questionDotToken, typeArguments, args, flags);
374
+ const updated = newCallExpression(expression, questionDotToken, typeArguments, args, flags, false);
368
375
  this.finishUpdate(updated, node);
369
376
  return updated;
370
377
  }
@@ -2057,13 +2064,13 @@ export abstract class NodeFactoryBase {
2057
2064
  initializer: Expression,
2058
2065
  ): PropertyAssignment {
2059
2066
  if (
2060
- modifiers !== node.modifiers ||
2067
+ modifiers !== propertyAssignmentModifiers(node) ||
2061
2068
  name !== node.name ||
2062
- postfixToken !== node.postfixToken ||
2063
- typeNode !== node.type ||
2069
+ postfixToken !== propertyAssignmentPostfixToken(node) ||
2070
+ typeNode !== propertyAssignmentType(node) ||
2064
2071
  initializer !== node.initializer
2065
2072
  ) {
2066
- const updated = new PropertyAssignment(modifiers, name, postfixToken, typeNode, initializer);
2073
+ const updated = newPropertyAssignment(modifiers, name, postfixToken, typeNode, initializer, false);
2067
2074
  this.finishUpdate(updated, node);
2068
2075
  return updated;
2069
2076
  }
@@ -45,6 +45,8 @@ import {
45
45
  VariableDeclarationList,
46
46
  VariableStatement,
47
47
  VoidExpression,
48
+ newCallExpression,
49
+ newPropertyAssignment,
48
50
  } from '../ast.js';
49
51
  import { modifierToFlag } from '../ast-utilities.js';
50
52
  import { getNameOfDeclaration, getNonAssignedNameOfDeclaration, hasSyntacticModifier } from '../binder-utilities.js';
@@ -166,7 +168,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
166
168
 
167
169
  createCallExpression(expression: Node, args: Node[]): CallExpression {
168
170
  return this.created(
169
- new CallExpression(expression, undefined, undefined, this.createNodeList(args), NodeFlags.None),
171
+ newCallExpression(expression, undefined, undefined, this.createNodeList(args), NodeFlags.None, false),
170
172
  );
171
173
  }
172
174
 
@@ -265,7 +267,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
265
267
  }
266
268
 
267
269
  createPropertyAssignment(name: Node, initializer: Node): PropertyAssignment {
268
- return this.created(new PropertyAssignment(undefined, name, undefined, undefined, initializer));
270
+ return this.created(newPropertyAssignment(undefined, name, undefined, undefined, initializer, false));
269
271
  }
270
272
 
271
273
  createParameter(name: Node): ParameterDeclaration {
@@ -546,7 +548,7 @@ export abstract class NodeFactory extends NodeFactoryBase {
546
548
  createMethodCall(object: Node, method: string, args: Node[]): CallExpression {
547
549
  const callee = this.createPropertyAccessExpression(object, this.createIdentifier(method));
548
550
  const flags = object instanceof CallExpression ? object.flags & NodeFlags.OptionalChain : NodeFlags.None;
549
- return this.created(new CallExpression(callee, undefined, undefined, this.createNodeList(args), flags));
551
+ return this.created(newCallExpression(callee, undefined, undefined, this.createNodeList(args), flags, false));
550
552
  }
551
553
 
552
554
  /** `Global.method(...args)`, such as `Math.pow(a, b)`. */
@@ -157,6 +157,8 @@ import {
157
157
  getProperties,
158
158
  getStatements,
159
159
  getModifiers,
160
+ callQuestionDotToken,
161
+ callTypeArguments,
160
162
  } from '../ast.js';
161
163
  import { OperatorPrecedence } from '../ast-utilities.js';
162
164
  import {
@@ -2248,8 +2250,8 @@ export class Printer extends NameGeneratorHost {
2248
2250
  private emitCallExpression(node: CallExpression): boolean {
2249
2251
  const state = this.enterNode(node);
2250
2252
  this.emitCallee(node.expression, node);
2251
- this.emitOptionalToken(node.questionDotToken);
2252
- this.emitTypeArguments(node, node.typeArguments);
2253
+ this.emitOptionalToken(callQuestionDotToken(node));
2254
+ this.emitTypeArguments(node, callTypeArguments(node));
2253
2255
  this.emitList(ListItem.Argument, node, node.arguments, ListFormat.CallExpressionArguments);
2254
2256
  this.exitNode(node, state);
2255
2257
  return true;
@@ -2653,8 +2655,8 @@ export class Printer extends NameGeneratorHost {
2653
2655
  return factory.updateCallExpression(
2654
2656
  node,
2655
2657
  this.parenthesizeExpressionForNoAsi(node.expression),
2656
- node.questionDotToken,
2657
- node.typeArguments,
2658
+ callQuestionDotToken(node),
2659
+ callTypeArguments(node),
2658
2660
  node.arguments,
2659
2661
  node.flags,
2660
2662
  );
@@ -2921,8 +2923,8 @@ export class Printer extends NameGeneratorHost {
2921
2923
  this.write1('(');
2922
2924
  this.emitExpression(call.expression, OperatorPrecedence.Lowest);
2923
2925
  this.write1(')');
2924
- this.emitOptionalToken(call.questionDotToken);
2925
- this.emitTypeArguments(call, call.typeArguments);
2926
+ this.emitOptionalToken(callQuestionDotToken(call));
2927
+ this.emitTypeArguments(call, callTypeArguments(call));
2926
2928
  this.emitList(ListItem.Argument, call, call.arguments, ListFormat.CallExpressionArguments);
2927
2929
  this.exitNode(call, callState);
2928
2930
  }
@@ -32,6 +32,11 @@ import { CommentDirectiveKind } from './types.js';
32
32
  /** What the checker needs, answered by a program. */
33
33
  export class ProgramCheckerHost extends CheckerHost {
34
34
  private specifierHost: ProgramModuleSpecifierHost | undefined = undefined;
35
+ /**
36
+ * `getSourceFileForResolvedModule` by resolved file name (null when there is none): every import of
37
+ * a module asks again, and the program finds a file by its path, which it computes from the name.
38
+ */
39
+ private readonly resolvedSourceFiles = new Map<string, SourceFile | null>();
35
40
 
36
41
  constructor(readonly program: Program) {
37
42
  super();
@@ -54,7 +59,11 @@ export class ProgramCheckerHost extends CheckerHost {
54
59
  }
55
60
 
56
61
  getSourceFileForResolvedModule(fileName: string): SourceFile | undefined {
57
- return this.program.getSourceFileForResolvedModule(fileName);
62
+ const known = this.resolvedSourceFiles.get(fileName);
63
+ if (known !== undefined) return known ?? undefined;
64
+ const file = this.program.getSourceFileForResolvedModule(fileName);
65
+ this.resolvedSourceFiles.set(fileName, file ?? null);
66
+ return file;
58
67
  }
59
68
 
60
69
  getModeForUsageLocation(file: SourceFile, location: Node): ModuleKind {
@@ -129,6 +129,8 @@ import {
129
129
  getResolvedMember,
130
130
  hasResolvedProperties,
131
131
  resolvedPropertiesAreOptional,
132
+ positionsOfNamesFoundInSource,
133
+ firstUnmatchedProperty,
132
134
  } from './checker-members.js';
133
135
  import {
134
136
  getParentOfSymbol,
@@ -2822,7 +2824,13 @@ export class Relater extends TypeComparer {
2822
2824
  !isObjectLiteralType(source) &&
2823
2825
  !isEmptyArrayLiteralType(c, source) &&
2824
2826
  !isTupleType(source);
2825
- const unmatchedProperty = getUnmatchedProperty(c, source, target, requireOptionalProperties, false);
2827
+ const targetProperties = getPropertiesOfType(c, target);
2828
+ // Where it is known which target names the source has, nothing else is looked up by name.
2829
+ const found = positionsOfNamesFoundInSource(c, source, target, targetProperties);
2830
+ const unmatchedProperty =
2831
+ found !== undefined
2832
+ ? firstUnmatchedProperty(c, targetProperties, found, requireOptionalProperties)
2833
+ : getUnmatchedProperty(c, source, target, requireOptionalProperties, false);
2826
2834
  if (unmatchedProperty !== undefined) {
2827
2835
  if (reportErrors && shouldReportUnmatchedPropertyError(c, source, target))
2828
2836
  this.reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties);
@@ -2842,7 +2850,7 @@ export class Relater extends TypeComparer {
2842
2850
  }
2843
2851
  }
2844
2852
  const numericNamesOnly = isTupleType(source) && isTupleType(target);
2845
- for (const targetProp of getPropertiesOfType(c, target)) {
2853
+ for (const targetProp of found !== undefined ? found.map((i) => targetProperties[i]!) : targetProperties) {
2846
2854
  if (excludedProperties !== undefined && excludedProperties.has(targetProp.name)) continue;
2847
2855
  const name = targetProp.name;
2848
2856
  if (
@@ -84,6 +84,7 @@ import {
84
84
  getTypeExpression,
85
85
  getTypeParameters,
86
86
  type TypeNode,
87
+ FullPropertyAssignment,
87
88
  } from './ast.js';
88
89
  import {
89
90
  isAssignmentOperator,
@@ -855,10 +856,14 @@ export class Reparser {
855
856
  if (parent.kind !== SyntaxKind.ClassDeclaration && parent.kind !== SyntaxKind.ClassExpression) return false;
856
857
  const className = tag.className;
857
858
  const heritageClauses = getHeritageClauses(parent);
859
+ // Parsed lists may share their nodes array (empty ones do), so a longer list is a new list.
858
860
  if (heritageClauses !== undefined) {
859
861
  for (const clause of heritageClauses.nodes)
860
862
  if (clause instanceof HeritageClause && (clause as HeritageClause).token === SyntaxKind.ImplementsKeyword) {
861
- (clause as HeritageClause).types.nodes.push(this.addDeepCloneReparse(className));
863
+ const types = (clause as HeritageClause).types;
864
+ const nodes = types.nodes.slice();
865
+ nodes.push(this.addDeepCloneReparse(className));
866
+ (clause as HeritageClause).types = this.p.newNodeList(types.pos, types.end, nodes);
862
867
  this.finishMutatedNode(clause);
863
868
  return true;
864
869
  }
@@ -868,7 +873,11 @@ export class Reparser {
868
873
  this.finishReparsedNode(heritageClause, className);
869
874
  if (heritageClauses === undefined)
870
875
  setHeritageClauses(parent, this.p.newNodeList(className.pos, className.end, [heritageClause]));
871
- else heritageClauses.nodes.push(heritageClause);
876
+ else {
877
+ const nodes = heritageClauses.nodes.slice();
878
+ nodes.push(heritageClause);
879
+ setHeritageClauses(parent, this.p.newNodeList(heritageClauses.pos, heritageClauses.end, nodes));
880
+ }
872
881
  this.finishMutatedNode(parent);
873
882
  return true;
874
883
  }
@@ -1420,8 +1429,9 @@ function setType(node: Node, value: Node): boolean {
1420
1429
  (node as PropertyDeclaration).type = value;
1421
1430
  return true;
1422
1431
  }
1423
- if (node instanceof PropertyAssignment) {
1424
- (node as PropertyAssignment).type = value;
1432
+ // Property assignments in JavaScript files, which are the ones reparsed, are full ones.
1433
+ if (node instanceof FullPropertyAssignment) {
1434
+ (node as FullPropertyAssignment).type = value;
1425
1435
  return true;
1426
1436
  }
1427
1437
  if (node instanceof ShorthandPropertyAssignment) {
@@ -55,6 +55,9 @@ import {
55
55
  getMembers,
56
56
  getModifiers,
57
57
  getName,
58
+ callQuestionDotToken,
59
+ callTypeArguments,
60
+ newCallExpression,
58
61
  } from '../ast.js';
59
62
  import { isLeftHandSideExpression } from '../ast-utilities.js';
60
63
  import {
@@ -1209,7 +1212,14 @@ export class ClassFieldsTransformer extends Transformer {
1209
1212
  if (node instanceof CallExpression)
1210
1213
  return factory.cloneNode(
1211
1214
  node,
1212
- new CallExpression(node.expression, node.questionDotToken, node.typeArguments, node.arguments, node.flags),
1215
+ newCallExpression(
1216
+ node.expression,
1217
+ callQuestionDotToken(node),
1218
+ callTypeArguments(node),
1219
+ node.arguments,
1220
+ node.flags,
1221
+ false,
1222
+ ),
1213
1223
  );
1214
1224
  return factory.cloneNode(node, node.deepClone());
1215
1225
  }
@@ -1232,7 +1242,7 @@ export class ClassFieldsTransformer extends Transformer {
1232
1242
  const call = factory.created(
1233
1243
  new PropertyAccessExpression(
1234
1244
  target,
1235
- optional ? node.questionDotToken : undefined,
1245
+ optional ? callQuestionDotToken(node) : undefined,
1236
1246
  factory.createIdentifier('call'),
1237
1247
  optional ? NodeFlags.OptionalChain : NodeFlags.None,
1238
1248
  ),
@@ -63,6 +63,7 @@ import {
63
63
  ModifierList,
64
64
  getElements,
65
65
  getName,
66
+ callQuestionDotToken,
66
67
  } from '../ast.js';
67
68
  import { getExternalModuleName, isImportCall, isInJSFile, isRequireCall } from '../ast-utilities.js';
68
69
  import { isAssignmentExpression, isDestructuringAssignment } from '../binder-utilities.js';
@@ -1248,7 +1249,7 @@ export class CommonJSModuleTransformer extends Transformer {
1248
1249
  const updated = this.factory.updateCallExpression(
1249
1250
  node,
1250
1251
  expression,
1251
- node.questionDotToken,
1252
+ callQuestionDotToken(node),
1252
1253
  undefined,
1253
1254
  this.visitNodes(node.arguments)!,
1254
1255
  node.flags,
@@ -1340,7 +1341,7 @@ export class CommonJSModuleTransformer extends Transformer {
1340
1341
  if (rewritten !== first || visitedRest !== rest)
1341
1342
  args = new NodeList(args.pos, args.end, [rewritten].concat(visitedRest));
1342
1343
  }
1343
- return factory.updateCallExpression(node, expression, node.questionDotToken, undefined, args, node.flags);
1344
+ return factory.updateCallExpression(node, expression, callQuestionDotToken(node), undefined, args, node.flags);
1344
1345
  }
1345
1346
 
1346
1347
  private visitTaggedTemplateExpression(node: TaggedTemplateExpression): Node {
@@ -33,6 +33,7 @@ import {
33
33
  getSymbol,
34
34
  getType,
35
35
  getTypeParameters,
36
+ propertyAssignmentPostfixToken,
36
37
  } from '../ast.js';
37
38
  import { isFunctionLike, nodeIsMissing } from '../ast-utilities.js';
38
39
  import { getCombinedNodeFlags, hasSyntacticModifier, isIdentifierNamed } from '../binder-utilities.js';
@@ -544,7 +545,7 @@ export class PseudoChecker {
544
545
  }
545
546
  case SyntaxKind.PropertyAssignment: {
546
547
  const assignment = property as PropertyAssignment;
547
- const postfix = assignment.postfixToken;
548
+ const postfix = propertyAssignmentPostfixToken(assignment);
548
549
  members.push(
549
550
  new PseudoMember(
550
551
  PseudoMemberKind.Property,
@@ -2751,7 +2751,7 @@ const modifierKindsInOrder: SyntaxKind[] = [
2751
2751
  SyntaxKind.OutKeyword,
2752
2752
  ];
2753
2753
 
2754
- function preservedReferences(references: FileReference[]): FileReference[] {
2754
+ function preservedReferences(references: readonly FileReference[]): FileReference[] {
2755
2755
  const result: FileReference[] = [];
2756
2756
  for (const reference of references)
2757
2757
  if (reference.preserve)
@@ -26,6 +26,7 @@ import {
26
26
  StringLiteral,
27
27
  NoSubstitutionTemplateLiteral,
28
28
  Identifier,
29
+ callQuestionDotToken,
29
30
  } from '../ast.js';
30
31
  import { isAnyImportOrReExport, isImportCall, isInJSFile, isRequireCall } from '../ast-utilities.js';
31
32
  import { type CompilerOptions, JsxEmit, ModuleKind, getEmitModuleKind, getIsolatedModules } from '../options.js';
@@ -392,7 +393,7 @@ export class ESModuleTransformer extends Transformer {
392
393
  return factory.updateCallExpression(
393
394
  node,
394
395
  this.visitNode(node.expression)!,
395
- node.questionDotToken,
396
+ callQuestionDotToken(node),
396
397
  undefined,
397
398
  new NodeList(node.arguments.pos, node.arguments.end, [argument].concat(rest)),
398
399
  node.flags,
@@ -9,6 +9,8 @@ import {
9
9
  PropertyAccessExpression,
10
10
  SyntheticReferenceExpression,
11
11
  TaggedTemplateExpression,
12
+ callQuestionDotToken,
13
+ newCallExpression,
12
14
  } from '../ast.js';
13
15
  import { skipParentheses } from '../binder-utilities.js';
14
16
  import type { EmitContext } from '../printer/emit-context.js';
@@ -201,12 +203,13 @@ export class OptionalChainTransformer extends Transformer {
201
203
  );
202
204
  } else
203
205
  rightExpression = factory.created(
204
- new CallExpression(
206
+ newCallExpression(
205
207
  rightExpression,
206
208
  undefined,
207
209
  undefined,
208
210
  this.visitNodes(segment.arguments)!,
209
211
  NodeFlags.None,
212
+ false,
210
213
  ),
211
214
  );
212
215
  }
@@ -231,7 +234,7 @@ export class OptionalChainTransformer extends Transformer {
231
234
  function questionDotTokenOf(node: Node): Node | undefined {
232
235
  if (node instanceof PropertyAccessExpression) return node.questionDotToken;
233
236
  if (node instanceof ElementAccessExpression) return node.questionDotToken;
234
- if (node instanceof CallExpression) return node.questionDotToken;
237
+ if (node instanceof CallExpression) return callQuestionDotToken(node);
235
238
  return undefined;
236
239
  }
237
240
 
@@ -32,6 +32,7 @@ import {
32
32
  JsxSelfClosingElement,
33
33
  HeritageClause,
34
34
  getModifiers,
35
+ callTypeArguments,
35
36
  } from '../ast.js';
36
37
  import { ClusteredIntLinkTable } from '../link-tables.js';
37
38
  import { isTypeNodeKind } from '../printer/utilities.js';
@@ -233,7 +234,7 @@ function ownFacts(node: Node): Facts {
233
234
  ? Facts.TypeScript
234
235
  : Facts.None;
235
236
  case SyntaxKind.CallExpression:
236
- return node instanceof CallExpression && node.typeArguments !== undefined ? Facts.TypeScript : Facts.None;
237
+ return node instanceof CallExpression && callTypeArguments(node) !== undefined ? Facts.TypeScript : Facts.None;
237
238
  case SyntaxKind.NewExpression:
238
239
  return node instanceof NewExpression && node.typeArguments !== undefined ? Facts.TypeScript : Facts.None;
239
240
  case SyntaxKind.TaggedTemplateExpression:
@@ -2,7 +2,6 @@
2
2
  // calls with a `__makeTemplateObject` template object.
3
3
  import {
4
4
  ArrayLiteralExpression,
5
- CallExpression,
6
5
  type Node,
7
6
  NodeFlags,
8
7
  NoSubstitutionTemplateLiteral,
@@ -13,6 +12,7 @@ import {
13
12
  TemplateMiddle,
14
13
  TemplateSpan,
15
14
  TemplateTail,
15
+ newCallExpression,
16
16
  } from '../ast.js';
17
17
  import type { EmitContext } from '../printer/emit-context.js';
18
18
  import { getSourceTextOfNode } from '../printer/utilities.js';
@@ -106,7 +106,7 @@ export class TaggedTemplateTransformer extends Transformer {
106
106
  templateObject = factory.createLogicalOr(name, factory.createAssignment(name, helperCall));
107
107
  }
108
108
  args.unshift(templateObject);
109
- const call = factory.created(new CallExpression(tag, undefined, undefined, factory.createNodeList(args), 0));
109
+ const call = factory.created(newCallExpression(tag, undefined, undefined, factory.createNodeList(args), 0, false));
110
110
  call.pos = node.pos;
111
111
  call.end = node.end;
112
112
  return call;