diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 9336c54a40fb6..92b214276e533 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -283,10 +283,8 @@ export function transformModule(context: TransformationContext): (x: SourceFile ); } } - if (some(currentModuleInfo.exportedFunctions)) { - for (const f of currentModuleInfo.exportedFunctions) { - appendExportsOfHoistedDeclaration(statements, f); - } + for (const f of currentModuleInfo.exportedFunctions) { + appendExportsOfHoistedDeclaration(statements, f); } append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, topLevelVisitor, isStatement)); @@ -613,10 +611,8 @@ export function transformModule(context: TransformationContext): (x: SourceFile if (some(currentModuleInfo.exportedNames)) { append(statements, factory.createExpressionStatement(reduceLeft(currentModuleInfo.exportedNames, (prev, nextId) => factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier("exports"), factory.createIdentifier(idText(nextId))), prev), factory.createVoidZero() as Expression))); } - if (some(currentModuleInfo.exportedFunctions)) { - for (const f of currentModuleInfo.exportedFunctions) { - appendExportsOfHoistedDeclaration(statements, f); - } + for (const f of currentModuleInfo.exportedFunctions) { + appendExportsOfHoistedDeclaration(statements, f); } // Visit each statement of the module body. diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 5f79baf03fe54..f03ad63a1c0ca 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -433,7 +433,7 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc // this set is used to filter names brought by star expors. // local names set should only be added if we have anything exported - if (!some(moduleInfo.exportedNames) && !some(moduleInfo.exportedFunctions) && moduleInfo.exportSpecifiers.size === 0) { + if (!some(moduleInfo.exportedNames) && moduleInfo.exportedFunctions.size === 0 && moduleInfo.exportSpecifiers.size === 0) { // no exported declarations (export var ...) or export specifiers (export {x}) // check if we have any non star export declarations. let hasExportDeclarationWithExportClause = false; @@ -469,21 +469,19 @@ export function transformSystemModule(context: TransformationContext): (x: Sourc } } - if (moduleInfo.exportedFunctions) { - for (const f of moduleInfo.exportedFunctions) { - if (hasSyntacticModifier(f, ModifierFlags.Default)) { - continue; - } - Debug.assert(!!f.name); - - // write name of exported declaration, i.e 'export var x...' - exportedNames.push( - factory.createPropertyAssignment( - factory.createStringLiteralFromNode(f.name), - factory.createTrue(), - ), - ); + for (const f of moduleInfo.exportedFunctions) { + if (hasSyntacticModifier(f, ModifierFlags.Default)) { + continue; } + Debug.assert(!!f.name); + + // write name of exported declaration, i.e 'export var x...' + exportedNames.push( + factory.createPropertyAssignment( + factory.createStringLiteralFromNode(f.name), + factory.createTrue(), + ), + ); } const exportedNamesStorageRef = factory.createUniqueName("exportedNames"); diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index 893460cf7a42f..8f5f2b257a004 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -105,7 +105,7 @@ export interface ExternalModuleInfo { exportSpecifiers: IdentifierNameMap; // file-local export specifiers by name (no reexports) exportedBindings: Identifier[][]; // exported names of local declarations exportedNames: Identifier[] | undefined; // all exported names in the module, both local and reexported, excluding the names of locally exported function declarations - exportedFunctions: FunctionDeclaration[] | undefined; // all of the top-level exported function declarations + exportedFunctions: Set; // all of the top-level exported function declarations exportEquals: ExportAssignment | undefined; // an export= declaration if one was present hasExportStarsToExportValues: boolean; // whether this module contains export* } @@ -174,8 +174,8 @@ export function collectExternalModuleInfo(context: TransformationContext, source const exportSpecifiers = new IdentifierNameMultiMap(); const exportedBindings: Identifier[][] = []; const uniqueExports = new Map(); + const exportedFunctions = new Set(); let exportedNames: Identifier[] | undefined; - let exportedFunctions: FunctionDeclaration[] | undefined; let hasExportDefault = false; let exportEquals: ExportAssignment | undefined; let hasExportStarsToExportValues = false; @@ -256,22 +256,7 @@ export function collectExternalModuleInfo(context: TransformationContext, source case SyntaxKind.FunctionDeclaration: if (hasSyntacticModifier(node, ModifierFlags.Export)) { - exportedFunctions = append(exportedFunctions, node as FunctionDeclaration); - if (hasSyntacticModifier(node, ModifierFlags.Default)) { - // export default function() { } - if (!hasExportDefault) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(node as FunctionDeclaration)); - hasExportDefault = true; - } - } - else { - // export function x() { } - const name = (node as FunctionDeclaration).name!; - if (!uniqueExports.get(idText(name))) { - multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); - uniqueExports.set(idText(name), true); - } - } + addExportedFunctionDeclaration(node as FunctionDeclaration, /*name*/ undefined, hasSyntacticModifier(node, ModifierFlags.Default)); } break; @@ -317,6 +302,11 @@ export function collectExternalModuleInfo(context: TransformationContext, source || resolver.getReferencedValueDeclaration(name); if (decl) { + if (decl.kind === SyntaxKind.FunctionDeclaration) { + addExportedFunctionDeclaration(decl as FunctionDeclaration, specifier.name, specifier.name.escapedText === InternalSymbolName.Default); + continue; + } + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name); } @@ -325,6 +315,27 @@ export function collectExternalModuleInfo(context: TransformationContext, source } } } + + function addExportedFunctionDeclaration(node: FunctionDeclaration, name: Identifier | undefined, isDefault: boolean) { + exportedFunctions.add(node); + if (isDefault) { + // export default function() { } + // function x() { } + export { x as default }; + if (!hasExportDefault) { + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name ?? context.factory.getDeclarationName(node)); + hasExportDefault = true; + } + } + else { + // export function x() { } + // function x() { } + export { x } + name ??= node.name!; + if (!uniqueExports.get(idText(name))) { + multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); + uniqueExports.set(idText(name), true); + } + } + } } function collectExportedVariableInfo(decl: VariableDeclaration | BindingElement, uniqueExports: Map, exportedNames: Identifier[] | undefined, exportedBindings: Identifier[][]) { diff --git a/tests/baselines/reference/assertionFunctionWildcardImport2.js b/tests/baselines/reference/assertionFunctionWildcardImport2.js index ddc8713a11fd5..4d1beeec12f3c 100644 --- a/tests/baselines/reference/assertionFunctionWildcardImport2.js +++ b/tests/baselines/reference/assertionFunctionWildcardImport2.js @@ -23,7 +23,7 @@ function test(obj: string | null): void { //// [asserts.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isNonNullable = void 0; +exports.isNonNullable = isNonNullable; function isNonNullable(obj) { if (obj === undefined || obj === null) { throw new Error("Must not be a nullable value"); diff --git a/tests/baselines/reference/declarationEmitInferredTypeAlias2.js b/tests/baselines/reference/declarationEmitInferredTypeAlias2.js index 2b4273dda315b..9be3ac16bcdf8 100644 --- a/tests/baselines/reference/declarationEmitInferredTypeAlias2.js +++ b/tests/baselines/reference/declarationEmitInferredTypeAlias2.js @@ -23,7 +23,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); //// [1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.bar = exports.v = void 0; +exports.v = void 0; +exports.bar = bar; var v = "str" || true; exports.v = v; function bar() { diff --git a/tests/baselines/reference/declarationsForIndirectTypeAliasReference.js b/tests/baselines/reference/declarationsForIndirectTypeAliasReference.js index e356338cf14dc..e16e1dc35efcb 100644 --- a/tests/baselines/reference/declarationsForIndirectTypeAliasReference.js +++ b/tests/baselines/reference/declarationsForIndirectTypeAliasReference.js @@ -39,7 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); //// [a.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.doSome = void 0; +exports.doSome = doSome; var MAP = { a: "a" }; diff --git a/tests/baselines/reference/exportsAndImports1-amd.js b/tests/baselines/reference/exportsAndImports1-amd.js index 4bb4dd61c602e..752885c6cc936 100644 --- a/tests/baselines/reference/exportsAndImports1-amd.js +++ b/tests/baselines/reference/exportsAndImports1-amd.js @@ -37,7 +37,8 @@ export { v, f, C, I, E, D, M, N, T, a }; define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.a = exports.M = exports.E = exports.C = exports.f = exports.v = void 0; + exports.a = exports.M = exports.E = exports.C = exports.v = void 0; + exports.f = f; var v = 1; exports.v = v; function f() { } diff --git a/tests/baselines/reference/exportsAndImports1-es6.js b/tests/baselines/reference/exportsAndImports1-es6.js index 0ae74e26e4050..ac5b0421b1c2e 100644 --- a/tests/baselines/reference/exportsAndImports1-es6.js +++ b/tests/baselines/reference/exportsAndImports1-es6.js @@ -36,7 +36,8 @@ export { v, f, C, I, E, D, M, N, T, a }; //// [t1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.a = exports.M = exports.E = exports.C = exports.f = exports.v = void 0; +exports.a = exports.M = exports.E = exports.C = exports.v = void 0; +exports.f = f; var v = 1; exports.v = v; function f() { } diff --git a/tests/baselines/reference/exportsAndImports1.js b/tests/baselines/reference/exportsAndImports1.js index a8dbd5b01c113..080433308cc4b 100644 --- a/tests/baselines/reference/exportsAndImports1.js +++ b/tests/baselines/reference/exportsAndImports1.js @@ -36,7 +36,8 @@ export { v, f, C, I, E, D, M, N, T, a }; //// [t1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.a = exports.M = exports.E = exports.C = exports.f = exports.v = void 0; +exports.a = exports.M = exports.E = exports.C = exports.v = void 0; +exports.f = f; var v = 1; exports.v = v; function f() { } diff --git a/tests/baselines/reference/exportsAndImports3-amd.js b/tests/baselines/reference/exportsAndImports3-amd.js index 2e1976b18e86f..2c52509189182 100644 --- a/tests/baselines/reference/exportsAndImports3-amd.js +++ b/tests/baselines/reference/exportsAndImports3-amd.js @@ -37,7 +37,7 @@ export { v, f, C, I, E, D, M, N, T, a }; define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); - exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.f1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; + exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; exports.f = f; exports.f1 = f; exports.v = 1; diff --git a/tests/baselines/reference/exportsAndImports3-es6.js b/tests/baselines/reference/exportsAndImports3-es6.js index e7d5bda14e57f..50c7f861f7c07 100644 --- a/tests/baselines/reference/exportsAndImports3-es6.js +++ b/tests/baselines/reference/exportsAndImports3-es6.js @@ -36,7 +36,7 @@ export { v, f, C, I, E, D, M, N, T, a }; //// [t1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.f1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; +exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; exports.f = f; exports.f1 = f; exports.v = 1; diff --git a/tests/baselines/reference/exportsAndImports3.js b/tests/baselines/reference/exportsAndImports3.js index 2714fe2ecaaf8..eede925b22a68 100644 --- a/tests/baselines/reference/exportsAndImports3.js +++ b/tests/baselines/reference/exportsAndImports3.js @@ -36,7 +36,7 @@ export { v, f, C, I, E, D, M, N, T, a }; //// [t1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.f1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; +exports.a1 = exports.M1 = exports.E1 = exports.C1 = exports.v1 = exports.a = exports.M = exports.E = exports.C = exports.v = void 0; exports.f = f; exports.f1 = f; exports.v = 1; diff --git a/tests/baselines/reference/importNonExportedMember.js b/tests/baselines/reference/importNonExportedMember.js index 8db7c1d65349e..9c935d0ac0ea5 100644 --- a/tests/baselines/reference/importNonExportedMember.js +++ b/tests/baselines/reference/importNonExportedMember.js @@ -12,7 +12,8 @@ import { foo, bar } from "./a"; //// [a.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.baz = exports.foo = void 0; +exports.foo = foo; +exports.baz = bar; //// [b.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/importNonExportedMember1.js b/tests/baselines/reference/importNonExportedMember1.js index f72561c644085..571284f4eb3c0 100644 --- a/tests/baselines/reference/importNonExportedMember1.js +++ b/tests/baselines/reference/importNonExportedMember1.js @@ -12,7 +12,7 @@ import { bar } from "./a"; //// [a.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.foo = void 0; +exports.foo = foo; //// [b.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/jsDeclarationsDefault.js b/tests/baselines/reference/jsDeclarationsDefault.js index 4c14181fcbf85..4357bdd55759e 100644 --- a/tests/baselines/reference/jsDeclarationsDefault.js +++ b/tests/baselines/reference/jsDeclarationsDefault.js @@ -46,7 +46,7 @@ exports.default = 12; //// [index2.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.bar = exports.x = void 0; +exports.x = void 0; exports.default = foo; exports.bar = foo; function foo() { diff --git a/tests/baselines/reference/jsDeclarationsFunctions.js b/tests/baselines/reference/jsDeclarationsFunctions.js index d8fe4ed52e2f6..b9c6f345cbeb9 100644 --- a/tests/baselines/reference/jsDeclarationsFunctions.js +++ b/tests/baselines/reference/jsDeclarationsFunctions.js @@ -63,13 +63,14 @@ export function j() {} //// [index.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.jj = exports.ii = exports.h = exports.g = void 0; exports.a = a; exports.b = b; exports.c = c; exports.d = d; exports.e = e; exports.f = f; +exports.g = g; +exports.h = hh; exports.i = i; exports.ii = i; exports.j = j; diff --git a/tests/baselines/reference/jsxNamespaceReexports.js b/tests/baselines/reference/jsxNamespaceReexports.js index bb65971d285b4..157c5ce7eb105 100644 --- a/tests/baselines/reference/jsxNamespaceReexports.js +++ b/tests/baselines/reference/jsxNamespaceReexports.js @@ -18,7 +18,7 @@ const content = ; //// [library.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.createElement = void 0; +exports.createElement = createElement; function createElement(element, props) { var children = []; for (var _i = 2; _i < arguments.length; _i++) { diff --git a/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=node16).js b/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=node16).js index 39944c06ff259..30926a25ccde1 100644 --- a/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=node16).js +++ b/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=node16).js @@ -28,7 +28,8 @@ export {require, exports, Object}; //// [index.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.Object = exports.exports = exports.require = exports.__esModule = void 0; +exports.Object = exports.exports = exports.__esModule = void 0; +exports.require = require; // cjs format file function require() { } const exports = {}; diff --git a/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=nodenext).js b/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=nodenext).js index 39944c06ff259..30926a25ccde1 100644 --- a/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesAllowJsGeneratedNameCollisions(module=nodenext).js @@ -28,7 +28,8 @@ export {require, exports, Object}; //// [index.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.Object = exports.exports = exports.require = exports.__esModule = void 0; +exports.Object = exports.exports = exports.__esModule = void 0; +exports.require = require; // cjs format file function require() { } const exports = {}; diff --git a/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=node16).js b/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=node16).js index 1572a39c8d770..3b196cd32c98b 100644 --- a/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=node16).js +++ b/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=node16).js @@ -28,7 +28,8 @@ export {require, exports, Object}; //// [index.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.Object = exports.exports = exports.require = exports.__esModule = void 0; +exports.Object = exports.exports = exports.__esModule = void 0; +exports.require = require; // cjs format file function require() { } const exports = {}; diff --git a/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=nodenext).js b/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=nodenext).js index 1572a39c8d770..3b196cd32c98b 100644 --- a/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesGeneratedNameCollisions(module=nodenext).js @@ -28,7 +28,8 @@ export {require, exports, Object}; //// [index.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.Object = exports.exports = exports.require = exports.__esModule = void 0; +exports.Object = exports.exports = exports.__esModule = void 0; +exports.require = require; // cjs format file function require() { } const exports = {}; diff --git a/tests/baselines/reference/reExportDefaultExport.js b/tests/baselines/reference/reExportDefaultExport.js index 71ba9c96f931a..b0a50abe5170f 100644 --- a/tests/baselines/reference/reExportDefaultExport.js +++ b/tests/baselines/reference/reExportDefaultExport.js @@ -16,7 +16,6 @@ foo(); //// [m1.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.f = void 0; exports.default = f; exports.f = f; function f() { diff --git a/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js index e09a3c117267d..3edec230fe0f8 100644 --- a/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js +++ b/tests/baselines/reference/spreadExpressionContextualTypeWithNamespace.js @@ -38,7 +38,8 @@ getStuff().exportedDirectly; "use strict"; // Repro from #44179 with some modification Object.defineProperty(exports, "__esModule", { value: true }); -exports.obj = exports.klass = exports.func = void 0; +exports.obj = exports.klass = void 0; +exports.func = func; exports.exportedDirectly = exportedDirectly; function func() { } var klass = /** @class */ (function () { diff --git a/tests/baselines/reference/valuesMergingAcrossModules.js b/tests/baselines/reference/valuesMergingAcrossModules.js index adf0e145cb497..2f536cb52d330 100644 --- a/tests/baselines/reference/valuesMergingAcrossModules.js +++ b/tests/baselines/reference/valuesMergingAcrossModules.js @@ -22,7 +22,7 @@ A.displayName; //// [a.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.A = void 0; +exports.A = A; function A() { } //// [b.js] "use strict";