From 9864b4e1ff6bb0a5b24e2bf631ab64a5acdd8d58 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 14 Mar 2017 14:41:49 -0700 Subject: [PATCH] Emit import callExpression for UMD and AMD --- src/compiler/transformers/module/module.ts | 66 ++++++++++++++++++- .../importCallExpressionInAMD1.ts | 11 ++++ .../importCallExpressionInUMD1.ts | 11 ++++ 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 tests/cases/conformance/es2018/dynamicImport/importCallExpressionInAMD1.ts create mode 100644 tests/cases/conformance/es2018/dynamicImport/importCallExpressionInUMD1.ts diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 22afc900f49..11fb94693cf 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -501,13 +501,73 @@ namespace ts { } } - function visitImportCallExpression(node: ImportCallExpression): Expression{ + function visitImportCallExpression(node: ImportCallExpression): Expression { + switch (compilerOptions.module) { + case ModuleKind.CommonJS: + return transformImportCallExpressionCommonJS(node); + case ModuleKind.AMD: + return transformImportCallExpressionAMD(node); + case ModuleKind.UMD: + return transformImportCallExpressionUMD(node); + } + Debug.assert(false, "All supported module kind in this transformation step should have been handled"); + } + + function transformImportCallExpressionUMD(node: ImportCallExpression): Expression { + // (function (factory) { + // ... (regular UMD) + // } + // })(function (require, exports, useSyncRequire) { + // "use strict"; + // Object.defineProperty(exports, "__esModule", { value: true }); + // require.length === 1 ? + // /*CommonJs Require*/ Promise.resolve().then(() => require('blah')); + // /*Amd Require*/ new Promise(resolve => require(['blah'], resolve)); + // }); + const require = createIdentifier("require"); + return createConditional( + /*condition*/ createBinary(createPropertyAccess(require, /*name*/ "length"), /*operator*/ createToken(SyntaxKind.EqualsEqualsEqualsToken), createNumericLiteral("1")), + /*whenTrue*/ transformImportCallExpressionCommonJS(node), + /*whenFalse*/ transformImportCallExpressionAMD(node) + ); + } + + function transformImportCallExpressionAMD(node: ImportCallExpression): Expression { + // improt("./blah") + // emit as + // define(["require", "exports", "blah"], function (require, exports) { + // ... + // new Promise(resolve => require(['blah'], resolve)); + // }); + const resolve = createIdentifier("resolve"); + return createNew( + createIdentifier("Promise"), + /*typeArguments*/ undefined, + [ + createArrowFunction( + /*modifiers*/undefined, + /*typeParameters*/ undefined, + [createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve)], + /*type*/ undefined, + createToken(SyntaxKind.EqualsGreaterThanToken), + createCall(createIdentifier("require"), /*typeArguments*/ undefined, [createArrayLiteral([node.specifier]), resolve]) + ) + ] + ); + } + + function transformImportCallExpressionCommonJS(node: ImportCallExpression): Expression { + // import("./blah") + // emit as + // Promise.resolve().then(() => require("./blah")); + // We have to wrap require in then callback so that require is done in asynchronously + // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately return createCall( createPropertyAccess( - createCall(/*expression*/ createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []), + createCall(/*expression*/ createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/[]), "then"), /*typeArguments*/ undefined, - [ createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), createCall(createIdentifier("require"), /*typeArguments*/ undefined, [node.specifier]))] + [createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), createCall(createIdentifier("require"), /*typeArguments*/ undefined, [node.specifier]))] ); } diff --git a/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInAMD1.ts b/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInAMD1.ts new file mode 100644 index 00000000000..28d3ca8a044 --- /dev/null +++ b/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInAMD1.ts @@ -0,0 +1,11 @@ +// @module: amd +// @target: esnext +// @filename: 0.ts +export function foo() { return "foo"; } + +// @filename: 1.ts +import("./0"); +var p1 = import("./0"); +p1.then(zero => { + return zero.foo(); +}); \ No newline at end of file diff --git a/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInUMD1.ts b/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInUMD1.ts new file mode 100644 index 00000000000..73793673c22 --- /dev/null +++ b/tests/cases/conformance/es2018/dynamicImport/importCallExpressionInUMD1.ts @@ -0,0 +1,11 @@ +// @module: umd +// @target: esnext +// @filename: 0.ts +export function foo() { return "foo"; } + +// @filename: 1.ts +import("./0"); +var p1 = import("./0"); +p1.then(zero => { + return zero.foo(); +}); \ No newline at end of file