Skip to content

Support for an external exportStar helper #13272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21864,6 +21864,10 @@ namespace ts {
if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) {
error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
}

if (modulekind !== ModuleKind.System && modulekind !== ModuleKind.ES2015) {
checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
}
}
}
}
Expand Down Expand Up @@ -23538,7 +23542,8 @@ namespace ts {
case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator";
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
case ExternalEmitHelpers.AsyncValues: return "__asyncValues";
default: Debug.fail("Unrecognized helper.");
case ExternalEmitHelpers.ExportStar: return "__exportStar";
default: Debug.fail("Unrecognized helper");
}
}

Expand Down
51 changes: 31 additions & 20 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3850,23 +3850,34 @@ namespace ts {
return emitNode && emitNode.externalHelpersModuleName;
}

export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions) {
if (compilerOptions.importHelpers && (isExternalModule(node) || compilerOptions.isolatedModules)) {
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean) {
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
const externalHelpersModuleName = getExternalHelpersModuleName(node);
if (externalHelpersModuleName) {
return externalHelpersModuleName;
}

const helpers = getEmitHelpers(node);
if (helpers) {
for (const helper of helpers) {
if (!helper.scoped) {
const parseNode = getOriginalNode(node, isSourceFile);
const emitNode = getOrCreateEmitNode(parseNode);
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText));
const moduleKind = getEmitModuleKind(compilerOptions);
let create = hasExportStarsToExportValues
&& moduleKind !== ModuleKind.System
&& moduleKind !== ModuleKind.ES2015;
if (!create) {
const helpers = getEmitHelpers(node);
if (helpers) {
for (const helper of helpers) {
if (!helper.scoped) {
create = true;
break;
}
}
}
}

if (create) {
const parseNode = getOriginalNode(node, isSourceFile);
const emitNode = getOrCreateEmitNode(parseNode);
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText));
}
}
}

Expand Down Expand Up @@ -4249,17 +4260,6 @@ namespace ts {
let exportEquals: ExportAssignment = undefined;
let hasExportStarsToExportValues = false;

const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions);
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
createLiteral(externalHelpersModuleNameText));

if (externalHelpersImportDeclaration) {
externalImports.push(externalHelpersImportDeclaration);
}

for (const node of sourceFile.statements) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
Expand Down Expand Up @@ -4370,6 +4370,17 @@ namespace ts {
}
}

const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues);
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
createLiteral(externalHelpersModuleNameText));

if (externalHelpersImportDeclaration) {
externalImports.unshift(externalHelpersImportDeclaration);
}

return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
}

