tsc-ts 0.0.6 → 0.0.8

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 (85) hide show
  1. package/README.md +1 -1
  2. package/dist/api/compiler/ast.d.ts +57 -18
  3. package/dist/api/compiler/ast.js +134 -39
  4. package/dist/api/compiler/binder-utilities.js +2 -2
  5. package/dist/api/compiler/binder.js +6 -6
  6. package/dist/api/compiler/checker-calls.js +4 -4
  7. package/dist/api/compiler/checker-contextual.js +1 -1
  8. package/dist/api/compiler/checker-declaration-order.js +3 -2
  9. package/dist/api/compiler/checker-declared-types.js +6 -3
  10. package/dist/api/compiler/checker-deprecation.js +14 -13
  11. package/dist/api/compiler/checker-destructuring.js +3 -2
  12. package/dist/api/compiler/checker-emit-helpers.d.ts +2 -1
  13. package/dist/api/compiler/checker-emit-helpers.js +5 -4
  14. package/dist/api/compiler/checker-grammar.js +5 -5
  15. package/dist/api/compiler/checker-inference.d.ts +20 -10
  16. package/dist/api/compiler/checker-inference.js +48 -25
  17. package/dist/api/compiler/checker-members.d.ts +27 -0
  18. package/dist/api/compiler/checker-members.js +165 -0
  19. package/dist/api/compiler/checker-modules.d.ts +14 -0
  20. package/dist/api/compiler/checker-modules.js +73 -1
  21. package/dist/api/compiler/checker-symbol-types.js +5 -5
  22. package/dist/api/compiler/checker-symbols.js +3 -1
  23. package/dist/api/compiler/checker.d.ts +16 -0
  24. package/dist/api/compiler/checker.js +17 -0
  25. package/dist/api/compiler/diagnostics.js +9 -5
  26. package/dist/api/compiler/parallel-parse.js +3 -1
  27. package/dist/api/compiler/parser.d.ts +7 -0
  28. package/dist/api/compiler/parser.js +73 -41
  29. package/dist/api/compiler/printer/factory-base.js +8 -8
  30. package/dist/api/compiler/printer/factory.js +4 -4
  31. package/dist/api/compiler/printer/printer.js +6 -6
  32. package/dist/api/compiler/program-checker.d.ts +5 -0
  33. package/dist/api/compiler/program-checker.js +11 -1
  34. package/dist/api/compiler/relations.js +8 -3
  35. package/dist/api/compiler/reparser.js +13 -5
  36. package/dist/api/compiler/transformers/class-fields.js +3 -3
  37. package/dist/api/compiler/transformers/commonjs-module.js +3 -3
  38. package/dist/api/compiler/transformers/declarations-pseudo.js +2 -2
  39. package/dist/api/compiler/transformers/module.js +2 -2
  40. package/dist/api/compiler/transformers/optional-chain.js +3 -3
  41. package/dist/api/compiler/transformers/subtree-facts.js +2 -2
  42. package/dist/api/compiler/transformers/tagged-template.js +2 -2
  43. package/dist/api/compiler/transformers/type-eraser.js +2 -2
  44. package/dist/api/compiler/transformers/visitor-base.js +3 -3
  45. package/dist/api/compiler/tsconfig.js +2 -2
  46. package/package.json +9 -9
  47. package/src/compiler/ast.ts +184 -59
  48. package/src/compiler/binder-utilities.ts +2 -1
  49. package/src/compiler/binder.ts +11 -5
  50. package/src/compiler/checker-calls.ts +5 -3
  51. package/src/compiler/checker-contextual.ts +1 -1
  52. package/src/compiler/checker-declaration-order.ts +3 -2
  53. package/src/compiler/checker-declared-types.ts +6 -3
  54. package/src/compiler/checker-deprecation.ts +13 -11
  55. package/src/compiler/checker-destructuring.ts +11 -2
  56. package/src/compiler/checker-emit-helpers.ts +5 -4
  57. package/src/compiler/checker-grammar.ts +5 -3
  58. package/src/compiler/checker-inference.ts +49 -25
  59. package/src/compiler/checker-members.ts +164 -0
  60. package/src/compiler/checker-modules.ts +92 -1
  61. package/src/compiler/checker-symbol-types.ts +14 -4
  62. package/src/compiler/checker-symbols.ts +4 -1
  63. package/src/compiler/checker.ts +19 -0
  64. package/src/compiler/decoder.ts +5 -4
  65. package/src/compiler/diagnostics.ts +10 -5
  66. package/src/compiler/encoder.ts +10 -5
  67. package/src/compiler/parallel-parse.ts +3 -1
  68. package/src/compiler/parser.ts +93 -39
  69. package/src/compiler/printer/factory-base.ts +14 -7
  70. package/src/compiler/printer/factory.ts +5 -3
  71. package/src/compiler/printer/printer.ts +8 -6
  72. package/src/compiler/program-checker.ts +10 -1
  73. package/src/compiler/relations.ts +10 -2
  74. package/src/compiler/reparser.ts +14 -4
  75. package/src/compiler/transformers/class-fields.ts +12 -2
  76. package/src/compiler/transformers/commonjs-module.ts +3 -2
  77. package/src/compiler/transformers/declarations-pseudo.ts +2 -1
  78. package/src/compiler/transformers/declarations.ts +1 -1
  79. package/src/compiler/transformers/module.ts +2 -1
  80. package/src/compiler/transformers/optional-chain.ts +5 -2
  81. package/src/compiler/transformers/subtree-facts.ts +2 -1
  82. package/src/compiler/transformers/tagged-template.ts +2 -2
  83. package/src/compiler/transformers/type-eraser.ts +2 -1
  84. package/src/compiler/transformers/visitor-base.ts +10 -5
  85. package/src/compiler/tsconfig.ts +2 -1
@@ -57,7 +57,78 @@ export function resolveExternalModuleNameWorker(c, location, moduleReference, mo
57
57
  return undefined;
58
58
  return resolveExternalModule(c, location, getText(moduleReference), moduleNotFoundError, ignoreErrors ? undefined : moduleReference, isForAugmentation);
59
59
  }
