@@ -2860,7 +2860,7 @@ namespace ts {
2860
2860
}
2861
2861
2862
2862
function getExportsOfSymbol(symbol: Symbol): SymbolTable {
2863
- return symbol.flags & SymbolFlags.Class ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) :
2863
+ return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) :
2864
2864
symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) :
2865
2865
symbol.exports || emptySymbols;
2866
2866
}
@@ -4224,7 +4224,15 @@ namespace ts {
4224
4224
if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late) {
4225
4225
const decl = first(propertySymbol.declarations);
4226
4226
if (hasLateBindableName(decl)) {
4227
- trackComputedName(decl.name, saveEnclosingDeclaration, context);
4227
+ if (isBinaryExpression(decl)) {
4228
+ const name = getNameOfDeclaration(decl);
4229
+ if (name && isElementAccessExpression(name) && isPropertyAccessEntityNameExpression(name.argumentExpression)) {
4230
+ trackComputedName(name.argumentExpression, saveEnclosingDeclaration, context);
4231
+ }
4232
+ }
4233
+ else {
4234
+ trackComputedName(decl.name.expression, saveEnclosingDeclaration, context);
4235
+ }
4228
4236
}
4229
4237
}
4230
4238
const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
@@ -4440,7 +4448,7 @@ namespace ts {
4440
4448
return <BindingName>elideInitializerAndSetEmitFlags(node);
4441
4449
function elideInitializerAndSetEmitFlags(node: Node): Node {
4442
4450
if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
4443
- trackComputedName(node, context.enclosingDeclaration, context);
4451
+ trackComputedName(node.expression , context.enclosingDeclaration, context);
4444
4452
}
4445
4453
const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!;
4446
4454
const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited);
@@ -4452,10 +4460,10 @@ namespace ts {
4452
4460
}
4453
4461
}
4454
4462
4455
- function trackComputedName(node: LateBoundName , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
4463
+ function trackComputedName(accessExpression: EntityNameOrEntityNameExpression , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
4456
4464
if (!context.tracker.trackSymbol) return;
4457
4465
// get symbol of the first identifier of the entityName
4458
- const firstIdentifier = getFirstIdentifier(node.expression );
4466
+ const firstIdentifier = getFirstIdentifier(accessExpression );
4459
4467
const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
4460
4468
if (name) {
4461
4469
context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value);
@@ -7182,8 +7190,10 @@ namespace ts {
7182
7190
if (declaration.kind === SyntaxKind.ExportAssignment) {
7183
7191
type = widenTypeForVariableLikeDeclaration(checkExpressionCached((<ExportAssignment>declaration).expression), declaration);
7184
7192
}
7185
- else if (isInJSFile(declaration) &&
7186
- (isCallExpression(declaration) || isBinaryExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent))) {
7193
+ else if (
7194
+ isBinaryExpression(declaration) ||
7195
+ (isInJSFile(declaration) &&
7196
+ (isCallExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent)))) {
7187
7197
type = getWidenedTypeForAssignmentDeclaration(symbol);
7188
7198
}
7189
7199
else if (isJSDocPropertyLikeTag(declaration)
@@ -8201,9 +8211,12 @@ namespace ts {
8201
8211
* - The type of its expression is a string or numeric literal type, or is a `unique symbol` type.
8202
8212
*/
8203
8213
function isLateBindableName(node: DeclarationName): node is LateBoundName {
8204
- return isComputedPropertyName(node)
8205
- && isEntityNameExpression(node.expression)
8206
- && isTypeUsableAsPropertyName(checkComputedPropertyName(node));
8214
+ if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) {
8215
+ return false;
8216
+ }
8217
+ const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression;
8218
+ return isEntityNameExpression(expr)
8219
+ && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr));
8207
8220
}
8208
8221
8209
8222
function isLateBoundName(name: __String): boolean {
@@ -8215,7 +8228,7 @@ namespace ts {
8215
8228
/**
8216
8229
* Indicates whether a declaration has a late-bindable dynamic name.
8217
8230
*/
8218
- function hasLateBindableName(node: Declaration): node is LateBoundDeclaration {
8231
+ function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration {
8219
8232
const name = getNameOfDeclaration(node);
8220
8233
return !!name && isLateBindableName(name);
8221
8234
}
@@ -8252,7 +8265,7 @@ namespace ts {
8252
8265
* late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound
8253
8266
* members.
8254
8267
*/
8255
- function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration, symbolFlags: SymbolFlags) {
8268
+ function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression , symbolFlags: SymbolFlags) {
8256
8269
Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol.");
8257
8270
symbol.flags |= symbolFlags;
8258
8271
getSymbolLinks(member.symbol).lateSymbol = symbol;
@@ -8297,14 +8310,15 @@ namespace ts {
8297
8310
* @param lateSymbols The late-bound symbols of the parent.
8298
8311
* @param decl The member to bind.
8299
8312
*/
8300
- function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration) {
8313
+ function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: SymbolTable, decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration ) {
8301
8314
Debug.assert(!!decl.symbol, "The member is expected to have a symbol.");
8302
8315
const links = getNodeLinks(decl);
8303
8316
if (!links.resolvedSymbol) {
8304
8317
// In the event we attempt to resolve the late-bound name of this member recursively,
8305
8318
// fall back to the early-bound name of this member.
8306
8319
links.resolvedSymbol = decl.symbol;
8307
- const type = checkComputedPropertyName(decl.name);
8320
+ const declName = isBinaryExpression(decl) ? decl.left : decl.name;
8321
+ const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName);
8308
8322
if (isTypeUsableAsPropertyName(type)) {
8309
8323
const memberName = getPropertyNameFromType(type);
8310
8324
const symbolFlags = decl.symbol.flags;
@@ -8321,9 +8335,9 @@ namespace ts {
8321
8335
// If we have an existing early-bound member, combine its declarations so that we can
8322
8336
// report an error at each declaration.
8323
8337
const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations;
8324
- const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(decl.name );
8338
+ const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(declName );
8325
8339
forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name));
8326
- error(decl.name || decl, Diagnostics.Duplicate_property_0, name);
8340
+ error(declName || decl, Diagnostics.Duplicate_property_0, name);
8327
8341
lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late);
8328
8342
}
8329
8343
lateSymbol.nameType = type;
@@ -8365,6 +8379,20 @@ namespace ts {
8365
8379
}
8366
8380
}
8367
8381
}
8382
+ const assignments = symbol.assignmentDeclarationMembers;
8383
+ if (assignments) {
8384
+ const decls = arrayFrom(assignments.values());
8385
+ for (const member of decls) {
8386
+ const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression);
8387
+ const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty
8388
+ || assignmentKind === AssignmentDeclarationKind.ThisProperty
8389
+ || assignmentKind === AssignmentDeclarationKind.ObjectDefinePrototypeProperty
8390
+ || assignmentKind === AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name
8391
+ if (isStatic === !isInstanceMember && hasLateBindableName(member)) {
8392
+ lateBindMember(symbol, earlySymbols, lateSymbols, member);
8393
+ }
8394
+ }
8395
+ }
8368
8396
8369
8397
links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols;
8370
8398
}
0 commit comments