From f2735b5a0695b6194e0f798fc17ffa3f28035a8a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 20 Jun 2019 12:58:16 -0700 Subject: [PATCH] Fake up a namespace enclosing declaration when generating expando namespace members (#31971) * Fake up a namespace enclosing declaration when generating expando namespace members * Fix #31676 --- src/compiler/transformers/declarations.ts | 12 +- ...onEmitDefaultExportWithStaticAssignment.js | 114 ++++++++++++++++++ ...tDefaultExportWithStaticAssignment.symbols | 71 +++++++++++ ...mitDefaultExportWithStaticAssignment.types | 77 ++++++++++++ ...onEmitDefaultExportWithStaticAssignment.ts | 32 +++++ 5 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js create mode 100644 tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.symbols create mode 100644 tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.types create mode 100644 tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 20aac7d4936e5..03f08b4de5441 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1036,19 +1036,25 @@ namespace ts { /*body*/ undefined )); if (clean && resolver.isExpandoFunctionDeclaration(input)) { - const declarations = mapDefined(resolver.getPropertiesOfContainerFunction(input), p => { + const props = resolver.getPropertiesOfContainerFunction(input); + const fakespace = createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || createIdentifier("_default"), createModuleBlock([]), NodeFlags.Namespace); + fakespace.flags ^= NodeFlags.Synthesized; // unset synthesized so it is usable as an enclosing declaration + fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration; + fakespace.locals = createSymbolTable(props); + fakespace.symbol = props[0].parent!; + const declarations = mapDefined(props, p => { if (!isPropertyAccessExpression(p.valueDeclaration)) { return undefined; } getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); - const type = resolver.createTypeOfDeclaration(p.valueDeclaration, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker); + const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker); getSymbolAccessibilityDiagnostic = oldDiag; const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined); return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl])); }); const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name!, createModuleBlock(declarations), NodeFlags.Namespace); - if (!hasModifier(clean, ModifierFlags.ExportDefault)) { + if (!hasModifier(clean, ModifierFlags.Default)) { return [clean, namespaceDecl]; } diff --git a/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js new file mode 100644 index 0000000000000..0edf3b6f01bae --- /dev/null +++ b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js @@ -0,0 +1,114 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts] //// + +//// [foo.ts] +export class Foo {} + +//// [index1.ts] +import {Foo} from './foo'; +export default function Example() {} +Example.Foo = Foo + +//// [index2.ts] +import {Foo} from './foo'; +export {Foo}; +export default function Example() {} +Example.Foo = Foo + +//// [index3.ts] +export class Bar {} +export default function Example() {} + +Example.Bar = Bar + +//// [index4.ts] +function A() { } + +function B() { } + +export function C() { + return null; +} + +C.A = A; +C.B = B; + +//// [foo.js] +"use strict"; +exports.__esModule = true; +var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; +}()); +exports.Foo = Foo; +//// [index1.js] +"use strict"; +exports.__esModule = true; +var foo_1 = require("./foo"); +function Example() { } +exports["default"] = Example; +Example.Foo = foo_1.Foo; +//// [index2.js] +"use strict"; +exports.__esModule = true; +var foo_1 = require("./foo"); +exports.Foo = foo_1.Foo; +function Example() { } +exports["default"] = Example; +Example.Foo = foo_1.Foo; +//// [index3.js] +"use strict"; +exports.__esModule = true; +var Bar = /** @class */ (function () { + function Bar() { + } + return Bar; +}()); +exports.Bar = Bar; +function Example() { } +exports["default"] = Example; +Example.Bar = Bar; +//// [index4.js] +"use strict"; +exports.__esModule = true; +function A() { } +function B() { } +function C() { + return null; +} +exports.C = C; +C.A = A; +C.B = B; + + +//// [foo.d.ts] +export declare class Foo { +} +//// [index1.d.ts] +declare function Example(): void; +declare namespace Example { + var Foo: typeof import("./foo").Foo; +} +export default Example; +//// [index2.d.ts] +import { Foo } from './foo'; +export { Foo }; +declare function Example(): void; +declare namespace Example { + var Foo: typeof import("./foo").Foo; +} +export default Example; +//// [index3.d.ts] +export declare class Bar { +} +declare function Example(): void; +declare namespace Example { + var Bar: typeof import("./index3").Bar; +} +export default Example; +//// [index4.d.ts] +export declare function C(): any; +export declare namespace C { + var A: () => void; + var B: () => void; +} diff --git a/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.symbols b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.symbols new file mode 100644 index 0000000000000..f65952c18d7dd --- /dev/null +++ b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.symbols @@ -0,0 +1,71 @@ +=== tests/cases/compiler/foo.ts === +export class Foo {} +>Foo : Symbol(Foo, Decl(foo.ts, 0, 0)) + +=== tests/cases/compiler/index1.ts === +import {Foo} from './foo'; +>Foo : Symbol(Foo, Decl(index1.ts, 0, 8)) + +export default function Example() {} +>Example : Symbol(Example, Decl(index1.ts, 0, 26), Decl(index1.ts, 1, 36)) + +Example.Foo = Foo +>Example.Foo : Symbol(Example.Foo, Decl(index1.ts, 1, 36)) +>Example : Symbol(Example, Decl(index1.ts, 0, 26), Decl(index1.ts, 1, 36)) +>Foo : Symbol(Example.Foo, Decl(index1.ts, 1, 36)) +>Foo : Symbol(Foo, Decl(index1.ts, 0, 8)) + +=== tests/cases/compiler/index2.ts === +import {Foo} from './foo'; +>Foo : Symbol(Foo, Decl(index2.ts, 0, 8)) + +export {Foo}; +>Foo : Symbol(Foo, Decl(index2.ts, 1, 8)) + +export default function Example() {} +>Example : Symbol(Example, Decl(index2.ts, 1, 13), Decl(index2.ts, 2, 36)) + +Example.Foo = Foo +>Example.Foo : Symbol(Example.Foo, Decl(index2.ts, 2, 36)) +>Example : Symbol(Example, Decl(index2.ts, 1, 13), Decl(index2.ts, 2, 36)) +>Foo : Symbol(Example.Foo, Decl(index2.ts, 2, 36)) +>Foo : Symbol(Foo, Decl(index2.ts, 0, 8)) + +=== tests/cases/compiler/index3.ts === +export class Bar {} +>Bar : Symbol(Bar, Decl(index3.ts, 0, 0)) + +export default function Example() {} +>Example : Symbol(Example, Decl(index3.ts, 0, 19), Decl(index3.ts, 1, 36)) + +Example.Bar = Bar +>Example.Bar : Symbol(Example.Bar, Decl(index3.ts, 1, 36)) +>Example : Symbol(Example, Decl(index3.ts, 0, 19), Decl(index3.ts, 1, 36)) +>Bar : Symbol(Example.Bar, Decl(index3.ts, 1, 36)) +>Bar : Symbol(Bar, Decl(index3.ts, 0, 0)) + +=== tests/cases/compiler/index4.ts === +function A() { } +>A : Symbol(A, Decl(index4.ts, 0, 0)) + +function B() { } +>B : Symbol(B, Decl(index4.ts, 0, 17)) + +export function C() { +>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1)) + + return null; +} + +C.A = A; +>C.A : Symbol(C.A, Decl(index4.ts, 6, 1)) +>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1)) +>A : Symbol(C.A, Decl(index4.ts, 6, 1)) +>A : Symbol(A, Decl(index4.ts, 0, 0)) + +C.B = B; +>C.B : Symbol(C.B, Decl(index4.ts, 8, 8)) +>C : Symbol(C, Decl(index4.ts, 2, 16), Decl(index4.ts, 6, 1)) +>B : Symbol(C.B, Decl(index4.ts, 8, 8)) +>B : Symbol(B, Decl(index4.ts, 0, 17)) + diff --git a/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.types b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.types new file mode 100644 index 0000000000000..b00ddcd68cf59 --- /dev/null +++ b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.types @@ -0,0 +1,77 @@ +=== tests/cases/compiler/foo.ts === +export class Foo {} +>Foo : Foo + +=== tests/cases/compiler/index1.ts === +import {Foo} from './foo'; +>Foo : typeof Foo + +export default function Example() {} +>Example : typeof Example + +Example.Foo = Foo +>Example.Foo = Foo : typeof Foo +>Example.Foo : typeof Foo +>Example : typeof Example +>Foo : typeof Foo +>Foo : typeof Foo + +=== tests/cases/compiler/index2.ts === +import {Foo} from './foo'; +>Foo : typeof Foo + +export {Foo}; +>Foo : typeof Foo + +export default function Example() {} +>Example : typeof Example + +Example.Foo = Foo +>Example.Foo = Foo : typeof Foo +>Example.Foo : typeof Foo +>Example : typeof Example +>Foo : typeof Foo +>Foo : typeof Foo + +=== tests/cases/compiler/index3.ts === +export class Bar {} +>Bar : Bar + +export default function Example() {} +>Example : typeof Example + +Example.Bar = Bar +>Example.Bar = Bar : typeof Bar +>Example.Bar : typeof Bar +>Example : typeof Example +>Bar : typeof Bar +>Bar : typeof Bar + +=== tests/cases/compiler/index4.ts === +function A() { } +>A : () => void + +function B() { } +>B : () => void + +export function C() { +>C : typeof C + + return null; +>null : null +} + +C.A = A; +>C.A = A : () => void +>C.A : () => void +>C : typeof C +>A : () => void +>A : () => void + +C.B = B; +>C.B = B : () => void +>C.B : () => void +>C : typeof C +>B : () => void +>B : () => void + diff --git a/tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts b/tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts new file mode 100644 index 0000000000000..d6638ab8e3641 --- /dev/null +++ b/tests/cases/compiler/declarationEmitDefaultExportWithStaticAssignment.ts @@ -0,0 +1,32 @@ +// @declaration: true +// @filename: foo.ts +export class Foo {} + +// @filename: index1.ts +import {Foo} from './foo'; +export default function Example() {} +Example.Foo = Foo + +// @filename: index2.ts +import {Foo} from './foo'; +export {Foo}; +export default function Example() {} +Example.Foo = Foo + +// @filename: index3.ts +export class Bar {} +export default function Example() {} + +Example.Bar = Bar + +// @filename: index4.ts +function A() { } + +function B() { } + +export function C() { + return null; +} + +C.A = A; +C.B = B; \ No newline at end of file