Skip to content

Commit ec2f967

Browse files
committed
Merge branch 'master' into ownJsonParsing
2 parents c97b389 + 687ab54 commit ec2f967

File tree

78 files changed

+2765
-334
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+2765
-334
lines changed

src/compiler/checker.ts

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ namespace ts {
211211
return tryFindAmbientModule(moduleName, /*withAugmentations*/ false);
212212
},
213213
getApparentType,
214+
getAllPossiblePropertiesOfType,
214215
getSuggestionForNonexistentProperty,
215216
getSuggestionForNonexistentSymbol,
216217
getBaseConstraintOfType,
@@ -690,10 +691,6 @@ namespace ts {
690691
return type.flags & TypeFlags.Object ? (<ObjectType>type).objectFlags : 0;
691692
}
692693

693-
function getCheckFlags(symbol: Symbol): CheckFlags {
694-
return symbol.flags & SymbolFlags.Transient ? (<TransientSymbol>symbol).checkFlags : 0;
695-
}
696-
697694
function isGlobalSourceFile(node: Node) {
698695
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
699696
}
@@ -743,7 +740,8 @@ namespace ts {
743740
const useFile = getSourceFileOfNode(usage);
744741
if (declarationFile !== useFile) {
745742
if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) ||
746-
(!compilerOptions.outFile && !compilerOptions.out)) {
743+
(!compilerOptions.outFile && !compilerOptions.out) ||
744+
isInAmbientContext(declaration)) {
747745
// nodes are in different files and order cannot be determined
748746
return true;
749747
}
@@ -1288,7 +1286,7 @@ namespace ts {
12881286
else if (result.flags & SymbolFlags.Class) {
12891287
error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
12901288
}
1291-
else if (result.flags & SymbolFlags.Enum) {
1289+
else if (result.flags & SymbolFlags.RegularEnum) {
12921290
error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
12931291
}
12941292
}
@@ -4163,6 +4161,7 @@ namespace ts {
41634161
const types: Type[] = [];
41644162
let definedInConstructor = false;
41654163
let definedInMethod = false;
4164+
let jsDocType: Type;
41664165
for (const declaration of symbol.declarations) {
41674166
const expression = declaration.kind === SyntaxKind.BinaryExpression ? <BinaryExpression>declaration :
41684167
declaration.kind === SyntaxKind.PropertyAccessExpression ? <BinaryExpression>getAncestor(declaration, SyntaxKind.BinaryExpression) :
@@ -4181,19 +4180,26 @@ namespace ts {
41814180
}
41824181
}
41834182

4184-
if (expression.flags & NodeFlags.JavaScriptFile) {
4185-
// If there is a JSDoc type, use it
4186-
const type = getTypeForDeclarationFromJSDocComment(expression.parent);
4187-
if (type && type !== unknownType) {
4188-
types.push(getWidenedType(type));
4189-
continue;
4183+
// If there is a JSDoc type, use it
4184+
const type = getTypeForDeclarationFromJSDocComment(expression.parent);
4185+
if (type) {
4186+
const declarationType = getWidenedType(type);
4187+
if (!jsDocType) {
4188+
jsDocType = declarationType;
4189+
}
4190+
else if (jsDocType !== unknownType && declarationType !== unknownType && !isTypeIdenticalTo(jsDocType, declarationType)) {
4191+
const name = getNameOfDeclaration(declaration);
4192+
error(name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(name), typeToString(jsDocType), typeToString(declarationType));
41904193
}
41914194
}
4192-
4193-
types.push(getWidenedLiteralType(checkExpressionCached(expression.right)));
4195+
else if (!jsDocType) {
4196+
// If we don't have an explicit JSDoc type, get the type from the expression.
4197+
types.push(getWidenedLiteralType(checkExpressionCached(expression.right)));
4198+
}
41944199
}
41954200

4196-
return getWidenedType(addOptionality(getUnionType(types, /*subtypeReduction*/ true), definedInMethod && !definedInConstructor));
4201+
const type = jsDocType || getUnionType(types, /*subtypeReduction*/ true);
4202+
return getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor));
41974203
}
41984204

41994205
// Return the type implied by a binding pattern element. This is the type of the initializer of the element if
@@ -5692,6 +5698,22 @@ namespace ts {
56925698
getPropertiesOfObjectType(type);
56935699
}
56945700

