diff --git a/src/compiler/_namespaces/ts.NodeConstructors.ts b/src/compiler/_namespaces/ts.NodeConstructors.ts deleted file mode 100644 index 8c79d37ff27c2..0000000000000 --- a/src/compiler/_namespaces/ts.NodeConstructors.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../nodeConstructors"; diff --git a/src/compiler/_namespaces/ts.ObjectConstructors.ts b/src/compiler/_namespaces/ts.ObjectConstructors.ts deleted file mode 100644 index a546cb6c55e3b..0000000000000 --- a/src/compiler/_namespaces/ts.ObjectConstructors.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../objectConstructors"; diff --git a/src/compiler/_namespaces/ts.ts b/src/compiler/_namespaces/ts.ts index 791cdc7be5904..cf8cf4a010792 100644 --- a/src/compiler/_namespaces/ts.ts +++ b/src/compiler/_namespaces/ts.ts @@ -14,7 +14,6 @@ export * from "../diagnosticInformationMap.generated"; export * from "../scanner"; export * from "../utilitiesPublic"; export * from "../utilities"; -export * from "../factory/baseNodeFactory"; export * from "../factory/parenthesizerRules"; export * from "../factory/nodeConverters"; export * from "../factory/nodeFactory"; @@ -72,11 +71,5 @@ import * as moduleSpecifiers from "./ts.moduleSpecifiers"; export { moduleSpecifiers }; import * as performance from "./ts.performance"; export { performance }; -/** @internal */ -import * as NodeConstructors from "./ts.NodeConstructors"; -/** @internal */ -export { NodeConstructors }; -/** @internal */ -import * as ObjectConstructors from "./ts.ObjectConstructors"; -/** @internal */ -export { ObjectConstructors }; +/** @internal */ export * as NodeConstructors from "../nodeConstructors"; +/** @internal */ export * as ObjectConstructors from "../objectConstructors"; diff --git a/src/compiler/factory/baseNodeFactory.ts b/src/compiler/factory/baseNodeFactory.ts deleted file mode 100644 index 6f690627eac67..0000000000000 --- a/src/compiler/factory/baseNodeFactory.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { IdentifierObject, NodeObject, PrivateIdentifierObject, SourceFileObject, TokenObject } from "../nodeConstructors"; -import { - Node, - SyntaxKind, -} from "../_namespaces/ts"; - -/** - * A `BaseNodeFactory` is an abstraction over an `ObjectAllocator` that handles caching `Node` constructors - * and allocating `Node` instances based on a set of predefined types. - * - * @internal - */ -export interface BaseNodeFactory { - createBaseSourceFileNode(): Node; - createBaseIdentifierNode(): Node; - createBasePrivateIdentifierNode(): Node; - createBaseTokenNode(kind: SyntaxKind): Node; - createBaseNode(kind: SyntaxKind): Node; -} - -/** - * Creates a `BaseNodeFactory` which can be used to create `Node` instances from the constructors provided by the object allocator. - * - * @internal - */ -export function createBaseNodeFactory(): BaseNodeFactory { - return { - createBaseSourceFileNode, - createBaseIdentifierNode, - createBasePrivateIdentifierNode, - createBaseTokenNode, - createBaseNode - }; - - function createBaseSourceFileNode(): Node { - return new SourceFileObject(); - } - - function createBaseIdentifierNode(): Node { - return new IdentifierObject(); - } - - function createBasePrivateIdentifierNode(): Node { - return new PrivateIdentifierObject(); - } - - function createBaseTokenNode(kind: SyntaxKind): Node { - return new TokenObject(kind); - } - - function createBaseNode(kind: SyntaxKind): Node { - return new NodeObject(kind); - } -} diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 09fa4592c7599..23ed04d584486 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -17,7 +17,6 @@ import { AsteriskToken, AwaitExpression, AwaitKeyword, - BaseNodeFactory, BigIntLiteral, BinaryExpression, BinaryOperator, @@ -59,7 +58,6 @@ import { ConstructorTypeNode, ConstructSignatureDeclaration, ContinueStatement, - createBaseNodeFactory, createNodeConverters, createParenthesizerRules, createScanner, @@ -467,15 +465,15 @@ import { WithStatement, YieldExpression, } from "../_namespaces/ts"; -// import { -// Node as NodeObject, -// Identifier as IdentifierObject, -// PrivateIdentifier as PrivateIdentifierObject, -// Token as TokenObject, -// SourceFile as SourceFileObject, -// } from "../nodeConstructors"; import { - SourceMapSourceObject as SourceMapSourceObject, + IdentifierObject, + NodeObject, + PrivateIdentifierObject, + SourceFileObject, + TokenObject, +} from "../nodeConstructors"; +import { + SourceMapSourceObject, } from "../objectConstructors"; let nextAutoGenerateId = 0; @@ -491,6 +489,8 @@ export const enum NodeFactoryFlags { NoIndentationOnFreshPropertyAccess = 1 << 2, // Do not set an `original` pointer when updating a node. NoOriginalNode = 1 << 3, + // Mark nodes as synthetic + MarkSynthetic = 1 << 4, } const nodeFactoryPatchers: ((factory: NodeFactory) => void)[] = []; @@ -507,7 +507,8 @@ export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) { * * @internal */ -export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory { +export function createNodeFactory(flags: NodeFactoryFlags): NodeFactory { + const markSynthetic = (flags & NodeFactoryFlags.MarkSynthetic) === NodeFactoryFlags.MarkSynthetic; const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal; // Lazily load the parenthesizer, node converters, and some factory methods until they are used. @@ -531,7 +532,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const factory: NodeFactory = { get parenthesizer() { return parenthesizerRules(); }, get converters() { return converters(); }, - baseFactory, flags, createNodeArray, createNumericLiteral, @@ -1074,7 +1074,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function createBaseNode(kind: T["kind"]) { - return baseFactory.createBaseNode(kind) as Mutable; + const node = new NodeObject(kind) as Node as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; + return node; } function createBaseDeclaration(kind: T["kind"]) { @@ -1160,7 +1162,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // function createBaseIdentifier(escapedText: __String, originalKeywordKind: SyntaxKind | undefined) { - const node = baseFactory.createBaseIdentifierNode() as Mutable; + const node = new IdentifierObject() as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; node.originalKeywordKind = originalKeywordKind; node.escapedText = escapedText; node.autoGenerate = undefined; @@ -1257,7 +1260,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function createBasePrivateIdentifier(escapedText: __String) { - const node = baseFactory.createBasePrivateIdentifierNode() as Mutable; + const node = new PrivateIdentifierObject() as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; node.escapedText = escapedText; node.autoGenerate = undefined; node.transformFlags |= TransformFlags.ContainsClassFields; @@ -1306,7 +1310,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // function createBaseToken(kind: T["kind"]) { - return baseFactory.createBaseTokenNode(kind) as Mutable; + const node = new TokenObject(kind) as Node as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; + return node; } // @api @@ -6033,7 +6039,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode endOfFileToken: EndOfFileToken, flags: NodeFlags ) { - const node = baseFactory.createBaseSourceFileNode() as Mutable; + const node = new SourceFileObject() as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; node.statements = createNodeArray(statements); node.endOfFileToken = endOfFileToken; node.flags |= flags; @@ -6116,7 +6123,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function cloneSourceFileWorker(source: SourceFile) { // TODO: This mechanism for cloning results in megamorphic property reads and writes. In future perf-related // work, we should consider switching explicit property assignments instead of using `for..in`. - const node = baseFactory.createBaseSourceFileNode() as Mutable; + const node = new SourceFileObject() as Mutable; + if (markSynthetic) node.flags |= NodeFlags.Synthesized; node.flags |= source.flags & ~NodeFlags.Synthesized; for (const p in source) { if (hasProperty(node, p) || !hasProperty(source, p)) { @@ -6452,11 +6460,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } const clone = - !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : - baseFactory.createBaseNode(node.kind) as T; + !isNodeKind(node.kind) ? new TokenObject(node.kind) as Node as Mutable : + new NodeObject(node.kind) as Node as Mutable; - (clone as Mutable).flags |= (node.flags & ~NodeFlags.Synthesized); - (clone as Mutable).transformFlags = node.transformFlags; + if (markSynthetic) clone.flags |= NodeFlags.Synthesized; + clone.flags |= (node.flags & ~NodeFlags.Synthesized); + clone.transformFlags = node.transformFlags; setOriginalNode(clone, node); for (const key in node) { @@ -7388,22 +7397,7 @@ export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { } } -const baseFactory = createBaseNodeFactory(); - -function makeSynthetic(node: Node) { - (node as Mutable).flags |= NodeFlags.Synthesized; - return node; -} - -const syntheticFactory: BaseNodeFactory = { - createBaseSourceFileNode: () => makeSynthetic(baseFactory.createBaseSourceFileNode()), - createBaseIdentifierNode: () => makeSynthetic(baseFactory.createBaseIdentifierNode()), - createBasePrivateIdentifierNode: () => makeSynthetic(baseFactory.createBasePrivateIdentifierNode()), - createBaseTokenNode: kind => makeSynthetic(baseFactory.createBaseTokenNode(kind)), - createBaseNode: kind => makeSynthetic(baseFactory.createBaseNode(kind)), -}; - -export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory); +export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess | NodeFactoryFlags.MarkSynthetic); export function createUnparsedSourceFile(text: string): UnparsedSource; export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 857e4dbd7edcf..6a98253b3bcbd 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,4 +1,3 @@ -import { IdentifierObject, NodeObject, PrivateIdentifierObject, SourceFileObject, TokenObject } from "./nodeConstructors"; import * as ts from "./_namespaces/ts"; import { AccessorDeclaration, @@ -17,7 +16,6 @@ import { AsteriskToken, attachFileToDiagnostics, AwaitExpression, - BaseNodeFactory, BinaryExpression, BinaryOperatorToken, BindingElement, @@ -401,21 +399,8 @@ const enum SpeculationKind { Reparse } -/** - * NOTE: You should not use this, it is only exported to support `createNode` in `~/src/deprecatedCompat/deprecations.ts`. - * - * @internal - */ -export const parseBaseNodeFactory: BaseNodeFactory = { - createBaseSourceFileNode: () => new SourceFileObject(), - createBaseIdentifierNode: () => new IdentifierObject(), - createBasePrivateIdentifierNode: () => new PrivateIdentifierObject(), - createBaseTokenNode: kind => new TokenObject(kind), - createBaseNode: kind => new NodeObject(kind), -}; - /** @internal */ -export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory); +export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules); function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); @@ -1410,22 +1395,7 @@ namespace Parser { const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; - function countNode(node: Node) { - nodeCount++; - return node; - } - - // Rather than using `createBaseNodeFactory` here, we establish a `BaseNodeFactory` that closes over the - // constructors above, which are reset each time `initializeState` is called. - const baseNodeFactory: BaseNodeFactory = { - createBaseSourceFileNode: () => countNode(new SourceFileObject()), - createBaseIdentifierNode: () => countNode(new IdentifierObject()), - createBasePrivateIdentifierNode: () => countNode(new PrivateIdentifierObject()), - createBaseTokenNode: kind => countNode(new TokenObject(kind)), - createBaseNode: kind => countNode(new NodeObject(kind)) - }; - - const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory); + const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode); let fileName: string; let sourceFlags: NodeFlags; @@ -1898,9 +1868,16 @@ namespace Parser { setTextRangePosWidth(sourceFile, 0, sourceText.length); setFields(sourceFile); + // include the file in the count + nodeCount++; + // If we parsed this as an external module, it may contain top-level await if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) { - sourceFile = reparseTopLevelAwait(sourceFile); + const updated = reparseTopLevelAwait(sourceFile); + if (sourceFile !== updated) { + nodeCount++; + sourceFile = updated; + } setFields(sourceFile); } @@ -2514,6 +2491,7 @@ namespace Parser { (node as Mutable).flags |= NodeFlags.ThisNodeHasError; } + nodeCount++; return node; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 473ca23d5d70f..ee37443eb3bf7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1,5 +1,4 @@ import { - BaseNodeFactory, CreateSourceFileOptions, EmitHelperFactory, GetCanonicalFileName, @@ -8135,7 +8134,6 @@ export interface GeneratedNamePart { export interface NodeFactory { /** @internal */ readonly parenthesizer: ParenthesizerRules; /** @internal */ readonly converters: NodeConverters; - /** @internal */ readonly baseFactory: BaseNodeFactory; /** @internal */ readonly flags: NodeFactoryFlags; createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray; diff --git a/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts b/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts index 76b96b955ecb1..d7fa5b078f7fe 100644 --- a/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts +++ b/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts @@ -37,10 +37,10 @@ import { NamedImportBindings, Node, NodeArray, + NodeConstructors, NoSubstitutionTemplateLiteral, NumericLiteral, ParameterDeclaration, - parseBaseNodeFactory, PostfixUnaryExpression, PrefixUnaryExpression, PrimaryExpression, @@ -1345,11 +1345,11 @@ export const createLogicalNot = deprecate(function createLogicalNot(operand: Exp /** @deprecated Use an appropriate `factory` method instead. */ export const createNode = deprecate(function createNode(kind: SyntaxKind, pos = 0, end = 0): Node { return setTextRangePosEnd( - kind === SyntaxKind.SourceFile ? parseBaseNodeFactory.createBaseSourceFileNode() : - kind === SyntaxKind.Identifier ? parseBaseNodeFactory.createBaseIdentifierNode() : - kind === SyntaxKind.PrivateIdentifier ? parseBaseNodeFactory.createBasePrivateIdentifierNode() : - !isNodeKind(kind) ? parseBaseNodeFactory.createBaseTokenNode(kind) : - parseBaseNodeFactory.createBaseNode(kind), + kind === SyntaxKind.SourceFile ? new NodeConstructors.SourceFileObject() : + kind === SyntaxKind.Identifier ? new NodeConstructors.IdentifierObject() : + kind === SyntaxKind.PrivateIdentifier ? new NodeConstructors.PrivateIdentifierObject() : + !isNodeKind(kind) ? new NodeConstructors.TokenObject(kind) : + new NodeConstructors.NodeObject(kind), pos, end ); diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 98a35af0fe3e0..10d7730be0cd0 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1329,9 +1329,7 @@ function isTrivia(s: string) { // are more aggressive than is strictly necessary. const textChangesTransformationContext: TransformationContext = { ...nullTransformationContext, - factory: createNodeFactory( - nullTransformationContext.factory.flags | NodeFactoryFlags.NoParenthesizerRules, - nullTransformationContext.factory.baseFactory), + factory: createNodeFactory(nullTransformationContext.factory.flags | NodeFactoryFlags.NoParenthesizerRules), }; /** @internal */