Expand Down
24 changes: 12 additions & 12 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace ts {
addRange(statements, endLexicalEnvironment());

const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
if (currentModuleInfo.hasExportStarsToExportValues) {
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
addEmitHelper(updated, exportStarHelper);
Expand Down Expand Up @@ -408,7 +408,7 @@ namespace ts {
addRange(statements, endLexicalEnvironment());

const body = createBlock(statements, /*multiLine*/ true);
if (currentModuleInfo.hasExportStarsToExportValues) {
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
addEmitHelper(body, exportStarHelper);
Expand Down Expand Up @@ -833,15 +833,7 @@ namespace ts {
// export * from "mod";
return setTextRange(
createStatement(
createCall(
createIdentifier("__export"),
/*typeArguments*/ undefined,
[
moduleKind !== ModuleKind.AMD
? createRequireCall(node)
: generatedName
]
)
createExportStarHelper(context, moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName)
),
node
);
Expand Down Expand Up @@ -1598,9 +1590,17 @@ namespace ts {
text: `
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}`
}
`
};

function createExportStarHelper(context: TransformationContext, module: Expression) {
const compilerOptions = context.getCompilerOptions();
return compilerOptions.importHelpers
? createCall(getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")])
: createCall(createIdentifier("__export"), /*typeArguments*/ undefined, [module]);
}

// emit helper for dynamic import
const dynamicImportUMDHelper: EmitHelper = {
name: "typescript:dynamicimport-sync-require",
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4097,6 +4097,7 @@ namespace ts {
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation)

// Helpers included by ES2015 for..of
ForOfIncludes = Values,
Expand All @@ -4114,7 +4115,7 @@ namespace ts {
SpreadIncludes = Read | Spread,

FirstEmitHelper = Extends,
LastEmitHelper = AsyncValues
LastEmitHelper = ExportStar
}

export const enum EmitHint {
Expand Down
8 changes: 6 additions & 2 deletions tests/baselines/reference/importHelpersAmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ export class A { }

//// [b.ts]
import { A } from "./a";
export * from "./a";
export class B extends A { }

//// [tslib.d.ts]
export declare function __extends(d: Function, b: Function): void;
export declare function __assign(t: any, ...sources: any[]): any;
export declare function __rest(t: any, propertyNames: string[]): any;
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
export declare function __param(paramIndex: number, decorator: Function): Function;
export declare function __metadata(metadataKey: any, metadataValue: any): Function;
export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;

export declare function __generator(thisArg: any, body: Function): any;
export declare function __exportStar(m: any, exports: any): void;

//// [a.js]
define(["require", "exports"], function (require, exports) {
Expand All @@ -28,9 +31,10 @@ define(["require", "exports"], function (require, exports) {
exports.A = A;
});
//// [b.js]
define(["require", "exports", "tslib", "./a"], function (require, exports, tslib_1, a_1) {
define(["require", "exports", "tslib", "./a", "./a"], function (require, exports, tslib_1, a_1, a_2) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
tslib_1.__exportStar(a_2, exports);
var B = (function (_super) {
tslib_1.__extends(B, _super);
function B() {
Expand Down
19 changes: 18 additions & 1 deletion tests/baselines/reference/importHelpersAmd.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ export class A { }
import { A } from "./a";
>A : Symbol(A, Decl(b.ts, 0, 8))

export * from "./a";
export class B extends A { }
>B : Symbol(B, Decl(b.ts, 0, 24))
>B : Symbol(B, Decl(b.ts, 1, 20))
>A : Symbol(A, Decl(b.ts, 0, 8))

=== tests/cases/compiler/tslib.d.ts ===
Expand All @@ -23,6 +24,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
>t : Symbol(t, Decl(tslib.d.ts, --, --))
>sources : Symbol(sources, Decl(tslib.d.ts, --, --))

export declare function __rest(t: any, propertyNames: string[]): any;
>__rest : Symbol(__rest, Decl(tslib.d.ts, --, --))
>t : Symbol(t, Decl(tslib.d.ts, --, --))
>propertyNames : Symbol(propertyNames, Decl(tslib.d.ts, --, --))

export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
Expand Down Expand Up @@ -53,3 +59,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

export declare function __generator(thisArg: any, body: Function): any;
>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
>body : Symbol(body, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

export declare function __exportStar(m: any, exports: any): void;
>__exportStar : Symbol(__exportStar, Decl(tslib.d.ts, --, --))
>m : Symbol(m, Decl(tslib.d.ts, --, --))
>exports : Symbol(exports, Decl(tslib.d.ts, --, --))

17 changes: 17 additions & 0 deletions tests/baselines/reference/importHelpersAmd.types
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export class A { }
import { A } from "./a";
>A : typeof A

export * from "./a";
export class B extends A { }
>B : B
>A : A
Expand All @@ -23,6 +24,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
>t : any
>sources : any[]

export declare function __rest(t: any, propertyNames: string[]): any;
>__rest : (t: any, propertyNames: string[]) => any
>t : any
>propertyNames : string[]

export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
>__decorate : (decorators: Function[], target: any, key?: string | symbol, desc?: any) => any
>decorators : Function[]
Expand Down Expand Up @@ -53,3 +59,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
>generator : Function
>Function : Function

export declare function __generator(thisArg: any, body: Function): any;
>__generator : (thisArg: any, body: Function) => any
>thisArg : any
>body : Function
>Function : Function

export declare function __exportStar(m: any, exports: any): void;
>__exportStar : (m: any, exports: any) => void
>m : any
>exports : any

4 changes: 3 additions & 1 deletion tests/baselines/reference/importHelpersInAmbientContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ declare namespace N {
//// [tslib.d.ts]
export declare function __extends(d: Function, b: Function): void;
export declare function __assign(t: any, ...sources: any[]): any;
export declare function __rest(t: any, propertyNames: string[]): any;
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
export declare function __param(paramIndex: number, decorator: Function): Function;
export declare function __metadata(metadataKey: any, metadataValue: any): Function;
export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;

export declare function __generator(thisArg: any, body: Function): any;
export declare function __exportStar(m: any, exports: any): void;

//// [b.js]
"use strict";
Expand Down
16 changes: 16 additions & 0 deletions tests/baselines/reference/importHelpersInAmbientContext.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
>t : Symbol(t, Decl(tslib.d.ts, --, --))
>sources : Symbol(sources, Decl(tslib.d.ts, --, --))

export declare function __rest(t: any, propertyNames: string[]): any;
>__rest : Symbol(__rest, Decl(tslib.d.ts, --, --))
>t : Symbol(t, Decl(tslib.d.ts, --, --))
>propertyNames : Symbol(propertyNames, Decl(tslib.d.ts, --, --))

export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
Expand Down Expand Up @@ -128,3 +133,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

export declare function __generator(thisArg: any, body: Function): any;
>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
>body : Symbol(body, Decl(tslib.d.ts, --, --))
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))

export declare function __exportStar(m: any, exports: any): void;
>__exportStar : Symbol(__exportStar, Decl(tslib.d.ts, --, --))
>m : Symbol(m, Decl(tslib.d.ts, --, --))
>exports : Symbol(exports, Decl(tslib.d.ts, --, --))

16 changes: 16 additions & 0 deletions tests/baselines/reference/importHelpersInAmbientContext.types
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
>t : any
>sources : any[]

export declare function __rest(t: any, propertyNames: string[]): any;
>__rest : (t: any, propertyNames: string[]) => any
>t : any
>propertyNames : string[]

export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
>__decorate : (decorators: Function[], target: any, key?: string | symbol, desc?: any) => any
>decorators : Function[]
Expand Down Expand Up @@ -128,3 +133,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
>generator : Function
>Function : Function

export declare function __generator(thisArg: any, body: Function): any;
>__generator : (thisArg: any, body: Function) => any
>thisArg : any
>body : Function
>Function : Function

export declare function __exportStar(m: any, exports: any): void;
>__exportStar : (m: any, exports: any) => void
>m : any
>exports : any

21 changes: 14 additions & 7 deletions tests/baselines/reference/importHelpersNoHelpers.errors.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
tests/cases/compiler/external.ts(2,16): error TS2343: This syntax requires an imported helper named '__extends', but module 'tslib' has no exported member '__extends'.
tests/cases/compiler/external.ts(6,1): error TS2343: This syntax requires an imported helper named '__decorate', but module 'tslib' has no exported member '__decorate'.
tests/cases/compiler/external.ts(6,1): error TS2343: This syntax requires an imported helper named '__metadata', but module 'tslib' has no exported member '__metadata'.
tests/cases/compiler/external.ts(8,12): error TS2343: This syntax requires an imported helper named '__param', but module 'tslib' has no exported member '__param'.
tests/cases/compiler/external.ts(13,13): error TS2343: This syntax requires an imported helper named '__assign', but module 'tslib' has no exported member '__assign'.
tests/cases/compiler/external.ts(14,12): error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.
tests/cases/compiler/external.ts(1,1): error TS2343: This syntax requires an imported helper named '__exportStar', but module 'tslib' has no exported member '__exportStar'.
tests/cases/compiler/external.ts(3,16): error TS2343: This syntax requires an imported helper named '__extends', but module 'tslib' has no exported member '__extends'.
tests/cases/compiler/external.ts(7,1): error TS2343: This syntax requires an imported helper named '__decorate', but module 'tslib' has no exported member '__decorate'.
tests/cases/compiler/external.ts(7,1): error TS2343: This syntax requires an imported helper named '__metadata', but module 'tslib' has no exported member '__metadata'.
tests/cases/compiler/external.ts(9,12): error TS2343: This syntax requires an imported helper named '__param', but module 'tslib' has no exported member '__param'.
tests/cases/compiler/external.ts(14,13): error TS2343: This syntax requires an imported helper named '__assign', but module 'tslib' has no exported member '__assign'.
tests/cases/compiler/external.ts(15,12): error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.


==== tests/cases/compiler/external.ts (6 errors) ====
==== tests/cases/compiler/external.ts (7 errors) ====
export * from "./other";
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2343: This syntax requires an imported helper named '__exportStar', but module 'tslib' has no exported member '__exportStar'.
export class A { }
export class B extends A { }
~~~~~~~~~
Expand Down Expand Up @@ -34,6 +38,9 @@ tests/cases/compiler/external.ts(14,12): error TS2343: This syntax requires an i
~
!!! error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.

==== tests/cases/compiler/other.ts (0 errors) ====
export const x = 1;

==== tests/cases/compiler/script.ts (0 errors) ====
class A { }
class B extends A { }
Expand Down
Loading