diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4d785b218fcbb..7ce19bc264fb8 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2348,8 +2348,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const saveCurrentFlow = currentFlow; for (const typeAlias of delayedTypeAliases) { const host = typeAlias.parent.parent; - container = findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) as IsContainer | undefined || file; - blockScopeContainer = getEnclosingBlockScopeContainer(host) as IsBlockScopedContainer | undefined || file; + container = (findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) as IsContainer | undefined) || file; + blockScopeContainer = (getEnclosingBlockScopeContainer(host) as IsBlockScopedContainer | undefined) || file; currentFlow = initFlowNode({ flags: FlowFlags.Start }); parent = typeAlias; bind(typeAlias.typeExpression); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 42ea8fc08bc60..0b5c8895a945c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -57,8 +57,8 @@ import { canHaveJSDoc, canHaveLocals, canHaveModifiers, - canUsePropertyAccess, canHaveSymbol, + canUsePropertyAccess, cartesianProduct, CaseBlock, CaseClause, @@ -6597,7 +6597,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.truncating = true; } context.approximateLength += cachedResult.addedLength; - return deepCloneOrReuseNode(cachedResult) as TypeNode as T; + return deepCloneOrReuseNode(cachedResult.node) as T; } let depth: number | undefined; @@ -6613,11 +6613,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const result = transform(type); const addedLength = context.approximateLength - startLength; if (!context.reportedDiagnostic && !context.encounteredError) { - if (context.truncating) { - (result as any).truncating = true; - } - (result as any).addedLength = addedLength; - links?.serializedTypes?.set(key, result as TypeNode as TypeNode & {truncating?: boolean, addedLength: number}); + links?.serializedTypes?.set(key, { node: result, truncating: context.truncating, addedLength }); } context.visitedTypes.delete(typeId); if (id) { diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 216534e909ce2..3dce5667968b3 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -2319,9 +2319,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.TypeLiteral); node.members = createNodeArray(members); node.transformFlags = TransformFlags.ContainsTypeScript; - - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -2749,8 +2746,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.jsDocCache = undefined; // initialized by parser (JsDocContainer) - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -3585,8 +3580,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.jsDocCache = undefined; // initialized by parser (JsDocContainer) - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4373,8 +4366,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.jsDocCache = undefined; // initialized by parser (JsDocContainer) - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4415,8 +4406,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.jsDocCache = undefined; // initialized by parser (JsDocContainer) - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4510,8 +4499,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) node.jsDocCache = undefined; // initialized by parser (JsDocContainer) - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5142,8 +5129,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.JSDocTypeLiteral); node.jsDocPropertyTags = asNodeArray(propertyTags); node.isArrayType = isArrayType; - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5738,8 +5723,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildrenFlags(node.properties) | TransformFlags.ContainsJsx; - // node.locals = undefined; // initialized by binder (LocalsContainer) - // node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -6097,7 +6080,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function cloneSourceFileWorker(source: SourceFile) { - // TODO: explicit property assignments instead of for..in + // 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(SyntaxKind.SourceFile) as Mutable; node.flags |= source.flags & ~NodeFlags.Synthesized; for (const p in source) { diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 94107ec107caf..e2ec43aaa0d26 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1580,7 +1580,7 @@ namespace Parser { // Prime the scanner. nextToken(); const pos = getNodePos(); - let statements, endOfFileToken: EndOfFileToken; + let statements, endOfFileToken; if (token() === SyntaxKind.EndOfFileToken) { statements = createNodeArray([], pos, pos); endOfFileToken = parseTokenNode(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bc46be9b5a2b4..049ca49c341c5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5953,12 +5953,19 @@ export interface NodeLinks { isExhaustive?: boolean | 0; // Is node an exhaustive switch statement (0 indicates in-process resolution) skipDirectInference?: true; // Flag set by the API `getContextualType` call on a node when `Completions` is passed to force the checker to skip making inferences to a node's type declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter. - serializedTypes?: Map; // Collection of types serialized at this location + serializedTypes?: Map; // Collection of types serialized at this location contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution inferenceContext?: InferenceContext; // Inference context for contextual type } +/** @internal */ +export interface SerializedTypeEntry { + node: TypeNode; + truncating?: boolean; + addedLength: number; +} + export const enum TypeFlags { Any = 1 << 0, Unknown = 1 << 1,