diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index be07402ff13..243b442407b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2399,18 +2399,14 @@ namespace ts { } function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) { - // Look up the property in the local scope, since property assignments should follow the declaration let symbol = getJSInitializerSymbol(lookupSymbolForPropertyAccess(name)); - Debug.assert(propertyAccess.parent.kind === SyntaxKind.BinaryExpression || - propertyAccess.parent.kind === SyntaxKind.ExpressionStatement || - propertyAccess.parent.kind === SyntaxKind.PropertyAccessExpression); const isToplevelNamespaceableInitializer = isBinaryExpression(propertyAccess.parent) ? propertyAccess.parent.parent.parent.kind === SyntaxKind.SourceFile && getJavascriptInitializer(propertyAccess.parent.right) : propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; if (!isPrototypeProperty && (!symbol || !(symbol.flags & SymbolFlags.Namespace)) && isToplevelNamespaceableInitializer) { + // make symbols or add declarations for intermediate containers const flags = SymbolFlags.Module | SymbolFlags.JSContainer; const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer; - // make symbols are add declarations for intermediate containers forEachIdentifierInEntityName(propertyAccess.expression, (id, original) => { if (original) { // Note: add declaration to original symbol, not the special-syntax's symbol, so that namespaces work for type lookup @@ -2457,8 +2453,7 @@ namespace ts { } else { const s = getJSInitializerSymbol(forEachIdentifierInEntityName(e.expression, action)); - Debug.assert(!!s, "lost the chant"); - Debug.assert(!!s.exports, "has no exports"); + Debug.assert(!!s && !!s.exports); return action(e.name, s.exports.get(e.name.escapedText)); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fc1dad1cc0..2604bec3dbd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -858,11 +858,10 @@ namespace ts { mergeSymbolTable(target.exports, source.exports); } if ((source.flags | target.flags) & SymbolFlags.JSContainer) { - const fs = getJSInitializerSymbol(source); - const ft = getJSInitializerSymbol(target); - if (fs !== source || ft !== target) { - // also follow the source's valueDeclaration and merge its symbol - mergeSymbol(getJSInitializerSymbol(target), getJSInitializerSymbol(source)); + const sourceInitializer = getJSInitializerSymbol(source); + const targetInitializer = getJSInitializerSymbol(target); + if (sourceInitializer !== source || targetInitializer !== target) { + mergeSymbol(targetInitializer, sourceInitializer); } } recordMergedSymbol(target, source); @@ -4174,7 +4173,7 @@ namespace ts { } function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol: Symbol) { - // function/class/{} assignments are fresh declarations, not property assignments: + // function/class/{} assignments are fresh declarations, not property assignments, so return immediately const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); @@ -4392,6 +4391,7 @@ namespace ts { || isIdentifier(declaration) || (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration)) || isMethodSignature(declaration)) { + // 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); @@ -14758,10 +14758,10 @@ namespace ts { let spread: Type = emptyObjectType; let propagatedFlags: TypeFlags = TypeFlags.FreshLiteral; - const isInJSFile = isInJavaScriptFile(node); const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); + const isInJSFile = isInJavaScriptFile(node); const isJSObjectLiteral = !contextualType && isInJSFile; let typeFlags: TypeFlags = 0; let patternWithComputedProperties = false; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5cc23dcc2a0..9d36656fb2d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1512,15 +1512,15 @@ namespace ts { const e = skipParentheses(initializer.expression); return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined; } - if(initializer.kind === SyntaxKind.FunctionExpression || - initializer.kind === SyntaxKind.ClassExpression || - isObjectLiteralExpression(initializer) && initializer.properties.length === 0) { + if (initializer.kind === SyntaxKind.FunctionExpression || + initializer.kind === SyntaxKind.ClassExpression || + isObjectLiteralExpression(initializer) && initializer.properties.length === 0) { return initializer; } } function getDefaultedJavascriptInitializer(name: EntityNameExpression, initializer: Expression) { - const e = isBinaryExpression(initializer) && getJavascriptInitializer(initializer.right) + const e = isBinaryExpression(initializer) && getJavascriptInitializer(initializer.right); if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) { return e; }