@@ -2817,7 +2817,7 @@ namespace ts {
2817
2817
}
2818
2818
2819
2819
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
2820
- return symbol.flags & SymbolFlags.Class ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) :
2820
+ return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) :
2821
2821
symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) :
2822
2822
symbol.exports || emptySymbols;
2823
2823
}
@@ -4118,7 +4118,15 @@ namespace ts {
4118
4118
if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late) {
4119
4119
const decl = first(propertySymbol.declarations);
4120
4120
if (hasLateBindableName(decl)) {
4121
- trackComputedName(decl.name, saveEnclosingDeclaration, context);
4121
+ if (!isBinaryExpression(decl)) {
4122
+ trackComputedName(decl.name.expression, saveEnclosingDeclaration, context);
4123
+ }
4124
+ else {
4125
+ const name = getNameOfDeclaration(decl);
4126
+ if (name && isElementAccessExpression(name) && isPropertyAccessEntityNameExpression(name.argumentExpression)) {
4127
+ trackComputedName(name.argumentExpression, saveEnclosingDeclaration, context);
4128
+ }
4129
+ }
4122
4130
}
4123
4131
}
4124
4132
const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
@@ -4324,7 +4332,7 @@ namespace ts {
4324
4332
return <BindingName>elideInitializerAndSetEmitFlags(node);
4325
4333
function elideInitializerAndSetEmitFlags(node: Node): Node {
4326
4334
if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
4327
- trackComputedName(node, context.enclosingDeclaration, context);
4335
+ trackComputedName(node.expression , context.enclosingDeclaration, context);
4328
4336
}
4329
4337
const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!;
4330
4338
const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited);
@@ -4336,10 +4344,10 @@ namespace ts {
4336
4344
}
4337
4345
}
4338
4346
4339
- function trackComputedName(node: LateBoundName , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
4347
+ function trackComputedName(accessExpression: EntityNameOrEntityNameExpression , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
4340
4348
if (!context.tracker.trackSymbol) return;
4341
4349
// get symbol of the first identifier of the entityName
4342
- const firstIdentifier = getFirstIdentifier(node.expression );
4350
+ const firstIdentifier = getFirstIdentifier(accessExpression );
4343
4351
const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
4344
4352
if (name) {
4345
4353
context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value);
@@ -5831,6 +5839,9 @@ namespace ts {
5831
5839
if (declaration.kind === SyntaxKind.ExportAssignment) {
5832
5840
type = widenTypeForVariableLikeDeclaration(checkExpressionCached((<ExportAssignment>declaration).expression), declaration);
5833
5841
}
5842
+ else if (isBinaryExpression(declaration)) {
5843
+ type = getWidenedTypeForAssignmentDeclaration(symbol);
5844
+ }
5834
5845
else if (isInJSFile(declaration) &&
5835
5846
(isCallExpression(declaration) || isBinaryExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent))) {
5836
5847
type = getWidenedTypeForAssignmentDeclaration(symbol);
@@ -6836,9 +6847,12 @@ namespace ts {
6836
6847
* - The type of its expression is a string or numeric literal type, or is a `unique symbol` type.
6837
6848
*/
6838
6849
function isLateBindableName(node: DeclarationName): node is LateBoundName {
6839
- return isComputedPropertyName(node)
6840
- && isEntityNameExpression(node.expression)
6841
- && isTypeUsableAsPropertyName(checkComputedPropertyName(node));
6850
+ if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
6851
+ return false;
6852
+ }
6853
+ const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
6854
+ return isEntityNameExpression(expr)
6855
+ && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr));
6842
6856
}
6843
6857
6844
6858
function isLateBoundName(name: __String): boolean {
@@ -6850,7 +6864,7 @@ namespace ts {
6850
6864
/**
6851
6865
* Indicates whether a declaration has a late-bindable dynamic name.
6852
6866
*/
6853
- function hasLateBindableName(node: Declaration): node is LateBoundDeclaration {
6867
+ function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | BinaryExpression {
6854
6868
const name = getNameOfDeclaration(node);
6855
6869
return !!name && isLateBindableName(name);
6856
6870
}
@@ -6887,7 +6901,7 @@ namespace ts {
6887
6901
* late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound
6888
6902
* members.
6889
6903
*/
6890
- function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration, symbolFlags: SymbolFlags) {
6904
+ function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression , symbolFlags: SymbolFlags) {
6891
6905
Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol.");
6892
6906
symbol.flags |= symbolFlags;
6893
6907
getSymbolLinks(member.symbol).lateSymbol = symbol;
@@ -6932,14 +6946,15 @@ namespace ts {
6932
6946
* @param lateSymbols The late-bound symbols of the parent.
6933
6947
* @param decl The member to bind.
6934
6948
*/
6935
- function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration) {
6949
+ function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration | BinaryExpression ) {
6936
6950
Debug.assert(!!decl.symbol, "The member is expected to have a symbol.");
6937
6951
const links = getNodeLinks(decl);
6938
6952
if (!links.resolvedSymbol) {
6939
6953
// In the event we attempt to resolve the late-bound name of this member recursively,
6940
6954
// fall back to the early-bound name of this member.
6941
6955
links.resolvedSymbol = decl.symbol;
6942
- const type = checkComputedPropertyName(decl.name);
6956
+ const declName = isBinaryExpression(decl) ? (getNameOfDeclaration(decl) as ElementAccessExpression) : decl.name;
6957
+ const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName);
6943
6958
if (isTypeUsableAsPropertyName(type)) {
6944
6959
const memberName = getPropertyNameFromType(type);
6945
6960
const symbolFlags = decl.symbol.flags;
@@ -6956,9 +6971,9 @@ namespace ts {
6956
6971
// If we have an existing early-bound member, combine its declarations so that we can
6957
6972
// report an error at each declaration.
6958
6973
const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations;
6959
- const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(decl.name );
6974
+ const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(declName );
6960
6975
forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name));
6961
- error(decl.name || decl, Diagnostics.Duplicate_property_0, name);
6976
+ error(declName || decl, Diagnostics.Duplicate_property_0, name);
6962
6977
lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late);
6963
6978
}
6964
6979
lateSymbol.nameType = type;
@@ -7000,6 +7015,20 @@ namespace ts {
7000
7015
}
7001
7016
}
7002
7017
}
7018
+ const assignments = symbol.assignmentDeclarationMembers;
7019
+ if (assignments) {
7020
+ const decls = arrayFrom(assignments.values());
7021
+ for (const member of decls) {
7022
+ const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression);
7023
+ const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty
7024
+ || assignmentKind === AssignmentDeclarationKind.ThisProperty
7025
+ || assignmentKind === AssignmentDeclarationKind.ObjectDefinePrototypeProperty
7026
+ || assignmentKind === AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name
7027
+ if (isStatic === !isInstanceMember && hasLateBindableName(member)) {
7028
+ lateBindMember(symbol, earlySymbols, lateSymbols, member);
7029
+ }
7030
+ }
7031
+ }
7003
7032
7004
7033
links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols;
7005
7034
}
0 commit comments