Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2465,7 +2465,7 @@ namespace ts {
node.left.parent = node;
node.right.parent = node;
const lhs = node.left as PropertyAccessEntityNameExpression;
bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false);
bindPropertyAssignment(lhs.expression, lhs, /*isPrototypeProperty*/ false);
}

/**
Expand Down Expand Up @@ -2522,7 +2522,7 @@ namespace ts {
const isToplevel = isBinaryExpression(propertyAccess.parent)
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace)) && isToplevel) {
if (isToplevel && !isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace))) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unrelated change. I moved this condition to the front because it's the most important check, and it was buried behind the complex predicate at the end.

// make symbols or add declarations for intermediate containers
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment;
Expand Down
8 changes: 4 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20179,10 +20179,10 @@ namespace ts {
(isFunctionDeclaration(decl) && getSymbolOfNode(decl) ||
isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) ||
isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent));
if (assignmentSymbol) {
const prototype = forEach(assignmentSymbol.declarations, getAssignedJSPrototype);
if (prototype) {
return checkExpression(prototype);
if (assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.has("prototype" as __String)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would avoid has-then-getand just do:

const prototype = assignmentSymbol && assignmentSymbol.exports && assignmentSymbol.exports.get("prototype" as __String);
const init = prototype && getAssignedJSPrototype(prototype.valueDeclaration);
return init && checkExpression(init);

const init = getAssignedJSPrototype(assignmentSymbol.exports.get("prototype" as __String)!.valueDeclaration);
if (init) {
return checkExpression(init);
}
}
}
Expand Down
47 changes: 47 additions & 0 deletions tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
tests/cases/conformance/salsa/a.js(28,24): error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'.


==== tests/cases/conformance/salsa/a.js (1 errors) ====
// non top-level:
// all references to _map, set, get, addon should be ok
(function container() {
/** @constructor */
var Multimap = function() {
this._map = {};
this._map
this.set
this.get
this.addon
};

Multimap.prototype = {
set: function() {
this._map
this.set
this.get
this.addon
},
get() {
this._map
this.set
this.get
this.addon
}
}

Multimap.prototype.addon = function () {
~~~~~
!!! error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'.
this._map
this.set
this.get
this.addon
}

var mm = new Multimap();
mm._map
mm.set
mm.get
mm.addon
});

127 changes: 127 additions & 0 deletions tests/baselines/reference/typeFromPrototypeAssignment2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
=== tests/cases/conformance/salsa/a.js ===
// non top-level:
// all references to _map, set, get, addon should be ok
(function container() {
>container : Symbol(container, Decl(a.js, 2, 1))

/** @constructor */
var Multimap = function() {
>Multimap : Symbol(Multimap, Decl(a.js, 4, 7))

this._map = {};
>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

this._map
>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

this.set
>this.set : Symbol(set, Decl(a.js, 12, 26))
>set : Symbol(set, Decl(a.js, 12, 26))

this.get
>this.get : Symbol(get, Decl(a.js, 18, 10))
>get : Symbol(get, Decl(a.js, 18, 10))

this.addon
>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))

};

Multimap.prototype = {
>Multimap.prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6))
>Multimap : Symbol(Multimap, Decl(a.js, 4, 7))
>prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6))

set: function() {
>set : Symbol(set, Decl(a.js, 12, 26))

this._map
>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

this.set
>this.set : Symbol(set, Decl(a.js, 12, 26))
>set : Symbol(set, Decl(a.js, 12, 26))

this.get
>this.get : Symbol(get, Decl(a.js, 18, 10))
>get : Symbol(get, Decl(a.js, 18, 10))

this.addon
>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))

},
get() {
>get : Symbol(get, Decl(a.js, 18, 10))

this._map
>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

this.set
>this.set : Symbol(set, Decl(a.js, 12, 26))
>set : Symbol(set, Decl(a.js, 12, 26))

this.get
>this.get : Symbol(get, Decl(a.js, 18, 10))
>get : Symbol(get, Decl(a.js, 18, 10))

this.addon
>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
}
}

Multimap.prototype.addon = function () {
>Multimap.prototype : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>Multimap : Symbol(Multimap, Decl(a.js, 4, 7))
>prototype : Symbol(Multimap.prototype, Decl(a.js, 10, 6))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))

this._map
>this._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

this.set
>this.set : Symbol(set, Decl(a.js, 12, 26))
>set : Symbol(set, Decl(a.js, 12, 26))

this.get
>this.get : Symbol(get, Decl(a.js, 18, 10))
>get : Symbol(get, Decl(a.js, 18, 10))

this.addon
>this.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
}

var mm = new Multimap();
>mm : Symbol(mm, Decl(a.js, 34, 7))
>Multimap : Symbol(Multimap, Decl(a.js, 4, 7))

mm._map
>mm._map : Symbol(Multimap._map, Decl(a.js, 4, 31))
>mm : Symbol(mm, Decl(a.js, 34, 7))
>_map : Symbol(Multimap._map, Decl(a.js, 4, 31))

