Skip to content

Commit 8dc9006

Browse files
committed
Avoid emitting temp variable in downleveled import()
1 parent e99c935 commit 8dc9006

File tree

5 files changed

+41
-21
lines changed

5 files changed

+41
-21
lines changed

src/compiler/transformers/module/module.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -850,32 +850,57 @@ export function transformModule(context: TransformationContext): (x: SourceFile
850850
function createImportCallExpressionCommonJS(arg: Expression | undefined, isInlineable?: boolean): Expression {
851851
// import(x)
852852
// emit as
853-
// var _a;
854-
// (_a = x, Promise.resolve().then(() => require(_a)) /*CommonJs Require*/
853+
// Promise.resolve(`${x}`).then((s) => require(s)) /*CommonJs Require*/
855854
// We have to wrap require in then callback so that require is done in asynchronously
856855
// if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately
857-
// If the arg is not inlineable, we have to evaluate it in the current scope with a temp var
858-
const temp = arg && !isSimpleInlineableExpression(arg) && !isInlineable ? factory.createTempVariable(hoistVariableDeclaration) : undefined;
856+
// If the arg is not inlineable, we have to evaluate and ToString() it in the current scope
857+
// Otherwise, we inline it in require() so that it's statically analyzable
858+
const needSyncEval = arg && !isSimpleInlineableExpression(arg) && !isInlineable;
859+
859860
const promiseResolveCall = factory.createCallExpression(
860861
factory.createPropertyAccessExpression(factory.createIdentifier("Promise"), "resolve"),
861862
/*typeArguments*/ undefined,
862-
/*argumentsArray*/ [],
863+
/*argumentsArray*/ needSyncEval
864+
? languageVersion >= ScriptTarget.ES2015
865+
? [
866+
factory.createTemplateExpression(factory.createTemplateHead(""), [
867+
factory.createTemplateSpan(arg, factory.createTemplateTail("")),
868+
]),
869+
]
870+
: [
871+
factory.createCallExpression(
872+
factory.createPropertyAccessExpression(factory.createStringLiteral(""), "concat"),
873+
/*typeArguments*/ undefined,
874+
[arg]
875+
),
876+
]
877+
: []
863878
);
879+
864880
let requireCall: Expression = factory.createCallExpression(
865881
factory.createIdentifier("require"),
866882
/*typeArguments*/ undefined,
867-
temp ? [temp] : arg ? [arg] : [],
883+
needSyncEval ? [factory.createIdentifier("s")] : arg ? [arg] : [],
868884
);
869885
if (getESModuleInterop(compilerOptions)) {
870886
requireCall = emitHelpers().createImportStarHelper(requireCall);
871887
}
872888

889+
const parameters = needSyncEval
890+
? [
891+
factory.createParameterDeclaration(
892+
/*modifiers*/ undefined,
893+
/*dotDotDotToken*/ undefined,
894+
/*name*/ "s"),
895+
]
896+
: [];
897+
873898
let func: FunctionExpression | ArrowFunction;
874899
if (languageVersion >= ScriptTarget.ES2015) {
875900
func = factory.createArrowFunction(
876901
/*modifiers*/ undefined,
877902
/*typeParameters*/ undefined,
878-
/*parameters*/ [],
903+
/*parameters*/ parameters,
879904
/*type*/ undefined,
880905
/*equalsGreaterThanToken*/ undefined,
881906
requireCall);
@@ -886,14 +911,14 @@ export function transformModule(context: TransformationContext): (x: SourceFile
886911
/*asteriskToken*/ undefined,
887912
/*name*/ undefined,
888913
/*typeParameters*/ undefined,
889-
/*parameters*/ [],
914+
/*parameters*/ parameters,
890915
/*type*/ undefined,
891916
factory.createBlock([factory.createReturnStatement(requireCall)]));
892917
}
893918

894919
const downleveledImport = factory.createCallExpression(factory.createPropertyAccessExpression(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]);
895920

896-
return temp === undefined ? downleveledImport : factory.createCommaListExpression([factory.createAssignment(temp, arg!), downleveledImport]);
921+
return downleveledImport;
897922
}
898923

899924
function getHelperExpressionForExport(node: ExportDeclaration, innerExpr: Expression) {

tests/baselines/reference/asyncImportNestedYield.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,12 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
4646
function foo() {
4747
return __asyncGenerator(this, arguments, function foo_1() {
4848
return __generator(this, function (_a) {
49-
var _b, _c;
5049
switch (_a.label) {
5150
case 0: return [4 /*yield*/, __await("foo")];
5251
case 1: return [4 /*yield*/, _a.sent()];
53-
case 2: return [4 /*yield*/, __await.apply(void 0, [(_b = _a.sent(), Promise.resolve().then(function () { return require(_b); }))])];
52+
case 2: return [4 /*yield*/, __await.apply(void 0, [Promise.resolve("".concat(_a.sent())).then(function (s) { return require(s); })])];
5453
case 3:
55-
_c = (_a.sent())["default"], Promise.resolve().then(function () { return require(_c); });
54+
Promise.resolve("".concat((_a.sent())["default"])).then(function (s) { return require(s); });
5655
return [2 /*return*/];
5756
}
5857
});

tests/baselines/reference/dynamicImportEvaluateSpecifier.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@ const someFunction = async () => {
1616

1717

1818
//// [dynamicImportEvaluateSpecifier.js]
19-
var _a, _b;
2019
// https://github.com/microsoft/TypeScript/issues/48285
2120
let i = 0;
22-
_a = String(i++), Promise.resolve().then(() => require(_a));
23-
_b = String(i++), Promise.resolve().then(() => require(_b));
21+
Promise.resolve(`${String(i++)}`).then(s => require(s));
22+
Promise.resolve(`${String(i++)}`).then(s => require(s));
2423
const getPath = async () => {
2524
/* in reality this would do some async FS operation, or a web request */
2625
return "/root/my/cool/path";
2726
};
2827
const someFunction = async () => {
29-
var _a;
30-
const result = await (_a = await getPath(), Promise.resolve().then(() => require(_a)));
28+
const result = await Promise.resolve(`${await getPath()}`).then(s => require(s));
3129
};

tests/baselines/reference/dynamicImportTrailingComma.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ const path = './foo';
33
import(path,);
44

55
//// [dynamicImportTrailingComma.js]
6-
var _a;
76
var path = './foo';
8-
_a = path, Promise.resolve().then(function () { return require(_a); });
7+
Promise.resolve("".concat(path)).then(function (s) { return require(s); });

tests/baselines/reference/jsdocInTypeScript.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ var v = import(String());
5858

5959

6060
//// [jsdocInTypeScript.js]
61-
var _a;
6261
var T = /** @class */ (function () {
6362
function T() {
6463
}
@@ -93,4 +92,4 @@ var E = {};
9392
E[""];
9493
// make sure import types in JSDoc are not resolved
9594
/** @type {import("should-not-be-resolved").Type} */
96-
var v = (_a = String(), Promise.resolve().then(function () { return require(_a); }));
95+
var v = Promise.resolve("".concat(String())).then(function (s) { return require(s); });

0 commit comments

Comments
 (0)