60
+ /** A `resolveExternalModule` result that reported nothing, and the arguments it was computed for. */
61
+ export class ModuleResolution {
62
+ moduleReference;
63
+ moduleNotFoundError;
64
+ isForAugmentation;
65
+ symbol;
66
+ constructor(moduleReference, moduleNotFoundError, isForAugmentation, symbol) {
67
+ this.moduleReference = moduleReference;
68
+ this.moduleNotFoundError = moduleNotFoundError;
69
+ this.isForAugmentation = isForAugmentation;
70
+ this.symbol = symbol;
71
+ }
72
+ }
73
+ /**
74
+ * The module symbol `moduleReference` resolves to from `location`, reporting resolution errors at
75
+ * `errorNode`. Each name an import or export declaration lists resolves its module specifier again,
76
+ * with the same result and the same diagnostics: a result that reported nothing is kept for the
77
+ * specifier and returned to later calls from the same declaration (`sharesSpecifierContext`).
78
+ */
60
79
  export function resolveExternalModule(c, location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation) {
80
+ // An augmentation merged later can give the resolved module a new merged symbol, so results are
81
+ // kept only once every augmentation is merged.
82
+ const shared = c.modulesMerged && errorNode !== undefined && sharesSpecifierContext(location, errorNode);
83
+ if (shared) {
84
+ const known = c.moduleResolutions.get(errorNode);
85
+ if (known !== undefined &&
86
+ known.moduleReference === moduleReference &&
87
+ known.moduleNotFoundError === moduleNotFoundError &&
88
+ known.isForAugmentation === isForAugmentation)
89
+ return known.symbol;
90
+ }
91
+ const reports = c.reports;
92
+ const symbol = resolveExternalModuleWorker(c, location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation);
93
+ if (shared && c.reports === reports)
94
+ c.moduleResolutions.set(errorNode, new ModuleResolution(moduleReference, moduleNotFoundError, isForAugmentation, symbol));
95
+ return symbol;
96
+ }
97
+ /**
98
+ * Whether a resolution from `location` with errors at `errorNode` depends on `location` only through
99
+ * the declaration that `errorNode` is the module specifier of: `location` is that declaration, a
100
+ * clause or specifier inside it, or the specifier itself. The resolution mode, the emittability of
101
+ * the import and its resolution-mode attributes then all come from that declaration.
102
+ */
103
+ function sharesSpecifierContext(location, errorNode) {
104
+ const declaration = errorNode.parent;
105
+ if (declaration === undefined ||
106
+ (declaration.kind !== 273 /* SyntaxKind.ImportDeclaration */ &&
107
+ declaration.kind !== 346 /* SyntaxKind.JSImportDeclaration */ &&
108
+ declaration.kind !== 279 /* SyntaxKind.ExportDeclaration */) ||
109
+ getModuleSpecifier(declaration) !== errorNode)
110
+ return false;
111
+ for (let current = location; current !== undefined; current = current.parent)
112
+ switch (current.kind) {
113
+ case 273 /* SyntaxKind.ImportDeclaration */:
114
+ case 346 /* SyntaxKind.JSImportDeclaration */:
115
+ case 279 /* SyntaxKind.ExportDeclaration */:
116
+ return current === declaration;
117
+ case 274 /* SyntaxKind.ImportClause */:
118
+ case 276 /* SyntaxKind.NamedImports */:
119
+ case 275 /* SyntaxKind.NamespaceImport */:
120
+ case 277 /* SyntaxKind.ImportSpecifier */:
121
+ case 280 /* SyntaxKind.NamedExports */:
122
+ case 281 /* SyntaxKind.NamespaceExport */:
123
+ case 282 /* SyntaxKind.ExportSpecifier */:
124
+ break;
125
+ default:
126
+ if (current !== errorNode)
127
+ return false;
128
+ }
129
+ return false;
130
+ }
131
+ function resolveExternalModuleWorker(c, location, moduleReference, moduleNotFoundError, errorNode, isForAugmentation) {
61
132
  if (errorNode !== undefined && moduleReference.startsWith('@types/'))
62
133
  c.error(errorNode, 1302 /* Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1 */, moduleReference.substring(7), moduleReference);
63
134
  const ambient = tryFindAmbientModule(c, moduleReference, true);
@@ -490,7 +561,8 @@ function isOnlyImportableAsDefault(c, usage, resolvedModule) {
490
561
  const moduleSymbol = resolvedModule ?? resolveExternalModuleName(c, usage, usage, true);
491
562
  const targetFile = moduleSymbol !== undefined ? getSourceFileOfModuleSymbol(moduleSymbol) : undefined;
492
563
  return (targetFile !== undefined &&
493
- (isJsonSourceFile(targetFile) || getDeclarationFileExtension(targetFile.fileName) === '.d.json.ts'));
564
+ (isJsonSourceFile(targetFile) ||
565
+ (targetFile.fileName.endsWith('.d.json.ts') && getDeclarationFileExtension(targetFile.fileName) === '.d.json.ts')));
494
566
  }
495
567
  /** The source file that declares a module: its value declaration, or its first declaration that is not an augmentation. */
496
568
  function getSourceFileOfModuleSymbol(symbol) {
@@ -26,7 +26,7 @@ import { getTypeForBindingElement, getTypeFromBindingPattern } from './checker-d
26
26
  import { checkRightHandSideOfForOf } from './checker-statements.js';
27
27
  import { getTypeWithFacts, hasTypeFacts, getNonNullableType } from './checker-flow.js';
28
28
  import { getTypeOfModuleExportsSymbol, getWidenedTypeForAssignmentDeclaration } from './checker-javascript.js';
29
- import { copyDeclarations, getDeclarations, getSymbolId } from './symbol.js';
29
+ import { copyDeclarations, declarationAt, declarationCount, getDeclarations, getSymbolId, } from './symbol.js';
30
30
  export function getTypeOfSymbol(c, symbol) {
31
31
  const checkFlags = symbol.checkFlags;
32
32
  if ((checkFlags & 65536 /* CheckFlags.DeferredType */) !== 0)
@@ -748,11 +748,11 @@ export function isReadonlySymbol(c, symbol) {
748
748
  (getDeclarationNodeFlagsFromSymbol(symbol) & 6 /* NodeFlags.Constant */) !== 0) ||
749
749
  ((symbol.flags & 98304 /* SymbolFlags.Accessor */) !== 0 && (symbol.flags & 65536 /* SymbolFlags.SetAccessor */) === 0) ||
750
750
  (symbol.flags & 8 /* SymbolFlags.EnumMember */) !== 0 ||
751
- someReadonlyAssignmentDeclaration(c, getDeclarations(symbol)));
751
+ someReadonlyAssignmentDeclaration(c, symbol));
752
752
  }