5701+
function getAllPossiblePropertiesOfType(type: Type): Symbol[] {
5702+
if (type.flags & TypeFlags.Union) {
5703+
const props = createMap<Symbol>();
5704+
for (const memberType of (type as UnionType).types) {
5705+
for (const { name } of getPropertiesOfType(memberType)) {
5706+
if (!props.has(name)) {
5707+
props.set(name, createUnionOrIntersectionProperty(type as UnionType, name));
5708+
}
5709+
}
5710+
}
5711+
return arrayFrom(props.values());
5712+
} else {
5713+
return getPropertiesOfType(type);
5714+
}
5715+
}
5716+
56955717
function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
56965718
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) :
56975719
type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(<IndexedAccessType>type) :
@@ -12760,7 +12782,7 @@ namespace ts {
1276012782
* @param node the expression whose contextual type will be returned.
1276112783
* @returns the contextual type of an expression.
1276212784
*/
12763-
function getContextualType(node: Expression): Type {
12785+
function getContextualType(node: Expression): Type | undefined {
1276412786
if (isInsideWithStatementBody(node)) {
1276512787
// We cannot answer semantic questions within a with block, do not proceed any further
1276612788
return undefined;
@@ -13234,7 +13256,7 @@ namespace ts {
1323413256
}
1323513257
return result;
1323613258
}
13237-
}
13259+
}
1323813260

1323913261
function isValidSpreadType(type: Type): boolean {
1324013262
return !!(type.flags & (TypeFlags.Any | TypeFlags.Null | TypeFlags.Undefined | TypeFlags.NonPrimitive) ||
@@ -13554,6 +13576,20 @@ namespace ts {
1355413576
return _jsxElementChildrenPropertyName;
1355513577
}
1355613578

13579+
function getApparentTypeOfJsxPropsType(propsType: Type): Type {
13580+
if (!propsType) {
13581+
return undefined;
13582+
}
13583+
if (propsType.flags & TypeFlags.Intersection) {
13584+
const propsApparentType: Type[] = [];
13585+
for (const t of (<UnionOrIntersectionType>propsType).types) {
13586+
propsApparentType.push(getApparentType(t));
13587+
}
13588+
return getIntersectionType(propsApparentType);
13589+
}
13590+
return getApparentType(propsType);
13591+
}
13592+
1355713593
/**
1355813594
* Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component.
1355913595
* Return only attributes type of successfully resolved call signature.
@@ -13574,6 +13610,7 @@ namespace ts {
1357413610
if (callSignature !== unknownSignature) {
1357513611
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
1357613612
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
13613+
paramType = getApparentTypeOfJsxPropsType(paramType);
1357713614
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
1357813615
// Intersect in JSX.IntrinsicAttributes if it exists
1357913616
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
@@ -13611,7 +13648,8 @@ namespace ts {
1361113648
let allMatchingAttributesType: Type;
1361213649
for (const candidate of candidatesOutArray) {
1361313650
const callReturnType = getReturnTypeOfSignature(candidate);
13614-
const paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0]));
13651+
let paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0]));
13652+
paramType = getApparentTypeOfJsxPropsType(paramType);
1361513653
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
1361613654
let shouldBeCandidate = true;
1361713655
for (const attribute of openingLikeElement.attributes.properties) {
@@ -14011,25 +14049,6 @@ namespace ts {
1401114049
return s.valueDeclaration ? s.valueDeclaration.kind : SyntaxKind.PropertyDeclaration;
1401214050
}
1401314051

14014-
function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags {
14015-
if (s.valueDeclaration) {
14016-
const flags = getCombinedModifierFlags(s.valueDeclaration);
14017-
return s.parent && s.parent.flags & SymbolFlags.Class ? flags : flags & ~ModifierFlags.AccessibilityModifier;
14018-
}
14019-
if (getCheckFlags(s) & CheckFlags.Synthetic) {
14020-
const checkFlags = (<TransientSymbol>s).checkFlags;
14021-
const accessModifier = checkFlags & CheckFlags.ContainsPrivate ? ModifierFlags.Private :
14022-
checkFlags & CheckFlags.ContainsPublic ? ModifierFlags.Public :
14023-
ModifierFlags.Protected;
14024-
const staticModifier = checkFlags & CheckFlags.ContainsStatic ? ModifierFlags.Static : 0;
14025-
return accessModifier | staticModifier;
14026-
}
14027-
if (s.flags & SymbolFlags.Prototype) {
14028-
return ModifierFlags.Public | ModifierFlags.Static;
14029-
}
14030-
return 0;
14031-
}
14032-
1403314052
function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags {
1403414053
return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0;
1403514054
}

src/compiler/core.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,35 @@ namespace ts {
490490
return result;
491491
}
492492

493+
/**
494+
* Maps an array. If the mapped value is an array, it is spread into the result.
495+
* Avoids allocation if all elements map to themselves.
496+
*
497+
* @param array The array to map.
498+
* @param mapfn The callback used to map the result into one or more values.
499+
*/
500+
export function sameFlatMap<T>(array: T[], mapfn: (x: T, i: number) => T | T[]): T[] {
501+
let result: T[];
502+
if (array) {
503+
for (let i = 0; i < array.length; i++) {
504+
const item = array[i];
505+
const mapped = mapfn(item, i);
506+
if (result || item !== mapped || isArray(mapped)) {
507+
if (!result) {
508+
result = array.slice(0, i);
509+
}
510+
if (isArray(mapped)) {
511+
addRange(result, mapped);
512+
}
513+
else {
514+
result.push(mapped);
515+
}
516+
}
517+
}
518+
}
519+
return result || array;
520+
}
521+
493522
/**
494523
* Computes the first matching span of elements and returns a tuple of the first span
495524
* and the remaining elements.

src/compiler/emitter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ namespace ts {
733733
// Transformation nodes
734734
case SyntaxKind.PartiallyEmittedExpression:
735735
return emitPartiallyEmittedExpression(<PartiallyEmittedExpression>node);
736+
737+
case SyntaxKind.CommaListExpression:
738+
return emitCommaList(<CommaListExpression>node);
736739
}
737740
}
738741

@@ -2101,6 +2104,10 @@ namespace ts {
21012104
emitExpression(node.expression);
21022105
}
21032106

2107+
function emitCommaList(node: CommaListExpression) {
2108+
emitExpressionList(node, node.elements, ListFormat.CommaListElements);
2109+
}
2110+
21042111
/**
21052112
* Emits any prologue directives at the start of a Statement list, returning the
21062113
* number of prologue directives written to the output.
@@ -2951,6 +2958,7 @@ namespace ts {
29512958
ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings,
29522959
ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces,
29532960
ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets,
2961+
CommaListElements = CommaDelimited | SpaceBetweenSiblings | SingleLine,
29542962
CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis,
29552963
NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined,
29562964
TemplateExpressionSpans = SingleLine | NoInterveningComments,

src/compiler/factory.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,30 @@ namespace ts {
20772077
return node;
20782078
}
20792079

2080+
function flattenCommaElements(node: Expression): Expression | Expression[] {
2081+
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) {
2082+
if (node.kind === SyntaxKind.CommaListExpression) {
2083+
return (<CommaListExpression>node).elements;
2084+
}
2085+
if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) {
2086+
return [node.left, node.right];
2087+
}
2088+
}
2089+
return node;
2090+
}
2091+
2092+
export function createCommaList(elements: Expression[]) {
2093+
const node = <CommaListExpression>createSynthesizedNode(SyntaxKind.CommaListExpression);
2094+
node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements));
2095+
return node;
2096+
}
2097+
2098+
export function updateCommaList(node: CommaListExpression, elements: Expression[]) {
2099+
return node.elements !== elements
2100+
? updateNode(createCommaList(elements), node)
2101+
: node;
2102+
}
2103+
20802104
// Compound nodes
20812105

20822106
export function createComma(left: Expression, right: Expression) {
@@ -2852,7 +2876,11 @@ namespace ts {
28522876
}
28532877

28542878
export function inlineExpressions(expressions: Expression[]) {
2855-
return reduceLeft(expressions, createComma);
2879+
// Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call
2880+
// stack size exceeded" errors.
2881+
return expressions.length > 10
2882+
? createCommaList(expressions)
2883+
: reduceLeft(expressions, createComma);
28562884
}
28572885

28582886
export function createExpressionFromEntityName(node: EntityName | Expression): Expression {

src/compiler/moduleNameResolver.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ namespace ts {
4747
return resolved.path;
4848
}
4949

50-
/** Adds `isExernalLibraryImport` to a Resolved to get a ResolvedModule. */
51-
function resolvedModuleFromResolved({ path, extension }: Resolved, isExternalLibraryImport: boolean): ResolvedModuleFull {
52-
return { resolvedFileName: path, extension, isExternalLibraryImport };
53-
}
54-
5550
function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations {
56-
return { resolvedModule: resolved && resolvedModuleFromResolved(resolved, isExternalLibraryImport), failedLookupLocations };
51+
return {
52+
resolvedModule: resolved && { resolvedFileName: resolved.path, extension: resolved.extension, isExternalLibraryImport },
53+
failedLookupLocations
54+
};
5755
}
5856

5957
export function moduleHasNonRelativeName(moduleName: string): boolean {
@@ -442,6 +440,8 @@ namespace ts {
442440
case ModuleResolutionKind.Classic:
443441
result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache);
444442
break;
443+
default:
444+
Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
445445
}
446446

447447
if (perFolderCache) {

src/compiler/parser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ namespace ts {
361361
return visitNode(cbNode, (<ExternalModuleReference>node).expression);
362362
case SyntaxKind.MissingDeclaration:
363363
return visitNodes(cbNodes, node.decorators);
364+
case SyntaxKind.CommaListExpression:
365+
return visitNodes(cbNodes, (<CommaListExpression>node).elements);
364366

365367
case SyntaxKind.JsxElement:
366368
return visitNode(cbNode, (<JsxElement>node).openingElement) ||

0 commit comments

Comments
 (0)