diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 15d7cb6ff5fa5..20aac7d4936e5 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -63,7 +63,7 @@ namespace ts { let enclosingDeclaration: Node; let necessaryTypeReferences: Map | undefined; let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; - let lateStatementReplacementMap: Map>; + let lateStatementReplacementMap: Map>; let suppressNewDiagnosticContexts: boolean; let exportedModulesFromDeclarationEmit: Symbol[] | undefined; @@ -701,12 +701,12 @@ namespace ts { } } - function isExternalModuleIndicator(result: LateVisibilityPaintedStatement) { + function isExternalModuleIndicator(result: LateVisibilityPaintedStatement | ExportAssignment) { // Exported top-level member indicates moduleness return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export); } - function needsScopeMarker(result: LateVisibilityPaintedStatement) { + function needsScopeMarker(result: LateVisibilityPaintedStatement | ExportAssignment) { return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result); } @@ -1047,7 +1047,43 @@ namespace ts { return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl])); }); const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name!, createModuleBlock(declarations), NodeFlags.Namespace); - return [clean, namespaceDecl]; + + if (!hasModifier(clean, ModifierFlags.ExportDefault)) { + return [clean, namespaceDecl]; + } + + const modifiers = createModifiersFromModifierFlags((getModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient); + const cleanDeclaration = updateFunctionDeclaration( + clean, + /*decorators*/ undefined, + modifiers, + /*asteriskToken*/ undefined, + clean.name, + clean.typeParameters, + clean.parameters, + clean.type, + /*body*/ undefined + ); + + const namespaceDeclaration = updateModuleDeclaration( + namespaceDecl, + /*decorators*/ undefined, + modifiers, + namespaceDecl.name, + namespaceDecl.body + ); + + const exportDefaultDeclaration = createExportAssignment( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*isExportEquals*/ false, + namespaceDecl.name + ); + + resultHasExternalModuleIndicator = true; + resultHasScopeMarker = true; + + return [cleanDeclaration, namespaceDeclaration, exportDefaultDeclaration]; } else { return clean; diff --git a/tests/baselines/reference/exportDefaultNamespace.js b/tests/baselines/reference/exportDefaultNamespace.js new file mode 100644 index 0000000000000..39a70d5e231d7 --- /dev/null +++ b/tests/baselines/reference/exportDefaultNamespace.js @@ -0,0 +1,24 @@ +//// [exportDefaultNamespace.ts] +export default function someFunc() { + return 'hello!'; +} + +someFunc.someProp = 'yo'; + + +//// [exportDefaultNamespace.js] +"use strict"; +exports.__esModule = true; +function someFunc() { + return 'hello!'; +} +exports["default"] = someFunc; +someFunc.someProp = 'yo'; + + +//// [exportDefaultNamespace.d.ts] +declare function someFunc(): string; +declare namespace someFunc { + var someProp: string; +} +export default someFunc; diff --git a/tests/baselines/reference/exportDefaultNamespace.symbols b/tests/baselines/reference/exportDefaultNamespace.symbols new file mode 100644 index 0000000000000..eee148768948b --- /dev/null +++ b/tests/baselines/reference/exportDefaultNamespace.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/declarationEmit/exportDefaultNamespace.ts === +export default function someFunc() { +>someFunc : Symbol(someFunc, Decl(exportDefaultNamespace.ts, 0, 0), Decl(exportDefaultNamespace.ts, 2, 1)) + + return 'hello!'; +} + +someFunc.someProp = 'yo'; +>someFunc.someProp : Symbol(someFunc.someProp, Decl(exportDefaultNamespace.ts, 2, 1)) +>someFunc : Symbol(someFunc, Decl(exportDefaultNamespace.ts, 0, 0), Decl(exportDefaultNamespace.ts, 2, 1)) +>someProp : Symbol(someFunc.someProp, Decl(exportDefaultNamespace.ts, 2, 1)) + diff --git a/tests/baselines/reference/exportDefaultNamespace.types b/tests/baselines/reference/exportDefaultNamespace.types new file mode 100644 index 0000000000000..eebf33f51f4db --- /dev/null +++ b/tests/baselines/reference/exportDefaultNamespace.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/declarationEmit/exportDefaultNamespace.ts === +export default function someFunc() { +>someFunc : typeof someFunc + + return 'hello!'; +>'hello!' : "hello!" +} + +someFunc.someProp = 'yo'; +>someFunc.someProp = 'yo' : "yo" +>someFunc.someProp : string +>someFunc : typeof someFunc +>someProp : string +>'yo' : "yo" + diff --git a/tests/cases/conformance/declarationEmit/exportDefaultNamespace.ts b/tests/cases/conformance/declarationEmit/exportDefaultNamespace.ts new file mode 100644 index 0000000000000..4724bda727ca3 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/exportDefaultNamespace.ts @@ -0,0 +1,7 @@ +// @declaration: true + +export default function someFunc() { + return 'hello!'; +} + +someFunc.someProp = 'yo';