@@ -2860,7 +2860,7 @@ namespace ts {
28602860 }
28612861
28622862 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) :
28642864 symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) :
28652865 symbol.exports || emptySymbols;
28662866 }
@@ -4224,7 +4224,15 @@ namespace ts {
42244224 if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late) {
42254225 const decl = first(propertySymbol.declarations);
42264226 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+ }
42284236 }
42294237 }
42304238 const propertyName = symbolToName(propertySymbol, context, SymbolFlags.Value, /*expectsIdentifier*/ true);
@@ -4440,7 +4448,7 @@ namespace ts {
44404448 return <BindingName>elideInitializerAndSetEmitFlags(node);
44414449 function elideInitializerAndSetEmitFlags(node: Node): Node {
44424450 if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) {
4443- trackComputedName(node, context.enclosingDeclaration, context);
4451+ trackComputedName(node.expression , context.enclosingDeclaration, context);
44444452 }
44454453 const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!;
44464454 const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited);
@@ -4452,10 +4460,10 @@ namespace ts {
44524460 }
44534461 }
44544462
4455- function trackComputedName(node: LateBoundName , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
4463+ function trackComputedName(accessExpression: EntityNameOrEntityNameExpression , enclosingDeclaration: Node | undefined, context: NodeBuilderContext) {
44564464 if (!context.tracker.trackSymbol) return;
44574465 // get symbol of the first identifier of the entityName
4458- const firstIdentifier = getFirstIdentifier(node.expression );
4466+ const firstIdentifier = getFirstIdentifier(accessExpression );
44594467 const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true);
44604468 if (name) {
44614469 context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value);
@@ -7182,8 +7190,10 @@ namespace ts {
71827190 if (declaration.kind === SyntaxKind.ExportAssignment) {
71837191 type = widenTypeForVariableLikeDeclaration(checkExpressionCached((<ExportAssignment>declaration).expression), declaration);
71847192 }
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)))) {
71877197 type = getWidenedTypeForAssignmentDeclaration(symbol);
71887198 }
71897199 else if (isJSDocPropertyLikeTag(declaration)
@@ -8201,9 +8211,12 @@ namespace ts {
82018211 * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type.
82028212 */
82038213 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));
82078220 }
82088221
82098222 function isLateBoundName(name: __String): boolean {
@@ -8215,7 +8228,7 @@ namespace ts {
82158228 /**
82168229 * Indicates whether a declaration has a late-bindable dynamic name.
82178230 */
8218- function hasLateBindableName(node: Declaration): node is LateBoundDeclaration {
8231+ function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration {
82198232 const name = getNameOfDeclaration(node);
82208233 return !!name && isLateBindableName(name);
82218234 }
@@ -8252,7 +8265,7 @@ namespace ts {
82528265 * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound
82538266 * members.
82548267 */
8255- function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration, symbolFlags: SymbolFlags) {
8268+ function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression , symbolFlags: SymbolFlags) {
82568269 Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol.");
82578270 symbol.flags |= symbolFlags;
82588271 getSymbolLinks(member.symbol).lateSymbol = symbol;
@@ -8297,14 +8310,15 @@ namespace ts {
82978310 * @param lateSymbols The late-bound symbols of the parent.
82988311 * @param decl The member to bind.
82998312 */
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 ) {
83018314 Debug.assert(!!decl.symbol, "The member is expected to have a symbol.");
83028315 const links = getNodeLinks(decl);
83038316 if (!links.resolvedSymbol) {
83048317 // In the event we attempt to resolve the late-bound name of this member recursively,
83058318 // fall back to the early-bound name of this member.
83068319 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);
83088322 if (isTypeUsableAsPropertyName(type)) {
83098323 const memberName = getPropertyNameFromType(type);
83108324 const symbolFlags = decl.symbol.flags;
@@ -8321,9 +8335,9 @@ namespace ts {
83218335 // If we have an existing early-bound member, combine its declarations so that we can
83228336 // report an error at each declaration.
83238337 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 );
83258339 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);
83278341 lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late);
83288342 }
83298343 lateSymbol.nameType = type;
@@ -8365,6 +8379,20 @@ namespace ts {
83658379 }
83668380 }
83678381 }
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+ }
83688396
83698397 links[resolutionKind] = combineSymbolTables(earlySymbols, lateSymbols) || emptySymbols;
83708398 }
0 commit comments