mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Support var x = x || {} declarations in JS
This commit is contained in:
@@ -2407,8 +2407,8 @@ namespace ts {
|
||||
|
||||
function bindPropertyAssignment(functionName: __String, propertyAccess: PropertyAccessExpression, isPrototypeProperty: boolean) {
|
||||
const symbol = lookupSymbolForName(functionName);
|
||||
let targetSymbol = symbol && isDeclarationOfJavascriptExpression(symbol) ?
|
||||
(symbol.valueDeclaration as VariableDeclaration).initializer.symbol :
|
||||
let targetSymbol = symbol && isDeclarationOfJavascriptContainerExpression(symbol) ? (symbol.valueDeclaration as VariableDeclaration).initializer.symbol :
|
||||
symbol && isDeclarationOfDefaultedJavascriptContainerExpression(symbol) ? ((symbol.valueDeclaration as VariableDeclaration).initializer as BinaryExpression).right.symbol :
|
||||
symbol;
|
||||
Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || propertyAccess.parent.kind === SyntaxKind.ExpressionStatement);
|
||||
let isLegalPosition: boolean;
|
||||
|
||||
+11
-4
@@ -4359,6 +4359,10 @@ namespace ts {
|
||||
if (isInJavaScriptFile(declaration) && isJSDocPropertyLikeTag(declaration) && declaration.typeExpression) {
|
||||
return links.type = getTypeFromTypeNode(declaration.typeExpression.type);
|
||||
}
|
||||
if (isInJavaScriptFile(declaration) && isDeclarationOfDefaultedJavascriptContainerExpression(symbol)) {
|
||||
// !!! (probably out of place, probably not the right function to call)
|
||||
return links.type = checkExpression(((declaration as VariableDeclaration).initializer as BinaryExpression).right);
|
||||
}
|
||||
// Handle variable, parameter or property
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
@@ -4379,7 +4383,7 @@ namespace ts {
|
||||
|| isIdentifier(declaration)
|
||||
|| (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration))
|
||||
|| isMethodSignature(declaration)) {
|
||||
|
||||
// TODO: Might need to add a case here?
|
||||
// Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty`
|
||||
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
return getTypeOfFuncClassEnumModule(symbol);
|
||||
@@ -14744,15 +14748,18 @@ namespace ts {
|
||||
let spread: Type = emptyObjectType;
|
||||
let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral;
|
||||
|
||||
const contextualType = getApparentTypeOfContextualType(node);
|
||||
const isInJSFile = isInJavaScriptFile(node);
|
||||
// TODO: Might need to skip if isDeclarationOfDefaultedJavascriptContainerExpression(node.parent.parent) instead of just checking node.properties.length > 0
|
||||
// (actually, it would be better not to skip contextual typing at all, but to do that I need to avoid the checking loop another way)
|
||||
const contextualType = node.properties.length > 0 && getApparentTypeOfContextualType(node);
|
||||
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
||||
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
|
||||
const isJSObjectLiteral = !contextualType && isInJavaScriptFile(node);
|
||||
const isJSObjectLiteral = !contextualType && isInJSFile;
|
||||
let typeFlags: TypeFlags = 0;
|
||||
let patternWithComputedProperties = false;
|
||||
let hasComputedStringProperty = false;
|
||||
let hasComputedNumberProperty = false;
|
||||
const isInJSFile = isInJavaScriptFile(node);
|
||||
// TODO: This seems like the wrong way to put the assignment-properties into the type (especially the manual call to mergeSymbolTable)
|
||||
if (isInJSFile && node.symbol && node.symbol.exports) {
|
||||
mergeSymbolTable(propertiesTable, node.symbol.exports);
|
||||
node.symbol.exports.forEach(symbol => propertiesArray.push(symbol));
|
||||
|
||||
@@ -1489,14 +1489,29 @@ namespace ts {
|
||||
* 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));
|
||||
export function isDeclarationOfJavascriptContainerExpression(s: Symbol) {
|
||||
if (s.valueDeclaration && isVariableDeclaration(s.valueDeclaration)) {
|
||||
return isVariableDeclaration(s.valueDeclaration) && isJavascriptContainerExpression(s.valueDeclaration.initializer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isJavascriptContainerExpression(expression: Expression | undefined) {
|
||||
return expression &&
|
||||
(expression.kind === SyntaxKind.FunctionExpression ||
|
||||
expression.kind === SyntaxKind.ClassExpression ||
|
||||
isObjectLiteralExpression(expression) && expression.properties.length === 0)
|
||||
}
|
||||
|
||||
export function isDeclarationOfDefaultedJavascriptContainerExpression(s: Symbol) {
|
||||
if (s.valueDeclaration && isVariableDeclaration(s.valueDeclaration)) {
|
||||
return s.valueDeclaration.initializer &&
|
||||
isBinaryExpression(s.valueDeclaration.initializer) &&
|
||||
isIdentifier(s.valueDeclaration.initializer.left) &&
|
||||
isIdentifier(s.valueDeclaration.name) &&
|
||||
s.valueDeclaration.initializer.left.escapedText === s.valueDeclaration.name.escapedText &&
|
||||
isObjectLiteralExpression(s.valueDeclaration.initializer.right) &&
|
||||
s.valueDeclaration.initializer.right.properties.length === 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user