mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 12:57:11 -06:00
* Collect import helper needs during module info gathering * Add tests for other forms that trigger import helpers
This commit is contained in:
parent
efcb22ae09
commit
3305baf5eb
@ -4293,7 +4293,7 @@ namespace ts {
|
||||
return emitNode && emitNode.externalHelpersModuleName;
|
||||
}
|
||||
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean) {
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
|
||||
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(node);
|
||||
if (externalHelpersModuleName) {
|
||||
@ -4301,7 +4301,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
let create = hasExportStarsToExportValues
|
||||
let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault))
|
||||
&& moduleKind !== ModuleKind.System
|
||||
&& moduleKind !== ModuleKind.ES2015
|
||||
&& moduleKind !== ModuleKind.ESNext;
|
||||
|
||||
@ -690,36 +690,15 @@ namespace ts {
|
||||
return createCall(createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]);
|
||||
}
|
||||
|
||||
function getNamedImportCount(node: ImportDeclaration) {
|
||||
if (!(node.importClause && node.importClause.namedBindings)) return 0;
|
||||
const names = node.importClause.namedBindings;
|
||||
if (!names) return 0;
|
||||
if (!isNamedImports(names)) return 0;
|
||||
return names.elements.length;
|
||||
}
|
||||
|
||||
function containsDefaultReference(node: NamedImportBindings) {
|
||||
if (!node) return false;
|
||||
if (!isNamedImports(node)) return false;
|
||||
return some(node.elements, isNamedDefaultReference);
|
||||
}
|
||||
|
||||
function isNamedDefaultReference(e: ImportSpecifier) {
|
||||
return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default;
|
||||
}
|
||||
|
||||
function getHelperExpressionForImport(node: ImportDeclaration, innerExpr: Expression) {
|
||||
if (!compilerOptions.esModuleInterop || getEmitFlags(node) & EmitFlags.NeverApplyImportHelper) {
|
||||
return innerExpr;
|
||||
}
|
||||
const nameCount = getNamedImportCount(node);
|
||||
const hasDefault = nameCount > 0 ? containsDefaultReference(node.importClause.namedBindings) : undefined;
|
||||
|
||||
if (getNamespaceDeclarationNode(node) || (nameCount > 1 && hasDefault)) {
|
||||
if (getImportNeedsImportStarHelper(node)) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
return createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
if (isDefaultImport(node) || (nameCount === 1 && hasDefault)) {
|
||||
if (getImportNeedsImportDefaultHelper(node)) {
|
||||
context.requestEmitHelper(importDefaultHelper);
|
||||
return createCall(getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
|
||||
@ -15,6 +15,32 @@ namespace ts {
|
||||
hasExportStarsToExportValues: boolean; // whether this module contains export*
|
||||
}
|
||||
|
||||
function getNamedImportCount(node: ImportDeclaration) {
|
||||
if (!(node.importClause && node.importClause.namedBindings)) return 0;
|
||||
const names = node.importClause.namedBindings;
|
||||
if (!names) return 0;
|
||||
if (!isNamedImports(names)) return 0;
|
||||
return names.elements.length;
|
||||
}
|
||||
|
||||
function containsDefaultReference(node: NamedImportBindings) {
|
||||
if (!node) return false;
|
||||
if (!isNamedImports(node)) return false;
|
||||
return some(node.elements, isNamedDefaultReference);
|
||||
}
|
||||
|
||||
function isNamedDefaultReference(e: ImportSpecifier) {
|
||||
return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default;
|
||||
}
|
||||
|
||||
export function getImportNeedsImportStarHelper(node: ImportDeclaration) {
|
||||
return !!getNamespaceDeclarationNode(node) || (getNamedImportCount(node) > 1 && containsDefaultReference(node.importClause.namedBindings));
|
||||
}
|
||||
|
||||
export function getImportNeedsImportDefaultHelper(node: ImportDeclaration) {
|
||||
return isDefaultImport(node) || (getNamedImportCount(node) === 1 && containsDefaultReference(node.importClause.namedBindings));
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
|
||||
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
const exportSpecifiers = createMultiMap<ExportSpecifier>();
|
||||
@ -24,6 +50,7 @@ namespace ts {
|
||||
let hasExportDefault = false;
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
let hasImportStarOrImportDefault = false;
|
||||
|
||||
for (const node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
@ -33,6 +60,7 @@ namespace ts {
|
||||
// import * as x from "mod"
|
||||
// import { x, y } from "mod"
|
||||
externalImports.push(<ImportDeclaration>node);
|
||||
hasImportStarOrImportDefault = getImportNeedsImportStarHelper(<ImportDeclaration>node) || getImportNeedsImportDefaultHelper(<ImportDeclaration>node);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
@ -135,7 +163,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues);
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStarOrImportDefault);
|
||||
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
|
||||
64
tests/baselines/reference/esModuleInteropTslibHelpers.js
Normal file
64
tests/baselines/reference/esModuleInteropTslibHelpers.js
Normal file
@ -0,0 +1,64 @@
|
||||
//// [tests/cases/compiler/esModuleInteropTslibHelpers.ts] ////
|
||||
|
||||
//// [refs.d.ts]
|
||||
declare module "path";
|
||||
//// [file.ts]
|
||||
import path from "path";
|
||||
path.resolve("", "../");
|
||||
export class Foo { }
|
||||
//// [file2.ts]
|
||||
import * as path from "path";
|
||||
path.resolve("", "../");
|
||||
export class Foo2 { }
|
||||
//// [file3.ts]
|
||||
import {default as resolve} from "path";
|
||||
resolve("", "../");
|
||||
export class Foo3 { }
|
||||
//// [file4.ts]
|
||||
import {Bar, default as resolve} from "path";
|
||||
resolve("", "../");
|
||||
export { Bar }
|
||||
|
||||
//// [file.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var tslib_1 = require("tslib");
|
||||
var path_1 = tslib_1.__importDefault(require("path"));
|
||||
path_1["default"].resolve("", "../");
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
//// [file2.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var tslib_1 = require("tslib");
|
||||
var path = tslib_1.__importStar(require("path"));
|
||||
path.resolve("", "../");
|
||||
var Foo2 = /** @class */ (function () {
|
||||
function Foo2() {
|
||||
}
|
||||
return Foo2;
|
||||
}());
|
||||
exports.Foo2 = Foo2;
|
||||
//// [file3.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var tslib_1 = require("tslib");
|
||||
var path_1 = tslib_1.__importDefault(require("path"));
|
||||
path_1["default"]("", "../");
|
||||
var Foo3 = /** @class */ (function () {
|
||||
function Foo3() {
|
||||
}
|
||||
return Foo3;
|
||||
}());
|
||||
exports.Foo3 = Foo3;
|
||||
//// [file4.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var tslib_1 = require("tslib");
|
||||
var path_1 = tslib_1.__importStar(require("path"));
|
||||
exports.Bar = path_1.Bar;
|
||||
path_1["default"]("", "../");
|
||||
@ -0,0 +1,45 @@
|
||||
=== tests/cases/compiler/refs.d.ts ===
|
||||
declare module "path";
|
||||
No type information for this code.=== tests/cases/compiler/file.ts ===
|
||||
import path from "path";
|
||||
>path : Symbol(path, Decl(file.ts, 0, 6))
|
||||
|
||||
path.resolve("", "../");
|
||||
>path : Symbol(path, Decl(file.ts, 0, 6))
|
||||
|
||||
export class Foo { }
|
||||
>Foo : Symbol(Foo, Decl(file.ts, 1, 24))
|
||||
|
||||
=== tests/cases/compiler/file2.ts ===
|
||||
import * as path from "path";
|
||||
>path : Symbol(path, Decl(file2.ts, 0, 6))
|
||||
|
||||
path.resolve("", "../");
|
||||
>path : Symbol(path, Decl(file2.ts, 0, 6))
|
||||
|
||||
export class Foo2 { }
|
||||
>Foo2 : Symbol(Foo2, Decl(file2.ts, 1, 24))
|
||||
|
||||
=== tests/cases/compiler/file3.ts ===
|
||||
import {default as resolve} from "path";
|
||||
>default : Symbol(resolve, Decl(file3.ts, 0, 8))
|
||||
>resolve : Symbol(resolve, Decl(file3.ts, 0, 8))
|
||||
|
||||
resolve("", "../");
|
||||
>resolve : Symbol(resolve, Decl(file3.ts, 0, 8))
|
||||
|
||||
export class Foo3 { }
|
||||
>Foo3 : Symbol(Foo3, Decl(file3.ts, 1, 19))
|
||||
|
||||
=== tests/cases/compiler/file4.ts ===
|
||||
import {Bar, default as resolve} from "path";
|
||||
>Bar : Symbol(Bar, Decl(file4.ts, 0, 8))
|
||||
>default : Symbol(resolve, Decl(file4.ts, 0, 12))
|
||||
>resolve : Symbol(resolve, Decl(file4.ts, 0, 12))
|
||||
|
||||
resolve("", "../");
|
||||
>resolve : Symbol(resolve, Decl(file4.ts, 0, 12))
|
||||
|
||||
export { Bar }
|
||||
>Bar : Symbol(Bar, Decl(file4.ts, 2, 8))
|
||||
|
||||
61
tests/baselines/reference/esModuleInteropTslibHelpers.types
Normal file
61
tests/baselines/reference/esModuleInteropTslibHelpers.types
Normal file
@ -0,0 +1,61 @@
|
||||
=== tests/cases/compiler/refs.d.ts ===
|
||||
declare module "path";
|
||||
No type information for this code.=== tests/cases/compiler/file.ts ===
|
||||
import path from "path";
|
||||
>path : any
|
||||
|
||||
path.resolve("", "../");
|
||||
>path.resolve("", "../") : any
|
||||
>path.resolve : any
|
||||
>path : any
|
||||
>resolve : any
|
||||
>"" : ""
|
||||
>"../" : "../"
|
||||
|
||||
export class Foo { }
|
||||
>Foo : Foo
|
||||
|
||||
=== tests/cases/compiler/file2.ts ===
|
||||
import * as path from "path";
|
||||
>path : any
|
||||
|
||||
path.resolve("", "../");
|
||||
>path.resolve("", "../") : any
|
||||
>path.resolve : any
|
||||
>path : any
|
||||
>resolve : any
|
||||
>"" : ""
|
||||
>"../" : "../"
|
||||
|
||||
export class Foo2 { }
|
||||
>Foo2 : Foo2
|
||||
|
||||
=== tests/cases/compiler/file3.ts ===
|
||||
import {default as resolve} from "path";
|
||||
>default : any
|
||||
>resolve : any
|
||||
|
||||
resolve("", "../");
|
||||
>resolve("", "../") : any
|
||||
>resolve : any
|
||||
>"" : ""
|
||||
>"../" : "../"
|
||||
|
||||
export class Foo3 { }
|
||||
>Foo3 : Foo3
|
||||
|
||||
=== tests/cases/compiler/file4.ts ===
|
||||
import {Bar, default as resolve} from "path";
|
||||
>Bar : any
|
||||
>default : any
|
||||
>resolve : any
|
||||
|
||||
resolve("", "../");
|
||||
>resolve("", "../") : any
|
||||
>resolve : any
|
||||
>"" : ""
|
||||
>"../" : "../"
|
||||
|
||||
export { Bar }
|
||||
>Bar : any
|
||||
|
||||
21
tests/cases/compiler/esModuleInteropTslibHelpers.ts
Normal file
21
tests/cases/compiler/esModuleInteropTslibHelpers.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// @esModuleInterop: true
|
||||
// @importHelpers: true
|
||||
// @noEmitHelpers: true
|
||||
// @filename: refs.d.ts
|
||||
declare module "path";
|
||||
// @filename: file.ts
|
||||
import path from "path";
|
||||
path.resolve("", "../");
|
||||
export class Foo { }
|
||||
// @filename: file2.ts
|
||||
import * as path from "path";
|
||||
path.resolve("", "../");
|
||||
export class Foo2 { }
|
||||
// @filename: file3.ts
|
||||
import {default as resolve} from "path";
|
||||
resolve("", "../");
|
||||
export class Foo3 { }
|
||||
// @filename: file4.ts
|
||||
import {Bar, default as resolve} from "path";
|
||||
resolve("", "../");
|
||||
export { Bar }
|
||||
Loading…
x
Reference in New Issue
Block a user