mm.set
>mm.set : Symbol(set, Decl(a.js, 12, 26))
>mm : Symbol(mm, Decl(a.js, 34, 7))
>set : Symbol(set, Decl(a.js, 12, 26))

mm.get
>mm.get : Symbol(get, Decl(a.js, 18, 10))
>mm : Symbol(mm, Decl(a.js, 34, 7))
>get : Symbol(get, Decl(a.js, 18, 10))

mm.addon
>mm.addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))
>mm : Symbol(mm, Decl(a.js, 34, 7))
>addon : Symbol(Multimap.addon, Decl(a.js, 25, 5))

});

156 changes: 156 additions & 0 deletions tests/baselines/reference/typeFromPrototypeAssignment2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
=== tests/cases/conformance/salsa/a.js ===
// non top-level:
// all references to _map, set, get, addon should be ok
(function container() {
>(function container() { /** @constructor */ var Multimap = function() { this._map = {}; this._map this.set this.get this.addon }; Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } Multimap.prototype.addon = function () { this._map this.set this.get this.addon } var mm = new Multimap(); mm._map mm.set mm.get mm.addon}) : () => void
>function container() { /** @constructor */ var Multimap = function() { this._map = {}; this._map this.set this.get this.addon }; Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } Multimap.prototype.addon = function () { this._map this.set this.get this.addon } var mm = new Multimap(); mm._map mm.set mm.get mm.addon} : () => void
>container : () => void

/** @constructor */
var Multimap = function() {
>Multimap : typeof Multimap
>function() { this._map = {}; this._map this.set this.get this.addon } : typeof Multimap

this._map = {};
>this._map = {} : {}
>this._map : {}
>this : Multimap & { set: () => void; get(): void; }
>_map : {}
>{} : {}

this._map
>this._map : {}
>this : Multimap & { set: () => void; get(): void; }
>_map : {}

this.set
>this.set : () => void
>this : Multimap & { set: () => void; get(): void; }
>set : () => void

this.get
>this.get : () => void
>this : Multimap & { set: () => void; get(): void; }
>get : () => void

this.addon
>this.addon : () => void
>this : Multimap & { set: () => void; get(): void; }
>addon : () => void

};

Multimap.prototype = {
>Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } : { set: () => void; get(): void; }
>Multimap.prototype : { set: () => void; get(): void; }
>Multimap : typeof Multimap
>prototype : { set: () => void; get(): void; }
>{ set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon } } : { set: () => void; get(): void; }

set: function() {
>set : () => void
>function() { this._map this.set this.get this.addon } : () => void

this._map
>this._map : {}
>this : Multimap & { set: () => void; get(): void; }
>_map : {}

this.set
>this.set : () => void
>this : Multimap & { set: () => void; get(): void; }
>set : () => void

this.get
>this.get : () => void
>this : Multimap & { set: () => void; get(): void; }
>get : () => void

this.addon
>this.addon : () => void
>this : Multimap & { set: () => void; get(): void; }
>addon : () => void

},
get() {
>get : () => void

this._map
>this._map : {}
>this : Multimap & { set: () => void; get(): void; }
>_map : {}

this.set
>this.set : () => void
>this : Multimap & { set: () => void; get(): void; }
>set : () => void

this.get
>this.get : () => void
>this : Multimap & { set: () => void; get(): void; }
>get : () => void

this.addon
>this.addon : () => void
>this : Multimap & { set: () => void; get(): void; }
>addon : () => void
}
}

Multimap.prototype.addon = function () {
>Multimap.prototype.addon = function () { this._map this.set this.get this.addon } : () => void
>Multimap.prototype.addon : any
>Multimap.prototype : { set: () => void; get(): void; }
>Multimap : typeof Multimap
>prototype : { set: () => void; get(): void; }
>addon : any
>function () { this._map this.set this.get this.addon } : () => void

this._map
>this._map : {}
>this : Multimap & { set: () => void; get(): void; }
>_map : {}

this.set
>this.set : () => void
>this : Multimap & { set: () => void; get(): void; }
>set : () => void

this.get
>this.get : () => void
>this : Multimap & { set: () => void; get(): void; }
>get : () => void

this.addon
>this.addon : () => void
>this : Multimap & { set: () => void; get(): void; }
>addon : () => void
}

var mm = new Multimap();
>mm : Multimap & { set: () => void; get(): void; }
>new Multimap() : Multimap & { set: () => void; get(): void; }
>Multimap : typeof Multimap

mm._map
>mm._map : {}
>mm : Multimap & { set: () => void; get(): void; }
>_map : {}

mm.set
>mm.set : () => void
>mm : Multimap & { set: () => void; get(): void; }
>set : () => void

mm.get
>mm.get : () => void
>mm : Multimap & { set: () => void; get(): void; }
>get : () => void

mm.addon
>mm.addon : () => void
>mm : Multimap & { set: () => void; get(): void; }
>addon : () => void

});

Loading