From 55430c46e629b40d0dd67e0c07a4e65a61f53443 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 4 Apr 2017 15:43:45 -0700 Subject: [PATCH] Add boolean flag to not walk the tree if there is no dynamic import --- src/compiler/parser.ts | 1 + src/compiler/program.ts | 10 ++++++---- src/compiler/types.ts | 7 +++++++ src/services/services.ts | 1 + 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c830be85a59..f0d456758a2 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3700,6 +3700,7 @@ namespace ts { // For example: // var foo3 = require("subfolder // import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression + sourceFile.possiblyContainDynamicImport = true; expression = parseTokenNode(); } else { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index e69098a21a1..57462cf1947 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1223,7 +1223,9 @@ namespace ts { for (const node of file.statements) { collectModuleReferences(node, /*inAmbientModule*/ false); - collectImportOrRequireCalls(node); + if (file.possiblyContainDynamicImport || isJavaScriptFile) { + collectDynamicImportOrRequireCalls(node); + } } file.imports = imports || emptyArray; @@ -1285,8 +1287,8 @@ namespace ts { } } - function collectImportOrRequireCalls(node: Node): void { - if (isJavaScriptFile && isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) { + function collectDynamicImportOrRequireCalls(node: Node): void { + if (isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) { (imports || (imports = [])).push((node).arguments[0]); } // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. @@ -1294,7 +1296,7 @@ namespace ts { (imports || (imports = [])).push((node).arguments[0]); } else { - forEachChild(node, collectImportOrRequireCalls); + forEachChild(node, collectDynamicImportOrRequireCalls); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e2006a868bc..2f94510519b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2309,6 +2309,13 @@ namespace ts { /* @internal */ patternAmbientModules?: PatternAmbientModule[]; /* @internal */ ambientModuleNames: string[]; /* @internal */ checkJsDirective: CheckJsDirective | undefined; + // This flag will be set to true when the parse encounter dynamic import so that post-parsing process of module resolution + // will not walk the tree if the flag is not set. However, this flag is just a approximation because once it is set, the flag never get reset. + // (hence it is named "possiblyContainDynamicImport"). + // During editing, if dynamic import is remove, incremental parsing will *NOT* update this flag. This will then causes walking of the tree during module resolution. + // However, the removal operation should not occur often and in the case of the removal, it is likely that users will add back the import anyway. + // The advantage of this approach is its simplicity. For the case of batch compilation, we garuntee that users won't have to pay the price of walking the tree if dynamic import isn't used. + /* @internal */ possiblyContainDynamicImport: boolean; } export interface Bundle extends Node { diff --git a/src/services/services.ts b/src/services/services.ts index 7086f4471a5..f5e3def6472 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -507,6 +507,7 @@ namespace ts { private namedDeclarations: Map; public ambientModuleNames: string[]; public checkJsDirective: CheckJsDirective | undefined; + public possiblyContainDynamicImport: boolean; constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end);