753
- function someReadonlyAssignmentDeclaration(c, declarations) {
754
- for (const d of declarations)
755
- if (isReadonlyAssignmentDeclaration(c, d))
753
+ function someReadonlyAssignmentDeclaration(c, symbol) {
754
+ for (let i = 0; i < declarationCount(symbol); i++)
755
+ if (isReadonlyAssignmentDeclaration(c, declarationAt(symbol, i)))
756
756
  return true;
757
757
  return false;
758
758
  }
@@ -1459,9 +1459,11 @@ export function symbolIsValue(c, symbol) {
1459
1459
  function isDeclarationContainedBy(symbol, container) {
1460
1460
  const declaration = symbol.valueDeclaration;
1461
1461
  if (declaration !== undefined)
1462
- for (const d of getDeclarations(container))
1462
+ for (let i = 0; i < declarationCount(container); i++) {
1463
+ const d = declarationAt(container, i);
1463
1464
  if (declaration.pos >= d.pos && declaration.end <= d.end)
1464
1465
  return true;
1466
+ }
1465
1467
  return false;
1466
1468
  }
1467
1469
  /** Value members other than signatures and index signatures, declared ones first, each part ordered by declaration. */
@@ -6,6 +6,7 @@ import { Diagnostic, type DiagnosticMessage, Diagnostics } from './diagnostics.j
6
6
  import { type CompilerOptions, ModuleKind, ScriptTarget } from './options.js';
7
7
  import { CheckFlags, Symbol, SymbolFlags, type SymbolTable } from './symbol.js';
8
8
  import { IndexInfo, IntrinsicType, LiteralType, MemberNames, NodeLinks, ObjectFlags, ObjectType, Signature, SignatureFlags, SymbolLinks, type Type, TypeFlags, TypeMapper, TypeParameter, TypePredicate, VarianceFlags, TypeListCache, TypeListTable, type ConditionalType, type InterfaceType, type TypeChecking } from './checker-types.js';
9
+ import type { ModuleResolution } from './checker-modules.js';
9
10
  import { CheckerNameResolver, type LibGlobals, type MergedGlobals, TableChanges, SuggestionNameResolver } from './checker-symbols.js';
10
11
  import { Relation, RelationKey, type InternedRelationKey, type Relater, TypeComparer } from './relations.js';
11
12
  import { TypeNodeVisitor } from './checker-source-file.js';
@@ -19,6 +20,7 @@ import { SourceFileMetadata } from './program-utilities.js';
19
20
  import type { GrammarChecker } from './checker-grammar.js';
20
21
  import type { ResolvedModule } from './module-resolution-types.js';
21
22
  import type { ModuleSpecifierHost } from './module-specifiers.js';
23
+ import type { PropertyListIndex } from './checker-members.js';
22
24
  /** What the checker needs from a program. */
23
25
  export declare abstract class CheckerHost {
24
26
  abstract getCompilerOptions(): CompilerOptions;
@@ -151,6 +153,15 @@ export declare class Checker implements TypeChecking {
151
153
  currentNode: Node | undefined;
152
154
  readonly diagnostics: DiagnosticCollection;
153
155
  readonly suggestionDiagnostics: DiagnosticCollection;
156
+ /** Diagnostics and suggestions reported so far, whether kept or not (`resolveExternalModule`'s cache). */
157
+ reports: number;
158
+ /** `resolveExternalModule` results that reported nothing, by module specifier (checker-modules.ts). */
159
+ readonly moduleResolutions: Map<Node, ModuleResolution>;
160
+ /**
161
+ * Whether ambient modules and module augmentations are merged. Merging can give a module a new
162
+ * merged symbol, so `resolveExternalModule` keeps results only from then on.
163
+ */
164
+ modulesMerged: boolean;
154
165
  /** Module specifiers of `import("…")` types, by module symbol id, importing file path and resolution mode. */
155
166
  readonly moduleSpecifiers: Map<string, string>;
156
167
  /** Specifier generation for hosts without a program. */
@@ -161,6 +172,11 @@ export declare class Checker implements TypeChecking {
161
172
  readonly sideHolders: LinkTable<Type>;
162
173
  /** The same for signatures with side state (`signatureSideOf`), by signature id. */
163
174
  readonly signatureSideHolders: LinkTable<Signature>;
175
+ /**
176
+ * The indexes of long property lists that `propertiesRelatedTo` walks; before a list is indexed, its uses
177
+ * so far; null where a list repeats a name.
178
+ */
179
+ readonly propertyListIndexes: Map<Symbol[], number | PropertyListIndex | null>;
164
180
  /** The type of a value symbol. */
165
181
  readonly symbolTypes: LinkTable<Type>;
166
182
  /** For instantiated and synthetic symbols, the symbol they come from. */
@@ -230,6 +230,15 @@ export class Checker {
230
230
  currentNode = undefined;
231
231
  diagnostics = new DiagnosticCollection();
232
232
  suggestionDiagnostics = new DiagnosticCollection();
233
+ /** Diagnostics and suggestions reported so far, whether kept or not (`resolveExternalModule`'s cache). */
234
+ reports = 0;
235
+ /** `resolveExternalModule` results that reported nothing, by module specifier (checker-modules.ts). */
236
+ moduleResolutions = new Map();
237
+ /**
238
+ * Whether ambient modules and module augmentations are merged. Merging can give a module a new
239
+ * merged symbol, so `resolveExternalModule` keeps results only from then on.
240
+ */
241
+ modulesMerged = false;
233
242
  /** Module specifiers of `import("…")` types, by module symbol id, importing file path and resolution mode. */
234
243
  moduleSpecifiers = new Map();
235
244
  /** Specifier generation for hosts without a program. */
@@ -243,6 +252,11 @@ export class Checker {
243
252
  sideHolders = new LinkTable();
244
253
  /** The same for signatures with side state (`signatureSideOf`), by signature id. */
245
254
  signatureSideHolders = new LinkTable();
255
+ /**
256
+ * The indexes of long property lists that `propertiesRelatedTo` walks; before a list is indexed, its uses
257
+ * so far; null where a list repeats a name.
258
+ */
259
+ propertyListIndexes = new Map();
246
260
  /** The type of a value symbol. */
247
261
  symbolTypes = new LinkTable();
248
262
  /** For instantiated and synthetic symbols, the symbol they come from. */
@@ -740,6 +754,7 @@ export class Checker {
740
754
  this.diagnostics.startLog();
741
755
  this.suggestionDiagnostics.startLog();
742
756
  mergeAmbientModulesAndAugmentations(this);
757
+ this.modulesMerged = true;
743
758
  this.mergeDiagnostics.push(this.diagnostics.takeLog(), this.suggestionDiagnostics.takeLog());
744
759
  }
745
760
  // ---- Public API
@@ -830,11 +845,13 @@ export class Checker {
830
845
  return diagnostic;
831
846
  }
832
847
  addDiagnostic(diagnostic) {
848
+ this.reports++;
833
849
  // Discard diagnostics created while at the maximum number of nested typeToString calls.
834
850
  if (this.serializationLevel < maxSerializationLevel)
835
851
  this.diagnostics.add(diagnostic);
836
852
  }
837
853
  addSuggestion(diagnostic) {
854
+ this.reports++;
838
855
  this.suggestionDiagnostics.add(diagnostic);
839
856
  }
840
857
  /** Reports an error, or a suggestion when `isError` is false. */
@@ -152,12 +152,14 @@ function threadCopyOf(file) {
152
152
  }
153
153
  return copy;
154
154
  }
155
+ /** The empty value of a file's position tables until they are computed. */
156
+ const noNumbers = [];
155
157
  /** The text of a file diagnostics point into. */
156
158
  export class DiagnosticFile {
157
159
  fileName;
158
160
  text;
159
161
  // Computed on first use; never empty once computed.
160
- lineStarts = [];
162
+ lineStarts = noNumbers;
161
163
  /** Whether this is a thread's copy of a possibly shared file (`threadCopyOf`). */
162
164
  isThreadCopy = false;
163
165
  constructor(fileName, text) {
@@ -186,8 +188,8 @@ export class DiagnosticFile {
186
188
  // The non-ASCII characters, in order: their UTF-16 offsets, UTF-8 lengths, and the UTF-8 bytes
187
189
  // beyond one per UTF-16 code unit of the text up to and including each. Unset until first used.
188
190
  nonASCIIStarts = undefined;
189
- nonASCIILengths = [];
190
- extraBytes = [];
191
+ nonASCIILengths = noNumbers;
192
+ extraBytes = noNumbers;
191
193
  getNonASCIIStarts() {
192
194
  let starts = this.nonASCIIStarts;
193
195
  if (starts === undefined) {
@@ -196,8 +198,8 @@ export class DiagnosticFile {
196
198
  if (Buffer.byteLength(text, 'utf8') !== text.length) {
197
199
  // Scanning the UTF-8 encoding is faster than reading each code unit.
198
200
  const bytes = Buffer.from(text, 'utf8');
199
- const lengths = this.nonASCIILengths;
200
- const extraBytes = this.extraBytes;
201
+ const lengths = [];
202
+ const extraBytes = [];
201
203
  let extra = 0;
202
204
  for (let i = 0; i < bytes.length; i++) {
203
205
  const b = bytes[i];
@@ -211,6 +213,8 @@ export class DiagnosticFile {
211
213
  extraBytes.push(extra);
212
214
  i += length - 1;
213
215
  }
216
+ this.nonASCIILengths = lengths;
217
+ this.extraBytes = extraBytes;
214
218
  }
215
219
  this.nonASCIIStarts = starts;
216
220
  }
@@ -445,7 +445,9 @@ export class ParseSession {
445
445
  this.onIdle(batch);
446
446
  }
447
447
  post(i, chunk) {
448
- this.workers[i].postMessage(chunk);
448
+ // Published, the chunk reaches the thread by pointer: copying its names into the message took the
449
+ // main thread 25-45 us per chunk, which during config read delays the matching of root files.
450
+ this.workers[i].postMessage(publish(chunk));
449
451
  this.outstanding[i] = this.outstanding[i] + 1;
450
452
  if (chunk.kinds[0] === 2 /* LoadKind.Library */ && largeLibraries.has(chunk.names[0]))
451
453
  this.blocked[i] = true;
@@ -135,6 +135,8 @@ export declare class Parser extends ScannerErrorReporter {
135
135
  reparseList: Node[];
136
136
  private readonly reparseLists;
137
137
  private reparseDepth;
138
+ private readonly listScratch;
139
+ private listDepth;
138
140
  reparsedClones: Node[];
139
141
  /** Nodes with eagerly parsed JSDoc, for rewinding. */
140
142
  jsDocInfos: Node[];
@@ -209,6 +211,11 @@ export declare class Parser extends ScannerErrorReporter {
209
211
  parseList(kind: ParsingContext, element: ListElement): NodeList;
210
212
  /** The list, or undefined if an element parser returned undefined. */
211
213
  parseDelimitedList(kind: ParsingContext, element: ListElement): NodeList | undefined;
214
+ /** The scratch array for a list at the next nesting depth, empty. */
215
+ private openList;
216
+ /** The elements collected in `list` (the scratch array from `openList`) as an array of their exact
217
+ * length, or the shared empty array; empties the scratch array for the next list at its depth. */
218
+ private closeList;
212
219
  /** The list; a missing list if `opening` is absent; undefined if an element parser returned undefined. */
213
220
  parseBracketedList(kind: ParsingContext, element: ListElement, opening: SyntaxKind, closing: SyntaxKind): NodeList | undefined;
214
221
  parseEmptyNodeList(): NodeList;
@@ -5,7 +5,7 @@
5
5
  // const file = parseSourceFile('/src/main.ts', text);
6
6
  // for (const statement of file.statements.nodes) console.log(statement.kind);
7
7
  // ```
8
- import { ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, AsExpression, AwaitExpression, BigIntLiteral, BinaryExpression, BindingElement, BindingPattern, Block, BreakStatement, CallExpression, CallSignatureDeclaration, CaseBlock, CaseOrDefaultClause, CatchClause, CheckJsDirective, ClassDeclaration, ClassExpression, ClassStaticBlockDeclaration, ComputedPropertyName, ConditionalExpression, ConditionalTypeNode, ConstructSignatureDeclaration, ConstructorDeclaration, ConstructorTypeNode, ContinueStatement, DebuggerStatement, Decorator, DeleteExpression, DoStatement, ElementAccessExpression, EmptyStatement, EnumDeclaration, EnumMember, ExportAssignment, ExportDeclaration, ExportSpecifier, ExpressionStatement, ExpressionWithTypeArguments, ExternalModuleIndicatorOptions, ExternalModuleReference, FileReference, ForInOrOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, FunctionTypeNode, GetAccessorDeclaration, HeritageClause, Identifier, IfStatement, ImportAttribute, ImportAttributes, ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportSpecifier, ImportTypeNode, IndexSignatureDeclaration, IndexedAccessTypeNode, InferTypeNode, InterfaceDeclaration, IntersectionTypeNode, JSDocAllType, JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, JSDocVariadicType, JsxAttribute, JsxAttributes, JsxClosingElement, JsxClosingFragment, JsxElement, JsxExpression, JsxFragment, JsxNamespacedName, JsxOpeningElement, JsxOpeningFragment, JsxSelfClosingElement, JsxSpreadAttribute, JsxText, KeywordExpression, KeywordTypeNode, LabeledStatement, LiteralTypeNode, MappedTypeNode, MetaProperty, MethodDeclaration, MethodSignatureDeclaration, MissingDeclaration, MissingNodeList, ModifierList, ModuleBlock, ModuleDeclaration, NamedExports, NamedImports, NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, NoSubstitutionTemplateLiteral, NodeList, NodeVisitor, NonNullExpression, NumericLiteral, ObjectLiteralExpression, OmittedExpression, OptionalTypeNode, ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, PostfixUnaryExpression, Pragma, PragmaArgument, PrefixUnaryExpression, PrivateIdentifier, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertySignatureDeclaration, QualifiedName, ReferenceIdentifier, RegularExpressionLiteral, RestTypeNode, ReturnStatement, SatisfiesExpression, SemicolonClassElement, SetAccessorDeclaration, ShorthandPropertyAssignment, SourceFile, SpreadAssignment, SpreadElement, StringLiteral, SwitchStatement, TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateMiddle, TemplateSpan, TemplateTail, ThisTypeNode, ThrowStatement, Token, TryStatement, TupleTypeNode, TypeAliasDeclaration, TypeAssertion, TypeLiteralNode, TypeOfExpression, TypeOperatorNode, TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnionTypeNode, VariableDeclaration, VariableDeclarationList, VariableStatement, VoidExpression, WhileStatement, WithStatement, YieldExpression, getBody, getIsTypeOnly, getModifiers, getName, getPostfixToken, getQuestionToken, getStatements, getText, getType, getTypeArguments, getTypeParameters, } from './ast.js';
8
+ import { appendToList, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, AsExpression, AwaitExpression, BigIntLiteral, BinaryExpression, BindingElement, BindingPattern, Block, BreakStatement, CallExpression, CallSignatureDeclaration, CaseBlock, CaseOrDefaultClause, CatchClause, CheckJsDirective, ClassDeclaration, ClassExpression, ClassStaticBlockDeclaration, ComputedPropertyName, ConditionalExpression, ConditionalTypeNode, ConstructSignatureDeclaration, ConstructorDeclaration, ConstructorTypeNode, ContinueStatement, DebuggerStatement, Decorator, DeleteExpression, DoStatement, ElementAccessExpression, emptyCommentDirectives, emptyDiagnostics, emptyFileReferences, emptyNodes, emptyPragmas, EmptyStatement, EnumDeclaration, EnumMember, ExportAssignment, ExportDeclaration, ExportSpecifier, ExpressionStatement, ExpressionWithTypeArguments, ExternalModuleIndicatorOptions, ExternalModuleReference, FileReference, ForInOrOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, FunctionTypeNode, GetAccessorDeclaration, HeritageClause, Identifier, IfStatement, ImportAttribute, ImportAttributes, ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportSpecifier, ImportTypeNode, IndexSignatureDeclaration, IndexedAccessTypeNode, InferTypeNode, InterfaceDeclaration, IntersectionTypeNode, JSDocAllType, JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, JSDocVariadicType, JsxAttribute, JsxAttributes, JsxClosingElement, JsxClosingFragment, JsxElement, JsxExpression, JsxFragment, JsxNamespacedName, JsxOpeningElement, JsxOpeningFragment, JsxSelfClosingElement, JsxSpreadAttribute, JsxText, KeywordExpression, KeywordTypeNode, LabeledStatement, LiteralTypeNode, MappedTypeNode, MetaProperty, MethodDeclaration, MethodSignatureDeclaration, MissingDeclaration, MissingNodeList, ModifierList, ModuleBlock, ModuleDeclaration, NamedExports, NamedImports, NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, NoSubstitutionTemplateLiteral, NodeList, NodeVisitor, NonNullExpression, NumericLiteral, ObjectLiteralExpression, OmittedExpression, OptionalTypeNode, ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, PostfixUnaryExpression, Pragma, PragmaArgument, PrefixUnaryExpression, PrivateIdentifier, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertySignatureDeclaration, QualifiedName, ReferenceIdentifier, RegularExpressionLiteral, RestTypeNode, ReturnStatement, SatisfiesExpression, SemicolonClassElement, SetAccessorDeclaration, ShorthandPropertyAssignment, SourceFile, SpreadAssignment, SpreadElement, StringLiteral, SwitchStatement, TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateMiddle, TemplateSpan, TemplateTail, ThisTypeNode, ThrowStatement, Token, TryStatement, TupleTypeNode, TypeAliasDeclaration, TypeAssertion, TypeLiteralNode, TypeOfExpression, TypeOperatorNode, TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnionTypeNode, VariableDeclaration, VariableDeclarationList, VariableStatement, VoidExpression, WhileStatement, WithStatement, YieldExpression, getBody, getIsTypeOnly, getModifiers, getName, getPostfixToken, getQuestionToken, getStatements, getText, getType, getTypeArguments, getTypeParameters, newCallExpression, newPropertyAssignment, } from './ast.js';
9
9
  import { canHaveDecorators, canHaveIllegalDecorators, compareNodePositions, getBinaryOperatorPrecedence, getExternalModuleName, getImportTypeNodeLiteral, getTextOfNodeFromSourceText, isAmbientModule, isAnyImportOrReExport, isAssignmentOperator, isClassMemberModifier, isFunctionLike, isImportCall, isImportMeta, isInJSFile, isKeyword, isKeywordOrPunctuation, isLeftHandSideExpression, isModifierKind, isRequireCall, isReservedWord, isStringLiteralLike, modifierToFlag, modifiersToFlags, nodeIsMissing, nodeIsPresent, tagNamesAreEquivalent, tokenIsIdentifierOrKeyword, tokenIsIdentifierOrKeywordOrGreaterThan, } from './ast-utilities.js';
10
10
  import { isLineBreak } from './character-codes.js';
11
11
  import { Diagnostic, messageCode } from './diagnostics.js';
@@ -52,6 +52,10 @@ function appendRange(to, from, start, end) {
52
52
  for (let i = start; i < end; i += 1)
53
53
  to.push(from[i]);
54
54
  }
55
+ // The nodes of every empty parsed list. A list's nodes are pushed into a new `[]`, which natively
56
+ // reserves room for its first elements (112 bytes); a parsed list never changes, so an empty one
57
+ // keeps this shared array instead and its builder is freed.
58
+ const emptyListNodes = [];
55
59
  /** Parses `text` as the file `fileName`. The script kind defaults to the one implied by the extension. */
56
60
  export function parseSourceFile(fileName, text, options) {
57
61
  const path = options === undefined ? fileName : options.path;
@@ -143,6 +147,10 @@ export class Parser extends ScannerErrorReporter {
143
147
  // receives reparsed nodes, and a fresh array per parsed list would be one more allocation each.
144
148
  reparseLists;
145
149
  reparseDepth;
150
+ // One scratch array per nesting depth of the lists being parsed. A list collects its elements in
151
+ // its depth's array and is copied out at its exact length, so the tree keeps no spare capacity.
152
+ listScratch;
153
+ listDepth;
146
154
  reparsedClones;
147
155
  /** Nodes with eagerly parsed JSDoc, for rewinding. */
148
156
  jsDocInfos;
@@ -196,6 +204,8 @@ export class Parser extends ScannerErrorReporter {
196
204
  this.reparseList = [];
197
205
  this.reparseLists = [this.reparseList];
198
206
  this.reparseDepth = 0;
207
+ this.listScratch = [];
208
+ this.listDepth = -1;
199
209
  this.reparsedClones = [];
200
210
  this.jsDocInfos = [];
201
211
  this.jsDocTable = undefined;
@@ -368,10 +378,10 @@ export class Parser extends ScannerErrorReporter {
368
378
  }
369
379
  // Nodes
370
380
  newNodeList(pos, end, nodes) {
371
- return new NodeList(pos, end, nodes);
381
+ return new NodeList(pos, end, nodes.length === 0 ? emptyListNodes : nodes);
372
382
  }
373
383
  newModifierList(pos, end, nodes) {
374
- return new ModifierList(pos, end, nodes, modifiersToFlags(nodes));
384
+ return new ModifierList(pos, end, nodes.length === 0 ? emptyListNodes : nodes, modifiersToFlags(nodes));
375
385
  }
376
386
  finishNode(node, pos) {
377
387
  return this.finishNodeWithEnd(node, pos, this.nodePos());
@@ -434,7 +444,8 @@ export class Parser extends ScannerErrorReporter {
434
444
  return new SourceFile(this.fileName, this.path, this.sourceText, this.externalModuleIndicatorOptions, statements, eof);
435
445
  }
436
446
  finishSourceFile(result, isDeclarationFile) {
437
- result.commentDirectives = this.scanner.getCommentDirectives();
447
+ const commentDirectives = this.scanner.getCommentDirectives();
448
+ result.commentDirectives = commentDirectives.length === 0 ? emptyCommentDirectives : commentDirectives;
438
449
  result.pragmas = getCommentPragmas(this.sourceText);
439
450
  this.processPragmasIntoFields(result);
440
451
  result.diagnostics = attachFileToDiagnostics(this.diagnostics, result);
@@ -452,9 +463,13 @@ export class Parser extends ScannerErrorReporter {
452
463
  // The table stays with the parser: when top-level await reparsing produces a second source
453
464
  // file, it finishes with the same table, which still holds the JSDoc of retained statements.
454
465
  result.jsDocs = this.jsDocTable;
455
- const clones = this.reparsedClones.slice();
456
- clones.sort(compareNodePositions);
457
- result.reparsedClones = clones;
466
+ if (this.reparsedClones.length === 0)
467
+ result.reparsedClones = emptyNodes;
468
+ else {
469
+ const clones = this.reparsedClones.slice();
470
+ clones.sort(compareNodePositions);
471
+ result.reparsedClones = clones;
472
+ }
458
473
  setExternalModuleIndicator(result);
459
474
  }
460
475
  parseToplevelStatement(index) {
@@ -601,7 +616,7 @@ export class Parser extends ScannerErrorReporter {
601
616
  this.reparseLists.push([]);
602
617
  const reparseList = this.reparseLists[depth];
603
618
  this.reparseList = reparseList;
604
- const list = [];
619
+ const list = this.openList();
605
620
  while (!this.isListTerminator(kind)) {
606
621
  if (this.isListElement(kind, false)) {
607
622
  const elt = this.parseListElement(element, list.length);
@@ -627,7 +642,7 @@ export class Parser extends ScannerErrorReporter {
627
642
  this.reparseDepth = depth - 1;
628
643
  this.reparseList = outerReparseList;
629
644
  this.parsingContexts = saveParsingContexts;
630
- return list;
645
+ return this.closeList(list);
631
646
  }
632
647
  parseList(kind, element) {
633
648
  const pos = this.nodePos();
@@ -639,12 +654,13 @@ export class Parser extends ScannerErrorReporter {
639
654
  const pos = this.nodePos();
640
655
  const saveParsingContexts = this.parsingContexts;
641
656
  this.parsingContexts |= 1 << kind;
642
- const list = [];
657
+ const list = this.openList();
643
658
  for (;;) {
644
659
  if (this.isListElement(kind, false)) {
645
660
  const startPos = this.nodePos();
646
661
  const result = this.parseListElement(element, list.length);
647
662
  if (result === this.noElement) {
663
+ this.closeList(list);
648
664
  this.parsingContexts = saveParsingContexts;
649
665
  return undefined;
650
666
  }
@@ -674,7 +690,24 @@ export class Parser extends ScannerErrorReporter {
674
690
  break;
675
691
  }
676
692
  this.parsingContexts = saveParsingContexts;
677
- return this.newNodeList(pos, this.nodePos(), list);
693
+ return this.newNodeList(pos, this.nodePos(), this.closeList(list));
694
+ }
695
+ /** The scratch array for a list at the next nesting depth, empty. */
696
+ openList() {
697
+ const depth = ++this.listDepth;
698
+ if (depth === this.listScratch.length)
699
+ this.listScratch.push([]);
700
+ return this.listScratch[depth];
701
+ }
702
+ /** The elements collected in `list` (the scratch array from `openList`) as an array of their exact
703
+ * length, or the shared empty array; empties the scratch array for the next list at its depth. */
704
+ closeList(list) {
705
+ this.listDepth--;
706
+ if (list.length === 0)
707
+ return emptyListNodes;
708
+ const nodes = list.slice();
709
+ list.length = 0;
710
+ return nodes;
678
711
  }
679
712
  /** The list; a missing list if `opening` is absent; undefined if an element parser returned undefined. */
680
713
  parseBracketedList(kind, element, opening, closing) {
@@ -2364,10 +2397,11 @@ export class Parser extends ScannerErrorReporter {
2364
2397
  ? this.parseFunctionOrConstructorTypeToError(isUnionType)
2365
2398
  : this.parseConstituentType(isUnionType);
2366
2399
  if (this.token() === operator || hasLeadingOperator) {
2367
- const types = [type];
2400
+ const types = this.openList();
2401
+ types.push(type);
2368
2402
  while (this.parseOptional(operator))
2369
2403
  types.push(this.parseFunctionOrConstructorTypeToError(isUnionType));
2370
- const list = this.newNodeList(pos, this.nodePos(), types);
2404
+ const list = this.newNodeList(pos, this.nodePos(), this.closeList(types));
2371
2405
  type = isUnionType ? new UnionTypeNode(list) : new IntersectionTypeNode(list);
2372
2406
  this.finishNode(type, pos);
2373
2407
  }
@@ -3166,14 +3200,14 @@ export class Parser extends ScannerErrorReporter {
3166
3200
  }
3167
3201
  parseTemplateTypeSpans() {
3168
3202
  const pos = this.nodePos();
3169
- const list = [];
3203
+ const list = this.openList();
3170
3204
  for (;;) {
3171
3205
  const span = this.parseTemplateTypeSpan();
3172
3206
  list.push(span);
3173
3207
  if (span.literal.kind !== 16 /* SyntaxKind.TemplateMiddle */)
3174
3208
  break;
3175
3209
  }
3176
- return this.newNodeList(pos, this.nodePos(), list);
3210
+ return this.newNodeList(pos, this.nodePos(), this.closeList(list));
3177
3211
  }
3178
3212
  parseTemplateTypeSpan() {
3179
3213
  const pos = this.nodePos();
@@ -3273,12 +3307,10 @@ export class Parser extends ScannerErrorReporter {
3273
3307
  let hasTrailingModifier = false;
3274
3308
  let hasStaticModifier = false;
3275
3309
  const pos = this.nodePos();
3276
- let list;
3310
+ const list = this.openList();
3277
3311
  for (;;) {
3278
3312
  if (allowDecorators && this.token() === 59 /* SyntaxKind.AtToken */ && !hasTrailingModifier) {
3279
3313
  const decorator = this.parseDecorator();
3280
- if (list === undefined)
3281
- list = [];
3282
3314
  list.push(decorator);
3283
3315
  if (hasLeadingModifier)
3284
3316
  hasTrailingDecorator = true;
@@ -3289,8 +3321,6 @@ export class Parser extends ScannerErrorReporter {
3289
3321
  break;
3290
3322
  if (modifier.kind === 125 /* SyntaxKind.StaticKeyword */)
3291
3323
  hasStaticModifier = true;
3292
- if (list === undefined)
3293
- list = [];
3294
3324
  list.push(modifier);
3295
3325
  if (hasTrailingDecorator)
3296
3326
  hasTrailingModifier = true;
@@ -3298,7 +3328,8 @@ export class Parser extends ScannerErrorReporter {
3298
3328
  hasLeadingModifier = true;
3299
3329
  }
3300
3330
  }
3301
- return list === undefined ? undefined : this.newModifierList(pos, this.nodePos(), list);
3331
+ const nodes = this.closeList(list);
3332
+ return nodes.length === 0 ? undefined : this.newModifierList(pos, this.nodePos(), nodes);
3302
3333
  }
3303
3334
  parseDecorator() {
3304
3335
  const pos = this.nodePos();
@@ -3932,7 +3963,7 @@ export class Parser extends ScannerErrorReporter {
3932
3963
  const pos = this.nodePos();
3933
3964
  const saveParsingContexts = this.parsingContexts;
3934
3965
  this.parsingContexts |= 1 << 14 /* ParsingContext.JsxChildren */;
3935
- const list = [];
3966
+ const list = this.openList();
3936
3967
  for (;;) {
3937
3968
  // Like tsgo, this leaves the parser's current token unchanged.
3938
3969
  const currentToken = this.scanner.reScanJsxToken(true);
@@ -3948,7 +3979,7 @@ export class Parser extends ScannerErrorReporter {
3948
3979
  break;
3949
3980
  }
3950
3981
  this.parsingContexts = saveParsingContexts;
3951
- return this.newNodeList(pos, this.nodePos(), list);
3982
+ return this.newNodeList(pos, this.nodePos(), this.closeList(list));
3952
3983
  }
3953
3984
  parseJsxChild(openingTag, token) {
3954
3985
  switch (token) {
@@ -4449,7 +4480,7 @@ export class Parser extends ScannerErrorReporter {
4449
4480
  const inner = expression;
4450
4481
  const argumentList = this.parseArgumentList();
4451
4482
  const isOptionalChain = questionDotToken !== undefined || this.tryReparseOptionalChain(expression);
4452
- expression = this.checkJSSyntax(this.finishNode(new CallExpression(expression, questionDotToken, typeArguments, argumentList, isOptionalChain ? 32 /* NodeFlags.OptionalChain */ : 0 /* NodeFlags.None */), pos));
4483
+ expression = this.checkJSSyntax(this.finishNode(newCallExpression(expression, questionDotToken, typeArguments, argumentList, isOptionalChain ? 32 /* NodeFlags.OptionalChain */ : 0 /* NodeFlags.None */, (this.contextFlags & 65536 /* NodeFlags.JavaScriptFile */) !== 0), pos));
4453
4484
  this.unparseExpressionWithTypeArguments(inner, typeArguments, expression);
4454
4485
  continue;
4455
4486
  }
@@ -4510,14 +4541,14 @@ export class Parser extends ScannerErrorReporter {
4510
4541
  }
4511
4542
  parseTemplateSpans(isTaggedTemplate) {
4512
4543
  const pos = this.nodePos();
4513
- const list = [];
4544
+ const list = this.openList();
4514
4545
  for (;;) {
4515
4546
  const span = this.parseTemplateSpan(isTaggedTemplate);
4516
4547
  list.push(span);
4517
4548
  if (span.literal.kind !== 16 /* SyntaxKind.TemplateMiddle */)
4518
4549
  break;
4519
4550
  }
4520
- return this.newNodeList(pos, this.nodePos(), list);
4551
+ return this.newNodeList(pos, this.nodePos(), this.closeList(list));
4521
4552
  }
4522
4553
  parseTemplateSpan(isTaggedTemplate) {
4523
4554
  const pos = this.nodePos();
@@ -4636,7 +4667,7 @@ export class Parser extends ScannerErrorReporter {
4636
4667
  else {
4637
4668
  this.parseExpected(58 /* SyntaxKind.ColonToken */);
4638
4669
  const initializer = this.parseAssignmentExpressionOrHigherAllowIn();
4639
- node = new PropertyAssignment(modifiers, name, postfixToken, undefined, initializer);
4670
+ node = newPropertyAssignment(modifiers, name, postfixToken, undefined, initializer, (this.contextFlags & 65536 /* NodeFlags.JavaScriptFile */) !== 0);
4640
4671
  }
4641
4672
  return this.finishWithJSDoc(node, pos, jsdoc);
4642
4673
  }
@@ -5540,9 +5571,9 @@ export class Parser extends ScannerErrorReporter {
5540
5571
  // Pragmas
5541
5572
  processPragmasIntoFields(file) {
5542
5573
  file.checkJsDirective = undefined;
5543
- file.referencedFiles = [];
5544
- file.typeReferenceDirectives = [];
5545
- file.libReferenceDirectives = [];
5574
+ file.referencedFiles = emptyFileReferences;
5575
+ file.typeReferenceDirectives = emptyFileReferences;
5576
+ file.libReferenceDirectives = emptyFileReferences;
5546
5577
  for (const pragma of file.pragmas) {
5547
5578
  switch (pragma.name) {
5548
5579
  case 'reference': {
@@ -5561,13 +5592,13 @@ export class Parser extends ScannerErrorReporter {
5561
5592
  const parsed = resolutionMode !== undefined
5562
5593
  ? this.parseResolutionMode(resolutionMode.value, resolutionMode.pos, resolutionMode.end)
5563
5594
  : ModuleKind.None;
5564
- file.typeReferenceDirectives.push(new FileReference(types.pos, types.end, types.value, parsed, isPreserved));
5595
+ file.typeReferenceDirectives = appendToList(file.typeReferenceDirectives, new FileReference(types.pos, types.end, types.value, parsed, isPreserved));
5565
5596
  }
5566
5597
  else if (lib !== undefined) {
5567
- file.libReferenceDirectives.push(new FileReference(lib.pos, lib.end, lib.value, ModuleKind.None, isPreserved));
5598
+ file.libReferenceDirectives = appendToList(file.libReferenceDirectives, new FileReference(lib.pos, lib.end, lib.value, ModuleKind.None, isPreserved));
5568
5599
  }
5569
5600
  else if (path !== undefined) {
5570
- file.referencedFiles.push(new FileReference(path.pos, path.end, path.value, ModuleKind.None, isPreserved));
5601
+ file.referencedFiles = appendToList(file.referencedFiles, new FileReference(path.pos, path.end, path.value, ModuleKind.None, isPreserved));
5571
5602
  }
5572
5603
  else {
5573
5604
  this.parseErrorAt(pragma.range.pos, pragma.range.end, 57 /* Diagnostics.Invalid_reference_directive_syntax */);
@@ -5776,7 +5807,7 @@ function typeHasBlockingError(node) {
5776
5807
  }
5777
5808
  function attachFileToDiagnostics(diagnostics, file) {
5778
5809
  if (diagnostics.length === 0)
5779
- return diagnostics;
5810
+ return emptyDiagnostics;
5780
5811
  const diagnosticFile = file.diagnosticFile();
5781
5812
  for (const d of diagnostics) {
5782
5813
  d.file = diagnosticFile;
@@ -6034,12 +6065,13 @@ function nextTokenIsNotColon(p) {
6034
6065
  }
6035
6066
  // Pragmas
6036
6067
  function getCommentPragmas(sourceText) {
6037
- const pragmas = [];
6038
6068
  const ranges = getLeadingCommentRanges(sourceText, 0);
6039
- if (ranges !== undefined)
6040
- for (const range of ranges)
6041
- extractPragmas(range, sourceText.substring(range.pos, range.end), pragmas);
6042
- return pragmas;
6069
+ if (ranges === undefined)
6070
+ return emptyPragmas;
6071
+ const pragmas = [];
6072
+ for (const range of ranges)
6073
+ extractPragmas(range, sourceText.substring(range.pos, range.end), pragmas);
6074
+ return pragmas.length === 0 ? emptyPragmas : pragmas;
6043
6075
  }
6044
6076
  function extractPragmas(range, text, pragmas) {
6045
6077
  if (range.kind === 2 /* SyntaxKind.SingleLineCommentTrivia */) {
@@ -6200,10 +6232,10 @@ function collectModuleReferences(file, node, inAmbientModule) {
6200
6232
  (inAmbientModule || hasModifierFlag(node, 128 /* ModifierFlags.Ambient */) || file.isDeclarationFile)) {
6201
6233
  const nameText = getText(node.name);
6202
6234
  if (file.externalModuleIndicator !== undefined || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
6203
- file.moduleAugmentations.push(node.name);
6235
+ file.moduleAugmentations = appendToList(file.moduleAugmentations, node.name);
6204
6236
  }
6205
6237
  else if (!inAmbientModule) {
6206
- file.ambientModuleNames.push(nameText);
6238
+ file.ambientModuleNames = appendToList(file.ambientModuleNames, nameText);
6207
6239
  const body = node.body;
6208
6240
  if (body !== undefined) {
6209
6241
  const statements = getStatements(body);