Try just the fetching change in checker.

This commit is contained in:
Daniel Rosenwasser 2021-11-09 01:09:57 +00:00 committed by GitHub
parent 083db3a677
commit d42b2b708d
15 changed files with 174 additions and 152 deletions

View file

@ -15,7 +15,7 @@ namespace ts {
referenced: boolean;
}
export function getModuleInstanceState(node: ModuleDeclaration, visited?: ESMap<Node, ModuleInstanceState | undefined>): ModuleInstanceState {
export function getModuleInstanceState(node: ModuleDeclaration, visited?: ESMap<number, ModuleInstanceState | undefined>): ModuleInstanceState {
if (node.body && !node.body.parent) {
// getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already
setParent(node.body, node);
@ -24,17 +24,18 @@ namespace ts {
return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated;
}
function getModuleInstanceStateCached(node: Node, visited = new Map<Node, ModuleInstanceState | undefined>()) {
if (visited.has(node)) {
return visited.get(node) || ModuleInstanceState.NonInstantiated;
function getModuleInstanceStateCached(node: Node, visited = new Map<number, ModuleInstanceState | undefined>()) {
const nodeId = getNodeId(node);
if (visited.has(nodeId)) {
return visited.get(nodeId) || ModuleInstanceState.NonInstantiated;
}
visited.set(node, undefined);
visited.set(nodeId, undefined);
const result = getModuleInstanceStateWorker(node, visited);
visited.set(node, result);
visited.set(nodeId, result);
return result;
}
function getModuleInstanceStateWorker(node: Node, visited: ESMap<Node, ModuleInstanceState | undefined>): ModuleInstanceState {
function getModuleInstanceStateWorker(node: Node, visited: ESMap<number, ModuleInstanceState | undefined>): ModuleInstanceState {
// A module is uninstantiated if it contains only
switch (node.kind) {
// 1. interface declarations, type alias declarations
@ -106,7 +107,7 @@ namespace ts {
return ModuleInstanceState.Instantiated;
}
function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: ESMap<Node, ModuleInstanceState | undefined>) {
function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: ESMap<number, ModuleInstanceState | undefined>) {
const name = specifier.propertyName || specifier.name;
let p: Node | undefined = specifier.parent;
while (p) {
@ -2983,7 +2984,7 @@ namespace ts {
function addLateBoundAssignmentDeclarationToSymbol(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol | undefined) {
if (symbol) {
(symbol.assignmentDeclarationMembers ||= new Set()).add(node);
(symbol.assignmentDeclarationMembers || (symbol.assignmentDeclarationMembers = new Map())).set(getNodeId(node), node);
}
}

View file

@ -3887,9 +3887,10 @@ namespace ts {
function getAlternativeContainingModules(symbol: Symbol, enclosingDeclaration: Node): Symbol[] {
const containingFile = getSourceFileOfNode(enclosingDeclaration);
const id = getNodeId(containingFile);
const links = getSymbolLinks(symbol);
let results: Symbol[] | undefined;
if (links.extendedContainersByFile && (results = links.extendedContainersByFile.get(containingFile))) {
if (links.extendedContainersByFile && (results = links.extendedContainersByFile.get(id))) {
return results;
}
if (containingFile && containingFile.imports) {
@ -3903,7 +3904,7 @@ namespace ts {
results = append(results, resolvedModule);
}
if (length(results)) {
(links.extendedContainersByFile ||= new Map()).set(containingFile, results!);
(links.extendedContainersByFile || (links.extendedContainersByFile = new Map())).set(id, results!);
return results!;
}
}
@ -33795,7 +33796,7 @@ namespace ts {
const type = checkExpression(node);
// If control flow analysis was required to determine the type, it is worth caching.
if (flowInvocationCount !== startInvocationCount) {
const cache = (flowTypeCache ||= []);
const cache = flowTypeCache || (flowTypeCache = []);
cache[getNodeId(node)] = type;
setNodeFlags(node, node.flags | NodeFlags.TypeCached);
}
@ -40317,8 +40318,9 @@ namespace ts {
const enclosingFile = getSourceFileOfNode(node);
const links = getNodeLinks(enclosingFile);
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
links.deferredNodes ||= new Set();
links.deferredNodes.add(node);
links.deferredNodes = links.deferredNodes || new Map();
const id = getNodeId(node);
links.deferredNodes.set(id, node);
}
}

View file

@ -869,7 +869,7 @@ namespace ts {
const bundledHelpers = new Map<string, boolean>();
let currentSourceFile: SourceFile | undefined;
let nodeToGeneratedName: ESMap<Node, string>; // Map of generated names for specific nodes.
let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes.
let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables.
let generatedNames: Set<string>; // Set of names generated by the NameGenerator.
let tempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes.
@ -1154,7 +1154,7 @@ namespace ts {
}
function reset() {
nodeToGeneratedName = new Map<Node, string>();
nodeIdToGeneratedName = [];
autoGeneratedIdToGeneratedName = [];
generatedNames = new Set();
tempFlagsStack = [];
@ -5008,11 +5008,8 @@ namespace ts {
}
function generateNameCached(node: Node, flags?: GeneratedIdentifierFlags) {
let result = nodeToGeneratedName.get(node);
if (result === undefined) {
nodeToGeneratedName.set(node, result = generateNameForNode(node, flags));
}
return result;
const nodeId = getNodeId(node);
return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, flags));
}
/**

View file

@ -5339,7 +5339,7 @@ namespace ts {
}
function flattenCommaElements(node: Expression): Expression | readonly Expression[] {
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode) {
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) {
if (isCommaListExpression(node)) {
return node.elements;
}

View file

@ -147,7 +147,7 @@ namespace ts {
let enabledSubstitutions: ClassPropertySubstitutionFlags;
let classAliases: ESMap<Node, Identifier>;
let classAliases: Identifier[];
/**
* Tracks what computed name expressions originating from elided names must be inlined
@ -162,7 +162,7 @@ namespace ts {
let pendingStatements: Statement[] | undefined;
const classLexicalEnvironmentStack: (ClassLexicalEnvironment | undefined)[] = [];
const classLexicalEnvironmentMap = new WeakMap<Node, ClassLexicalEnvironment>();
const classLexicalEnvironmentMap = new Map<number, ClassLexicalEnvironment>();
let currentClassLexicalEnvironment: ClassLexicalEnvironment | undefined;
let currentComputedPropertyNameClassLexicalEnvironment: ClassLexicalEnvironment | undefined;
let currentStaticPropertyDeclarationOrStaticBlock: PropertyDeclaration | ClassStaticBlockDeclaration | undefined;
@ -738,7 +738,7 @@ namespace ts {
function transformClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) {
if (shouldTransformPrivateElementsOrClassStaticBlocks) {
if (currentClassLexicalEnvironment) {
classLexicalEnvironmentMap.set(getOriginalNode(node), currentClassLexicalEnvironment);
classLexicalEnvironmentMap.set(getOriginalNodeId(node), currentClassLexicalEnvironment);
}
startLexicalEnvironment();
@ -1128,7 +1128,7 @@ namespace ts {
enableSubstitutionForClassAliases();
const alias = factory.cloneNode(temp) as GeneratedIdentifier;
alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes;
classAliases.set(getOriginalNode(node), alias);
classAliases[getOriginalNodeId(node)] = alias;
}
// To preserve the behavior of the old emitter, we explicitly indent
@ -1375,7 +1375,7 @@ namespace ts {
// capture the lexical environment for the member
setOriginalNode(transformed, property);
addEmitFlags(transformed, EmitFlags.AdviseOnEmitNode);
classLexicalEnvironmentMap.set(getOriginalNode(transformed), currentClassLexicalEnvironment);
classLexicalEnvironmentMap.set(getOriginalNodeId(transformed), currentClassLexicalEnvironment);
}
currentStaticPropertyDeclarationOrStaticBlock = savedCurrentStaticPropertyDeclarationOrStaticBlock;
return transformed;
@ -1453,7 +1453,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = new Map<Node, Identifier>();
classAliases = [];
}
}
@ -1516,16 +1516,18 @@ namespace ts {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
const original = getOriginalNode(node);
const classLexicalEnvironment = classLexicalEnvironmentMap.get(original);
if (classLexicalEnvironment) {
const savedClassLexicalEnvironment = currentClassLexicalEnvironment;
const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment;
currentClassLexicalEnvironment = classLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = classLexicalEnvironment;
previousOnEmitNode(hint, node, emitCallback);
currentClassLexicalEnvironment = savedClassLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = savedCurrentComputedPropertyNameClassLexicalEnvironment;
return;
if (original.id) {
const classLexicalEnvironment = classLexicalEnvironmentMap.get(original.id);
if (classLexicalEnvironment) {
const savedClassLexicalEnvironment = currentClassLexicalEnvironment;
const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment;
currentClassLexicalEnvironment = classLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = classLexicalEnvironment;
previousOnEmitNode(hint, node, emitCallback);
currentClassLexicalEnvironment = savedClassLexicalEnvironment;
currentComputedPropertyNameClassLexicalEnvironment = savedCurrentComputedPropertyNameClassLexicalEnvironment;
return;
}
}
switch (node.kind) {
@ -1631,7 +1633,7 @@ namespace ts {
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases.get(declaration);
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
if (classAlias) {
const clone = factory.cloneNode(classAlias);
setSourceMapRange(clone, node);

View file

@ -60,7 +60,7 @@ namespace ts {
let enclosingDeclaration: Node;
let necessaryTypeReferences: Set<string> | undefined;
let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined;
let lateStatementReplacementMap: ESMap<Node, VisitResult<LateVisibilityPaintedStatement | ExportAssignment>>;
let lateStatementReplacementMap: ESMap<NodeId, VisitResult<LateVisibilityPaintedStatement | ExportAssignment>>;
let suppressNewDiagnosticContexts: boolean;
let exportedModulesFromDeclarationEmit: Symbol[] | undefined;
@ -84,7 +84,7 @@ namespace ts {
let errorFallbackNode: Declaration | undefined;
let currentSourceFile: SourceFile;
let refs: ESMap<Node, SourceFile>;
let refs: ESMap<NodeId, SourceFile>;
let libs: ESMap<string, boolean>;
let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
const resolver = context.getEmitResolver();
@ -110,7 +110,7 @@ namespace ts {
}
// Otherwise we should emit a path-based reference
const container = getSourceFileOfNode(node);
refs.set(getOriginalNode(container), container);
refs.set(getOriginalNodeId(container), container);
}
function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) {
@ -426,12 +426,12 @@ namespace ts {
}
}
function collectReferences(sourceFile: SourceFile | UnparsedSource, ret: ESMap<Node, SourceFile>) {
function collectReferences(sourceFile: SourceFile | UnparsedSource, ret: ESMap<NodeId, SourceFile>) {
if (noResolve || (!isUnparsedSource(sourceFile) && isSourceFileJS(sourceFile))) return ret;
forEach(sourceFile.referencedFiles, f => {
const elem = host.getSourceFileFromReference(sourceFile, f);
if (elem) {
ret.set(getOriginalNode(elem), elem);
ret.set(getOriginalNodeId(elem), elem);
}
});
return ret;
@ -812,7 +812,7 @@ namespace ts {
needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit);
const result = transformTopLevelDeclaration(i);
needsDeclare = priorNeedsDeclare;
lateStatementReplacementMap.set(getOriginalNode(i), result);
lateStatementReplacementMap.set(getOriginalNodeId(i), result);
}
// And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list
@ -821,10 +821,10 @@ namespace ts {
function visitLateVisibilityMarkedStatements(statement: Statement) {
if (isLateVisibilityPaintedStatement(statement)) {
const originalNode = getOriginalNode(statement);
if (lateStatementReplacementMap.has(originalNode)) {
const result = lateStatementReplacementMap.get(originalNode);
lateStatementReplacementMap.delete(originalNode);
const key = getOriginalNodeId(statement);
if (lateStatementReplacementMap.has(key)) {
const result = lateStatementReplacementMap.get(key);
lateStatementReplacementMap.delete(key);
if (result) {
if (isArray(result) ? some(result, needsScopeMarker) : needsScopeMarker(result)) {
// Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier
@ -1146,7 +1146,7 @@ namespace ts {
const result = transformTopLevelDeclaration(input);
// Don't actually transform yet; just leave as original node - will be elided/swapped by late pass
lateStatementReplacementMap.set(getOriginalNode(input), result);
lateStatementReplacementMap.set(getOriginalNodeId(input), result);
return input;
}
@ -1348,9 +1348,9 @@ namespace ts {
needsDeclare = false;
visitNode(inner, visitDeclarationStatements);
// eagerly transform nested namespaces (the nesting doesn't need any elision or painting done)
const originalNode = getOriginalNode(inner!); // TODO: GH#18217
const body = lateStatementReplacementMap.get(originalNode);
lateStatementReplacementMap.delete(originalNode);
const id = getOriginalNodeId(inner!); // TODO: GH#18217
const body = lateStatementReplacementMap.get(id);
lateStatementReplacementMap.delete(id);
return cleanup(factory.updateModuleDeclaration(
input,
/*decorators*/ undefined,

View file

@ -46,7 +46,7 @@ namespace ts {
/** Whether the async function contains an element access on super (`super[x]`). */
let hasSuperElementAccess: boolean;
/** A set of node IDs for generated super accessors (variable statements). */
const substitutedSuperAccessors = new Set<Node>();
const substitutedSuperAccessors: boolean[] = [];
let contextFlags: ContextFlags = 0;
@ -503,7 +503,7 @@ namespace ts {
enableSubstitutionForAsyncMethodsWithSuper();
if (capturedSuperProperties.size) {
const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties);
substitutedSuperAccessors.add(variableStatement);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
}
}
@ -613,7 +613,7 @@ namespace ts {
}
}
// Disable substitution in the generated super accessor itself.
else if (enabledSubstitutions && substitutedSuperAccessors.has(node)) {
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = 0;
previousOnEmitNode(hint, node, emitCallback);

View file

@ -70,7 +70,7 @@ namespace ts {
/** Whether the async function contains an element access on super (`super[x]`). */
let hasSuperElementAccess: boolean;
/** A set of node IDs for generated super accessors. */
const substitutedSuperAccessors = new Set<Node>();
const substitutedSuperAccessors: boolean[] = [];
return chainBundle(context, transformSourceFile);
@ -972,7 +972,7 @@ namespace ts {
if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties);
substitutedSuperAccessors.add(variableStatement);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
}
@ -1087,7 +1087,7 @@ namespace ts {
}
}
// Disable substitution in the generated super accessor itself.
else if (enabledSubstitutions && substitutedSuperAccessors.has(node)) {
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = 0 as NodeCheckFlags;
previousOnEmitNode(hint, node, emitCallback);

View file

@ -11,14 +11,14 @@ namespace ts {
// enable emit notification only if using --jsx preserve or react-native
let previousOnEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
let noSubstitution: Set<Node>;
let noSubstitution: boolean[];
if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
previousOnEmitNode = context.onEmitNode;
context.onEmitNode = onEmitNode;
context.enableEmitNotification(SyntaxKind.JsxOpeningElement);
context.enableEmitNotification(SyntaxKind.JsxClosingElement);
context.enableEmitNotification(SyntaxKind.JsxSelfClosingElement);
noSubstitution = new Set<Node>();
noSubstitution = [];
}
const previousOnSubstituteNode = context.onSubstituteNode;
@ -49,7 +49,7 @@ namespace ts {
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
const tagName = (node as JsxOpeningElement | JsxClosingElement | JsxSelfClosingElement).tagName;
noSubstitution.add(getOriginalNode(tagName));
noSubstitution[getOriginalNodeId(tagName)] = true;
break;
}
@ -63,8 +63,7 @@ namespace ts {
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
// TODO: do we need to check for a Node ID here?
if (noSubstitution?.has(node)) {
if (node.id && noSubstitution && noSubstitution[node.id]) {
return previousOnSubstituteNode(hint, node);
}

View file

@ -245,7 +245,7 @@ namespace ts {
context.onSubstituteNode = onSubstituteNode;
let renamedCatchVariables: ESMap<string, boolean>;
let renamedCatchVariableDeclarations: ESMap<Node, Identifier>;
let renamedCatchVariableDeclarations: Identifier[];
let inGeneratorFunctionBody: boolean;
let inStatementContainingYield: boolean;
@ -1969,7 +1969,7 @@ namespace ts {
if (isIdentifier(original) && original.parent) {
const declaration = resolver.getReferencedValueDeclaration(original);
if (declaration) {
const name = renamedCatchVariableDeclarations.get(getOriginalNode(declaration));
const name = renamedCatchVariableDeclarations[getOriginalNodeId(declaration)];
if (name) {
// TODO(rbuckton): Does this need to be parented?
const clone = setParent(setTextRange(factory.cloneNode(name), name), name.parent);
@ -2137,12 +2137,12 @@ namespace ts {
name = declareLocal(text);
if (!renamedCatchVariables) {
renamedCatchVariables = new Map<string, boolean>();
renamedCatchVariableDeclarations = new Map<Node, Identifier>();
renamedCatchVariableDeclarations = [];
context.enableSubstitution(SyntaxKind.Identifier);
}
renamedCatchVariables.set(text, true);
renamedCatchVariableDeclarations.set(getOriginalNode(variable), name);
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
}
const exception = peekBlock() as ExceptionBlock;

View file

@ -40,12 +40,12 @@ namespace ts {
context.enableSubstitution(SyntaxKind.ShorthandPropertyAssignment); // Substitutes shorthand property assignments for imported/exported symbols.
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap = new Map<Node, ExternalModuleInfo>(); // The ExternalModuleInfo for each file.
const deferredExports = new Map<Node, Statement[] | undefined>();; // Exports to defer until an EndOfDeclarationMarker is found.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
let currentSourceFile: SourceFile; // The current file.
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
const noSubstitution = new Set<Node>(); // Set of nodes for which substitution rules should be ignored.
const noSubstitution: boolean[] = []; // Set of nodes for which substitution rules should be ignored.
let needUMDDynamicImportHelper: boolean;
return chainBundle(context, transformSourceFile);
@ -65,7 +65,7 @@ namespace ts {
currentSourceFile = node;
currentModuleInfo = collectExternalModuleInfo(context, node, resolver, compilerOptions);
moduleInfoMap.set(getOriginalNode(node), currentModuleInfo);
moduleInfoMap[getOriginalNodeId(node)] = currentModuleInfo;
// Perform the transformation.
const transformModule = getTransformModuleDelegate(moduleKind);
@ -692,13 +692,13 @@ namespace ts {
}
for (const exportName of exportedNames) {
noSubstitution.add(expression);
noSubstitution[getNodeId(expression)] = true;
expression = createExportExpression(exportName, expression);
setTextRange(expression, node);
}
if (temp) {
noSubstitution.add(expression);
noSubstitution[getNodeId(expression)] = true;
expression = factory.createComma(expression, temp);
setTextRange(expression, node);
}
@ -981,8 +981,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfImportDeclaration(statements, node);
@ -1072,8 +1072,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportEqualsDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfImportEqualsDeclaration(statements, node);
@ -1206,8 +1206,8 @@ namespace ts {
const original = node.original;
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportStatement(deferredExports.get(originalNode), factory.createIdentifier("default"), visitNode(node.expression, visitor), /*location*/ node, /*allowComments*/ true));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), visitNode(node.expression, visitor), /*location*/ node, /*allowComments*/ true);
}
else {
statements = appendExportStatement(statements, factory.createIdentifier("default"), visitNode(node.expression, visitor), /*location*/ node, /*allowComments*/ true);
@ -1249,8 +1249,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfHoistedDeclaration(statements, node);
@ -1290,8 +1290,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfHoistedDeclaration(statements, node);
@ -1370,8 +1370,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node);
}
else {
statements = appendExportsOfVariableStatement(statements, node);
@ -1441,8 +1441,8 @@ namespace ts {
// To balance the declaration, add the exports of the elided variable
// statement.
if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) {
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node.original as VariableStatement));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original as VariableStatement);
}
return node;
@ -1467,10 +1467,10 @@ namespace ts {
// For some transformations we emit an `EndOfDeclarationMarker` to mark the actual
// end of the transformed declaration. We use this marker to emit any deferred exports
// of the declaration.
const originalNode = getOriginalNode(node);
const statements = deferredExports.get(originalNode);
const id = getOriginalNodeId(node);
const statements = deferredExports[id];
if (statements) {
deferredExports.delete(node);
delete deferredExports[id];
return append(statements, node);
}
@ -1770,7 +1770,7 @@ namespace ts {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
currentSourceFile = node as SourceFile;
currentModuleInfo = moduleInfoMap.get(getOriginalNode(currentSourceFile))!;
currentModuleInfo = moduleInfoMap[getOriginalNodeId(currentSourceFile)];
previousOnEmitNode(hint, node, emitCallback);
@ -1794,7 +1794,7 @@ namespace ts {
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (noSubstitution.has(node)) {
if (node.id && noSubstitution[node.id]) {
return node;
}
@ -1852,7 +1852,7 @@ namespace ts {
function substituteCallExpression(node: CallExpression) {
if (isIdentifier(node.expression)) {
const expression = substituteExpressionIdentifier(node.expression);
noSubstitution.add(expression);
noSubstitution[getNodeId(expression)] = true;
if (!isIdentifier(expression)) {
return addEmitFlags(
factory.updateCallExpression(node,
@ -1871,7 +1871,7 @@ namespace ts {
function substituteTaggedTemplateExpression(node: TaggedTemplateExpression) {
if (isIdentifier(node.tag)) {
const tag = substituteExpressionIdentifier(node.tag);
noSubstitution.add(tag);
noSubstitution[getNodeId(tag)] = true;
if (!isIdentifier(tag)) {
return addEmitFlags(
factory.updateTaggedTemplateExpression(node,
@ -1962,7 +1962,7 @@ namespace ts {
let expression: Expression = node;
for (const exportName of exportedNames) {
// Mark the node to prevent triggering this rule again.
noSubstitution.add(expression);
noSubstitution[getNodeId(expression)] = true;
expression = createExportExpression(exportName, expression, /*location*/ node);
}
@ -1984,7 +1984,7 @@ namespace ts {
|| resolver.getReferencedValueDeclaration(name);
if (valueDeclaration) {
return currentModuleInfo
&& currentModuleInfo.exportedBindings.get(getOriginalNode(valueDeclaration));
&& currentModuleInfo.exportedBindings[getOriginalNodeId(valueDeclaration)];
}
}
}

View file

@ -26,11 +26,11 @@ namespace ts {
context.enableSubstitution(SyntaxKind.MetaProperty); // Substitutes 'import.meta'
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap = new Map<Node, ExternalModuleInfo>(); // The ExternalModuleInfo for each file.
const deferredExports = new Map<Node, (Statement[] | undefined)>(); // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap = new Map<Node, Identifier>(); // The export function associated with a source file.
const noSubstitutionMap = new Map<Node, Set<Node>>(); // Set of nodes for which substitution rules should be ignored for each file.
const contextObjectMap = new Map<Node, Identifier>(); // The context object associated with a source file.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file.
const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file.
const contextObjectMap: Identifier[] = []; // The context object associated with a source file.
let currentSourceFile: SourceFile; // The current file.
let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file.
@ -38,7 +38,7 @@ namespace ts {
let contextObject: Identifier; // The context object for the current file.
let hoistedStatements: Statement[] | undefined;
let enclosingBlockScopedContainer: Node;
let noSubstitution: Set<Node> | undefined; // Set of nodes for which substitution rules should be ignored.
let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored.
return chainBundle(context, transformSourceFile);
@ -52,7 +52,7 @@ namespace ts {
return node;
}
const originalNode = getOriginalNode(node);
const id = getOriginalNodeId(node);
currentSourceFile = node;
enclosingBlockScopedContainer = node;
@ -70,13 +70,13 @@ namespace ts {
// see comment to 'substitutePostfixUnaryExpression' for more details
// Collect information about the external module and dependency groups.
moduleInfoMap.set(originalNode, moduleInfo = collectExternalModuleInfo(context, node, resolver, compilerOptions));
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(context, node, resolver, compilerOptions);
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
exportFunction = factory.createUniqueName("exports");
exportFunctionsMap.set(originalNode, exportFunction);
contextObjectMap.set(originalNode, contextObject = factory.createUniqueName("context"));
exportFunctionsMap[id] = exportFunction;
contextObject = contextObjectMap[id] = factory.createUniqueName("context");
// Add the body of the module.
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
@ -123,7 +123,7 @@ namespace ts {
}
if (noSubstitution) {
noSubstitutionMap.set(originalNode, noSubstitution);
noSubstitutionMap[id] = noSubstitution;
noSubstitution = undefined;
}
@ -596,8 +596,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfImportDeclaration(statements, node);
@ -624,8 +624,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfImportEqualsDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfImportEqualsDeclaration(statements, node);
@ -649,8 +649,8 @@ namespace ts {
const original = node.original;
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportStatement(deferredExports.get(originalNode), factory.createIdentifier("default"), expression, /*allowComments*/ true));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), expression, /*allowComments*/ true);
}
else {
return createExportStatement(factory.createIdentifier("default"), expression, /*allowComments*/ true);
@ -682,8 +682,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
}
else {
hoistedStatements = appendExportsOfHoistedDeclaration(hoistedStatements, node);
@ -729,8 +729,8 @@ namespace ts {
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfHoistedDeclaration(deferredExports.get(originalNode), node));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node);
}
else {
statements = appendExportsOfHoistedDeclaration(statements, node);
@ -769,8 +769,8 @@ namespace ts {
if (isMarkedDeclaration) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const originalNode = getOriginalNode(node);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node, isExportedDeclaration));
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node, isExportedDeclaration);
}
else {
statements = appendExportsOfVariableStatement(statements, node, /*exportSelf*/ false);
@ -881,9 +881,9 @@ namespace ts {
// To balance the declaration, we defer the exports of the elided variable
// statement until we visit this declaration's `EndOfDeclarationMarker`.
if (hasAssociatedEndOfDeclarationMarker(node) && node.original!.kind === SyntaxKind.VariableStatement) {
const originalNode = getOriginalNode(node);
const id = getOriginalNodeId(node);
const isExportedDeclaration = hasSyntacticModifier(node.original!, ModifierFlags.Export);
deferredExports.set(originalNode, appendExportsOfVariableStatement(deferredExports.get(originalNode), node.original as VariableStatement, isExportedDeclaration));
deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original as VariableStatement, isExportedDeclaration);
}
return node;
@ -908,15 +908,16 @@ namespace ts {
// For some transformations we emit an `EndOfDeclarationMarker` to mark the actual
// end of the transformed declaration. We use this marker to emit any deferred exports
// of the declaration.
const originalNode = getOriginalNode(node);
const statements = deferredExports.get(originalNode);
const id = getOriginalNodeId(node);
const statements = deferredExports[id];
if (statements) {
deferredExports.delete(originalNode);
delete deferredExports[id];
return append(statements, node);
}
else {
if (isModuleOrEnumDeclaration(originalNode)) {
return append(appendExportsOfDeclaration(statements, originalNode), node);
const original = getOriginalNode(node);
if (isModuleOrEnumDeclaration(original)) {
return append(appendExportsOfDeclaration(statements, original), node);
}
}
@ -1677,14 +1678,16 @@ namespace ts {
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
const originalNode = getOriginalNode(node);
const id = getOriginalNodeId(node);
currentSourceFile = node as SourceFile;
moduleInfo = moduleInfoMap.get(originalNode)!;
exportFunction = exportFunctionsMap.get(originalNode)!;
noSubstitution = noSubstitutionMap.get(originalNode)!;
contextObject = contextObjectMap.get(originalNode)!;
moduleInfo = moduleInfoMap[id];
exportFunction = exportFunctionsMap[id];
noSubstitution = noSubstitutionMap[id];
contextObject = contextObjectMap[id];
noSubstitutionMap.delete(originalNode);
if (noSubstitution) {
delete noSubstitutionMap[id];
}
previousOnEmitNode(hint, node, emitCallback);
@ -1901,7 +1904,7 @@ namespace ts {
exportedNames = append(exportedNames, factory.getDeclarationName(valueDeclaration));
}
exportedNames = addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings.get(getOriginalNode(valueDeclaration)));
exportedNames = addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings[getOriginalNodeId(valueDeclaration)]);
}
}
@ -1914,7 +1917,8 @@ namespace ts {
* @param node The node which should not be substituted.
*/
function preventSubstitution<T extends Node>(node: T): T {
(noSubstitution ||= new Set<Node>()).add(node);
if (noSubstitution === undefined) noSubstitution = [];
noSubstitution[getNodeId(node)] = true;
return node;
}
@ -1924,7 +1928,7 @@ namespace ts {
* @param node The node to test.
*/
function isSubstitutionPrevented(node: Node) {
return noSubstitution?.has(node);
return noSubstitution && node.id && noSubstitution[node.id];
}
}
}

View file

@ -78,7 +78,7 @@ namespace ts {
* A map that keeps track of aliases created for classes with decorators to avoid issues
* with the double-binding behavior of classes.
*/
let classAliases: ESMap<Node, Identifier>;
let classAliases: Identifier[];
/**
* Keeps track of whether we are within any containing namespaces when performing
@ -1237,7 +1237,7 @@ namespace ts {
return undefined;
}
const classAlias = classAliases?.get(getOriginalNode(node));
const classAlias = classAliases && classAliases[getOriginalNodeId(node)];
// When we transform to ES5/3 this will be moved inside an IIFE and should reference the name
// without any block-scoped variable collision handling
@ -3139,7 +3139,7 @@ namespace ts {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
enableSubstitutionForClassAliases();
const classAlias = factory.createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? idText(node.name) : "default");
classAliases.set(getOriginalNode(node), classAlias);
classAliases[getOriginalNodeId(node)] = classAlias;
hoistVariableDeclaration(classAlias);
return classAlias;
}
@ -3171,7 +3171,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = new Map<Node, Identifier>();
classAliases = [];
}
}
@ -3290,7 +3290,7 @@ namespace ts {
// constructor references in static property initializers.
const declaration = resolver.getReferencedValueDeclaration(node);
if (declaration) {
const classAlias = classAliases.get(declaration);
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
if (classAlias) {
const clone = factory.cloneNode(classAlias);
setSourceMapRange(clone, node);

View file

@ -1,10 +1,15 @@
/* @internal */
namespace ts {
export function getOriginalNodeId(node: Node) {
node = getOriginalNode(node);
return node ? getNodeId(node) : 0;
}
export interface ExternalModuleInfo {
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
exportSpecifiers: ESMap<string, ExportSpecifier[]>; // file-local export specifiers by name (no reexports)
exportedBindings: MultiMap<Node, Identifier>; // exported names of local declarations
exportedBindings: Identifier[][]; // exported names of local declarations
exportedNames: Identifier[] | undefined; // all exported names in the module, both local and reexported
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
hasExportStarsToExportValues: boolean; // whether this module contains export*
@ -63,7 +68,7 @@ namespace ts {
export function collectExternalModuleInfo(context: TransformationContext, sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers = createMultiMap<ExportSpecifier>();
const exportedBindings = createMultiMap<Node, Identifier>();
const exportedBindings: Identifier[][] = [];
const uniqueExports = new Map<string, boolean>();
let exportedNames: Identifier[] | undefined;
let hasExportDefault = false;
@ -113,7 +118,7 @@ namespace ts {
else {
const name = ((node as ExportDeclaration).exportClause as NamespaceExport).name;
if (!uniqueExports.get(idText(name))) {
exportedBindings.add(getOriginalNode(node), name);
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(idText(name), true);
exportedNames = append(exportedNames, name);
}
@ -148,7 +153,7 @@ namespace ts {
if (hasSyntacticModifier(node, ModifierFlags.Default)) {
// export default function() { }
if (!hasExportDefault) {
exportedBindings.add(getOriginalNode(node), context.factory.getDeclarationName(node as FunctionDeclaration));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as FunctionDeclaration));
hasExportDefault = true;
}
}
@ -156,7 +161,7 @@ namespace ts {
// export function x() { }
const name = (node as FunctionDeclaration).name!;
if (!uniqueExports.get(idText(name))) {
exportedBindings.add(getOriginalNode(node), name);
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(idText(name), true);
exportedNames = append(exportedNames, name);
}
@ -169,7 +174,7 @@ namespace ts {
if (hasSyntacticModifier(node, ModifierFlags.Default)) {
// export default class { }
if (!hasExportDefault) {
exportedBindings.add(getOriginalNode(node), context.factory.getDeclarationName(node as ClassDeclaration));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as ClassDeclaration));
hasExportDefault = true;
}
}
@ -177,7 +182,7 @@ namespace ts {
// export class x { }
const name = (node as ClassDeclaration).name;
if (name && !uniqueExports.get(idText(name))) {
exportedBindings.add(getOriginalNode(node), name);
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(idText(name), true);
exportedNames = append(exportedNames, name);
}
@ -206,7 +211,7 @@ namespace ts {
|| resolver.getReferencedValueDeclaration(name);
if (decl) {
exportedBindings.add(getOriginalNode(decl), specifier.name);
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
}
uniqueExports.set(idText(specifier.name), true);
@ -234,6 +239,18 @@ namespace ts {
return exportedNames;
}
/** Use a sparse array as a multi-map. */
function multiMapSparseArrayAdd<V>(map: V[][], key: number, value: V): V[] {
let values = map[key];
if (values) {
values.push(value);
}
else {
map[key] = values = [value];
}
return values;
}
/**
* Used in the module transformer to check if an expression is reasonably without sideeffect,
* and thus better to copy into multiple places rather than to cache in a temporary variable

View file

@ -4908,7 +4908,7 @@ namespace ts {
/* @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter.
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
/* @internal */ assignmentDeclarationMembers?: Set<Declaration>; // detected late-bound assignment declarations associated with the symbol
/* @internal */ assignmentDeclarationMembers?: ESMap<number, Declaration>; // detected late-bound assignment declarations associated with the symbol
}
/* @internal */
@ -4946,7 +4946,7 @@ namespace ts {
lateSymbol?: Symbol; // Late-bound symbol for a computed property
specifierCache?: ESMap<string, string>; // For symbols corresponding to external modules, a cache of incoming path -> module specifier name mappings
extendedContainers?: Symbol[]; // Containers (other than the parent) which this symbol is aliased in
extendedContainersByFile?: ESMap<Node, Symbol[]>; // Containers (other than the parent) which this symbol is aliased in
extendedContainersByFile?: ESMap<NodeId, Symbol[]>; // Containers (other than the parent) which this symbol is aliased in
variances?: VarianceFlags[]; // Alias symbol type argument variance cache
deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type
deferralParent?: Type; // Source union/intersection of a deferred type
@ -5106,7 +5106,7 @@ namespace ts {
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
jsxImplicitImportContainer?: Symbol | false; // Resolved module symbol the implicit jsx import of this file should refer to
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
deferredNodes?: Set<Node>; // Set of nodes whose checking has been deferred
deferredNodes?: ESMap<NodeId, Node>; // Set of nodes whose checking has been deferred
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
isExhaustive?: boolean; // Is node an exhaustive switch statement