mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 10:00:13 -06:00
Fix late bound method name assignment, added tests (#43344)
* Fix late bound method name assignment, added tests * Refactor bindDynamicallyNamedthisPropertyAssignment * PR comments * Rollback allowJscheck fix
This commit is contained in:
parent
971133d5d0
commit
d0159a8891
@ -410,13 +410,15 @@ namespace ts {
|
||||
* @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.)
|
||||
* @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations.
|
||||
*/
|
||||
function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean): Symbol {
|
||||
Debug.assert(!hasDynamicName(node));
|
||||
function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): Symbol {
|
||||
Debug.assert(isComputedName || !hasDynamicName(node));
|
||||
|
||||
const isDefaultExport = hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node) && node.name.escapedText === "default";
|
||||
|
||||
// The exported symbol for an export default function/class node is always named "default"
|
||||
const name = isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node);
|
||||
const name = isComputedName ? InternalSymbolName.Computed
|
||||
: isDefaultExport && parent ? InternalSymbolName.Default
|
||||
: getDeclarationName(node);
|
||||
|
||||
let symbol: Symbol | undefined;
|
||||
if (name === undefined) {
|
||||
@ -2929,7 +2931,7 @@ namespace ts {
|
||||
constructorSymbol.members = constructorSymbol.members || createSymbolTable();
|
||||
// It's acceptable for multiple 'this' assignments of the same identifier to occur
|
||||
if (hasDynamicName(node)) {
|
||||
bindDynamicallyNamedThisPropertyAssignment(node, constructorSymbol);
|
||||
bindDynamicallyNamedThisPropertyAssignment(node, constructorSymbol, constructorSymbol.members);
|
||||
}
|
||||
else {
|
||||
declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
|
||||
@ -2948,7 +2950,7 @@ namespace ts {
|
||||
const containingClass = thisContainer.parent;
|
||||
const symbolTable = hasSyntacticModifier(thisContainer, ModifierFlags.Static) ? containingClass.symbol.exports! : containingClass.symbol.members!;
|
||||
if (hasDynamicName(node)) {
|
||||
bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol);
|
||||
bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol, symbolTable);
|
||||
}
|
||||
else {
|
||||
declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true);
|
||||
@ -2972,8 +2974,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindDynamicallyNamedThisPropertyAssignment(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol) {
|
||||
bindAnonymousDeclaration(node, SymbolFlags.Property, InternalSymbolName.Computed);
|
||||
function bindDynamicallyNamedThisPropertyAssignment(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol, symbolTable: SymbolTable) {
|
||||
declareSymbol(symbolTable, symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true);
|
||||
addLateBoundAssignmentDeclarationToSymbol(node, symbol);
|
||||
}
|
||||
|
||||
|
||||
@ -10243,7 +10243,7 @@ namespace ts {
|
||||
if (!symbol.declarations) {
|
||||
symbol.declarations = [member];
|
||||
}
|
||||
else {
|
||||
else if(!member.symbol.isReplaceableByMethod) {
|
||||
symbol.declarations.push(member);
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Value) {
|
||||
|
||||
18
tests/baselines/reference/lateBoundMethodNameAssigmentJS.js
Normal file
18
tests/baselines/reference/lateBoundMethodNameAssigmentJS.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [lateBoundMethodNameAssigmentJS.js]
|
||||
const _symbol = Symbol("_sym");
|
||||
export class MyClass {
|
||||
constructor() {
|
||||
this[_symbol] = this[_symbol].bind(this);
|
||||
}
|
||||
|
||||
async [_symbol]() { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
//// [lateBoundMethodNameAssigmentJS.d.ts]
|
||||
export class MyClass {
|
||||
[_symbol]: any;
|
||||
}
|
||||
declare const _symbol: unique symbol;
|
||||
export {};
|
||||
@ -0,0 +1,21 @@
|
||||
=== tests/cases/compiler/lateBoundMethodNameAssigmentJS.js ===
|
||||
const _symbol = Symbol("_sym");
|
||||
>_symbol : Symbol(_symbol, Decl(lateBoundMethodNameAssigmentJS.js, 0, 5))
|
||||
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
|
||||
|
||||
export class MyClass {
|
||||
>MyClass : Symbol(MyClass, Decl(lateBoundMethodNameAssigmentJS.js, 0, 31))
|
||||
|
||||
constructor() {
|
||||
this[_symbol] = this[_symbol].bind(this);
|
||||
>this : Symbol(MyClass, Decl(lateBoundMethodNameAssigmentJS.js, 0, 31))
|
||||
>_symbol : Symbol(_symbol, Decl(lateBoundMethodNameAssigmentJS.js, 0, 5))
|
||||
>this : Symbol(MyClass, Decl(lateBoundMethodNameAssigmentJS.js, 0, 31))
|
||||
>_symbol : Symbol(_symbol, Decl(lateBoundMethodNameAssigmentJS.js, 0, 5))
|
||||
>this : Symbol(MyClass, Decl(lateBoundMethodNameAssigmentJS.js, 0, 31))
|
||||
}
|
||||
|
||||
async [_symbol]() { }
|
||||
>[_symbol] : Symbol(MyClass[_symbol], Decl(lateBoundMethodNameAssigmentJS.js, 4, 5))
|
||||
>_symbol : Symbol(_symbol, Decl(lateBoundMethodNameAssigmentJS.js, 0, 5))
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
=== tests/cases/compiler/lateBoundMethodNameAssigmentJS.js ===
|
||||
const _symbol = Symbol("_sym");
|
||||
>_symbol : unique symbol
|
||||
>Symbol("_sym") : unique symbol
|
||||
>Symbol : SymbolConstructor
|
||||
>"_sym" : "_sym"
|
||||
|
||||
export class MyClass {
|
||||
>MyClass : MyClass
|
||||
|
||||
constructor() {
|
||||
this[_symbol] = this[_symbol].bind(this);
|
||||
>this[_symbol] = this[_symbol].bind(this) : error
|
||||
>this[_symbol] : error
|
||||
>this : this
|
||||
>_symbol : unique symbol
|
||||
>this[_symbol].bind(this) : error
|
||||
>this[_symbol].bind : error
|
||||
>this[_symbol] : any
|
||||
>this : this
|
||||
>_symbol : unique symbol
|
||||
>bind : any
|
||||
>this : this
|
||||
}
|
||||
|
||||
async [_symbol]() { }
|
||||
>[_symbol] : error
|
||||
>_symbol : unique symbol
|
||||
}
|
||||
15
tests/cases/compiler/lateBoundMethodNameAssigmentJS.ts
Normal file
15
tests/cases/compiler/lateBoundMethodNameAssigmentJS.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @emitDeclarationOnly: true
|
||||
// @strict: true
|
||||
// @target: es6
|
||||
// @declaration: true
|
||||
// @filename: lateBoundMethodNameAssigmentJS.js
|
||||
const _symbol = Symbol("_sym");
|
||||
export class MyClass {
|
||||
constructor() {
|
||||
this[_symbol] = this[_symbol].bind(this);
|
||||
}
|
||||
|
||||
async [_symbol]() { }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user