diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index edefd6bf9dde5..caa75a45eb987 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -892,6 +892,7 @@ namespace ts { function mergeSymbol(target: Symbol, source: Symbol) { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || (source.flags | target.flags) & SymbolFlags.JSContainer) { + Debug.assert(!!(target.flags & SymbolFlags.Transient)); // Javascript static-property-assignment declarations always merge, even though they are also values if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { // reset flag when merging instantiated module into value module that has only const enums @@ -915,8 +916,12 @@ namespace ts { } if ((source.flags | target.flags) & SymbolFlags.JSContainer) { const sourceInitializer = getJSInitializerSymbol(source); - const targetInitializer = getJSInitializerSymbol(target); + let targetInitializer = getJSInitializerSymbol(target); if (sourceInitializer !== source || targetInitializer !== target) { + if (!(targetInitializer.flags & SymbolFlags.Transient)) { + const mergedInitializer = getMergedSymbol(targetInitializer); + targetInitializer = mergedInitializer === targetInitializer ? cloneSymbol(targetInitializer) : mergedInitializer; + } mergeSymbol(targetInitializer, sourceInitializer); } } @@ -19452,7 +19457,7 @@ namespace ts { } const links = getNodeLinks(node); - const type = getTypeOfSymbol(node.symbol); + const type = getTypeOfSymbol(getMergedSymbol(node.symbol)); if (isTypeAny(type)) { return type; } diff --git a/tests/baselines/reference/typeFromPropertyAssignment10.types b/tests/baselines/reference/typeFromPropertyAssignment10.types index f4d118165373e..a880498f047c7 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment10.types +++ b/tests/baselines/reference/typeFromPropertyAssignment10.types @@ -1,28 +1,28 @@ === tests/cases/conformance/salsa/module.js === var Outer = Outer || {}; ->Outer : typeof __object ->Outer || {} : typeof __object ->Outer : typeof __object ->{} : typeof __object +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>Outer || {} : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>{} : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } Outer.app = Outer.app || {}; ->Outer.app = Outer.app || {} : typeof __object ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object ->Outer.app || {} : typeof __object ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object ->{} : typeof __object +>Outer.app = Outer.app || {} : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer.app || {} : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>{} : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } === tests/cases/conformance/salsa/someview.js === Outer.app.SomeView = (function () { >Outer.app.SomeView = (function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void >Outer.app.SomeView : () => void ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >SomeView : () => void >(function () { var SomeView = function() { var me = this; } return SomeView;})() : () => void >(function () { var SomeView = function() { var me = this; } return SomeView;}) : () => () => void @@ -43,9 +43,9 @@ Outer.app.SomeView = (function () { Outer.app.Inner = class { >Outer.app.Inner = class { constructor() { /** @type {number} */ this.y = 12; }} : typeof Inner >Outer.app.Inner : typeof Inner ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >Inner : typeof Inner >class { constructor() { /** @type {number} */ this.y = 12; }} : typeof Inner @@ -63,9 +63,9 @@ var example = new Outer.app.Inner(); >example : Inner >new Outer.app.Inner() : Inner >Outer.app.Inner : typeof Inner ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >Inner : typeof Inner example.y; @@ -77,9 +77,9 @@ example.y; Outer.app.statische = function (k) { >Outer.app.statische = function (k) { return k ** k;} : (k: number) => number >Outer.app.statische : (k: number) => number ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >statische : (k: number) => number >function (k) { return k ** k;} : (k: number) => number >k : number @@ -93,9 +93,9 @@ Outer.app.statische = function (k) { Outer.app.Application = (function () { >Outer.app.Application = (function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void >Outer.app.Application : () => void ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >Application : () => void >(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;})() : () => void >(function () { /** * Application main class. * Will be instantiated & initialized by HTML page */ var Application = function () { var me = this; me.view = new Outer.app.SomeView(); }; return Application;}) : () => () => void @@ -120,9 +120,9 @@ Outer.app.Application = (function () { >view : any >new Outer.app.SomeView() : any >Outer.app.SomeView : () => void ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >SomeView : () => void }; @@ -135,18 +135,18 @@ var app = new Outer.app.Application(); >app : any >new Outer.app.Application() : any >Outer.app.Application : () => void ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >Application : () => void var inner = new Outer.app.Inner(); >inner : Inner >new Outer.app.Inner() : Inner >Outer.app.Inner : typeof Inner ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >Inner : typeof Inner inner.y; @@ -166,9 +166,9 @@ x.y; Outer.app.statische(101); // Infinity, duh >Outer.app.statische(101) : number >Outer.app.statische : (k: number) => number ->Outer.app : typeof __object ->Outer : typeof __object ->app : typeof __object +>Outer.app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } +>Outer : { [x: string]: any; app: { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; }; } +>app : { [x: string]: any; SomeView: () => void; Inner: typeof Inner; statische(k: number): number; Application: () => void; } >statische : (k: number) => number >101 : 101 diff --git a/tests/baselines/reference/typeFromPropertyAssignment14.types b/tests/baselines/reference/typeFromPropertyAssignment14.types index 10a3fa00e3514..0416d2de952fe 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment14.types +++ b/tests/baselines/reference/typeFromPropertyAssignment14.types @@ -1,13 +1,13 @@ === tests/cases/conformance/salsa/def.js === var Outer = {}; ->Outer : typeof Outer ->{} : typeof Outer +>Outer : { [x: string]: any; Inner(): void; } +>{} : { [x: string]: any; Inner(): void; } === tests/cases/conformance/salsa/work.js === Outer.Inner = function () {} >Outer.Inner = function () {} : () => void >Outer.Inner : () => void ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner(): void; } >Inner : () => void >function () {} : () => void @@ -15,7 +15,7 @@ Outer.Inner.prototype = { >Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } >Outer.Inner.prototype : any >Outer.Inner : () => void ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner(): void; } >Inner : () => void >prototype : any >{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } @@ -48,7 +48,7 @@ var inno = new Outer.Inner() >inno : { [x: string]: any; x: number; m(): void; } >new Outer.Inner() : { [x: string]: any; x: number; m(): void; } >Outer.Inner : () => void ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner(): void; } >Inner : () => void inno.x diff --git a/tests/baselines/reference/typeFromPropertyAssignment4.types b/tests/baselines/reference/typeFromPropertyAssignment4.types index 3b46296c10e94..90b97d91d0c32 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment4.types +++ b/tests/baselines/reference/typeFromPropertyAssignment4.types @@ -1,13 +1,13 @@ === tests/cases/conformance/salsa/def.js === var Outer = {}; ->Outer : typeof Outer ->{} : typeof Outer +>Outer : { [x: string]: any; Inner: typeof Inner; } +>{} : { [x: string]: any; Inner: typeof Inner; } === tests/cases/conformance/salsa/a.js === Outer.Inner = class { >Outer.Inner = class { constructor() { /** @type {number} */ this.y = 12 }} : typeof Inner >Outer.Inner : typeof Inner ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner: typeof Inner; } >Inner : typeof Inner >class { constructor() { /** @type {number} */ this.y = 12 }} : typeof Inner @@ -35,7 +35,7 @@ var inner = new Outer.Inner() >inner : Inner >new Outer.Inner() : Inner >Outer.Inner : typeof Inner ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner: typeof Inner; } >Inner : typeof Inner inner.y @@ -57,7 +57,7 @@ var z = new Outer.Inner() >z : Inner >new Outer.Inner() : Inner >Outer.Inner : typeof Inner ->Outer : typeof Outer +>Outer : { [x: string]: any; Inner: typeof Inner; } >Inner : typeof Inner z.y diff --git a/tests/cases/fourslash/jsSpecialAssignmentMerging.ts b/tests/cases/fourslash/jsSpecialAssignmentMerging.ts new file mode 100644 index 0000000000000..fa093470baeaa --- /dev/null +++ b/tests/cases/fourslash/jsSpecialAssignmentMerging.ts @@ -0,0 +1,22 @@ +/// +// @noEmit: true +// @allowJs: true +// @checkJs: true + +// @Filename: b.d.ts +//// declare class C { } +// @Filename: a.js +//// C.prototype = { m: "q"; } +// @Filename: test.js +//// var c = new C() +//// /*1*/ +//// var c = new C() + +// #24015 +// This failed with 13 and up on my machine, so 20 is 2**7 more than needed. +for (let i = 0; i < 20; i++) { + goTo.marker('1'); + edit.insertLine('c'); + + verify.getSemanticDiagnostics([]) +}