From bc0d3e129700b6dda0fb504c5c55bf95f7a4f7d7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 27 Apr 2018 17:19:57 -0700 Subject: [PATCH] Look for top-level imports/exports before diving into the tree. --- src/compiler/parser.ts | 24 +++++++++++++++--------- src/compiler/types.ts | 6 +++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 12e498787c8..32e7ca19dd3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6139,14 +6139,11 @@ namespace ts { } function setExternalModuleIndicator(sourceFile: SourceFile) { - // Usually we'd like to avoid a full tree walk, but it's possible - // that we have a deeper external module indicator (e.g. `import.meta`, - // and possibly nested import statements in the future). - // Ideally the first few statements will be an import/export anyway. + // Try to use the first top-level import/export when available, then + // fall back to looking for an 'import.meta' somewhere in the tree if necessary. sourceFile.externalModuleIndicator = - !(sourceFile.flags & NodeFlags.PossiblyContainsImportMeta) ? - forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) : - walkTreeForExternalModuleIndicators(sourceFile); + forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || + getImportMetaIfNecessary(sourceFile); } function isAnExternalModuleIndicatorNode(node: Node) { @@ -6155,13 +6152,22 @@ namespace ts { || node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ExportAssignment || node.kind === SyntaxKind.ExportDeclaration - || isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta" ? node : undefined; } + function getImportMetaIfNecessary(sourceFile: SourceFile) { + return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ? + walkTreeForExternalModuleIndicators(sourceFile) : + undefined; + } + function walkTreeForExternalModuleIndicators(node: Node): Node { - return isAnExternalModuleIndicatorNode(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); + return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); + } + + function isImportMeta(node: Node): boolean { + return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; } const enum ParsingContext { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c678c4dab93..2622fe3f5e4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2564,7 +2564,11 @@ namespace ts { languageVersion: ScriptTarget; /* @internal */ scriptKind: ScriptKind; - // The first node that causes this file to be an external module + /** + * The first "most obvious" node that makes a file an external module. + * This is intended to be the first top-level import/export, + * but could be arbitrarily nested (e.g. `import.meta`). + */ /* @internal */ externalModuleIndicator: Node; // The first node that causes this file to be a CommonJS module /* @internal */ commonJsModuleIndicator: Node;