JS Object literal assignments are declarations

Previously this only worked cross-file because it was a merge. Now it
works anywhere, and locally it is actually binding a new property on the
object literal symbol.
This commit is contained in:
Nathan Shively-Sanders
2017-11-29 11:36:25 -08:00
parent 098a05268a
commit 8bd66a095d
3 changed files with 24 additions and 3 deletions

View File

@@ -2409,7 +2409,7 @@ namespace ts {
function bindPropertyAssignment(functionName: __String, propertyAccess: PropertyAccessExpression, isPrototypeProperty: boolean) {
const symbol = lookupSymbolForName(functionName);
let targetSymbol = symbol && isDeclarationOfFunctionOrClassExpression(symbol) ?
let targetSymbol = symbol && isDeclarationOfJavascriptExpression(symbol) ?
(symbol.valueDeclaration as VariableDeclaration).initializer.symbol :
symbol;
Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement);
@@ -2432,7 +2432,7 @@ namespace ts {
targetSymbol = declareSymbol(container.locals, /*parent*/ undefined, identifier, SymbolFlags.Module, SymbolFlags.ValueModuleExcludes);
}
}
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule))) {
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule | SymbolFlags.ObjectLiteral))) {
return;
}

View File

@@ -14431,6 +14431,10 @@ namespace ts {
let hasComputedStringProperty = false;
let hasComputedNumberProperty = false;
const isInJSFile = isInJavaScriptFile(node);
if (isInJSFile && node.symbol && node.symbol.exports) {
mergeSymbolTable(propertiesTable, node.symbol.exports);
node.symbol.exports.forEach(symbol => propertiesArray.push(symbol));
}
let offset = 0;
for (let i = 0; i < node.properties.length; i++) {

View File

@@ -1441,7 +1441,24 @@ namespace ts {
export function isDeclarationOfFunctionOrClassExpression(s: Symbol) {
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
const declaration = s.valueDeclaration as VariableDeclaration;
return declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression);
return declaration.initializer &&
(declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression);
}
return false;
}
/**
* Returns true if the node is a variable declaration whose initializer is a function or class expression, or an empty object literal.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isDeclarationOfJavascriptExpression(s: Symbol) {
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
const declaration = s.valueDeclaration as VariableDeclaration;
return declaration.initializer &&
(declaration.initializer.kind === SyntaxKind.FunctionExpression ||
declaration.initializer.kind === SyntaxKind.ClassExpression ||
(declaration.initializer.kind === SyntaxKind.ObjectLiteralExpression &&
(declaration.initializer as ObjectLiteralExpression).properties.length === 0));
}
return false;
}