Merge branch 'master' into release-3.3

This commit is contained in:
Daniel Rosenwasser
2019-01-28 09:44:50 -08:00
135 changed files with 4032 additions and 801 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outDir": "../../built/local/",
"rootDir": ".",
+39 -6
View File
@@ -100,6 +100,8 @@ namespace ts {
IsObjectLiteralOrClassExpressionMethod = 1 << 7,
}
let flowNodeCreated: <T extends FlowNode>(node: T) => T = identity;
const binder = createBinder();
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
@@ -530,6 +532,7 @@ namespace ts {
blockScopeContainer.locals = undefined;
}
if (containerFlags & ContainerFlags.IsControlFlowContainer) {
const saveFlowNodeCreated = flowNodeCreated;
const saveCurrentFlow = currentFlow;
const saveBreakTarget = currentBreakTarget;
const saveContinueTarget = currentContinueTarget;
@@ -553,6 +556,7 @@ namespace ts {
currentContinueTarget = undefined;
activeLabels = undefined;
hasExplicitReturn = false;
flowNodeCreated = identity;
bindChildren(node);
// Reset all reachability check related flags on node (for incremental scenarios)
node.flags &= ~NodeFlags.ReachabilityAndEmitFlags;
@@ -579,6 +583,7 @@ namespace ts {
currentReturnTarget = saveReturnTarget;
activeLabels = saveActiveLabels;
hasExplicitReturn = saveHasExplicitReturn;
flowNodeCreated = saveFlowNodeCreated;
}
else if (containerFlags & ContainerFlags.IsInterface) {
seenThisKeyword = false;
@@ -858,7 +863,7 @@ namespace ts {
return antecedent;
}
setFlowNodeReferenced(antecedent);
return { flags, expression, antecedent };
return flowNodeCreated({ flags, expression, antecedent });
}
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
@@ -866,17 +871,17 @@ namespace ts {
return antecedent;
}
setFlowNodeReferenced(antecedent);
return { flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent };
return flowNodeCreated({ flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent });
}
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
setFlowNodeReferenced(antecedent);
return { flags: FlowFlags.Assignment, antecedent, node };
return flowNodeCreated({ flags: FlowFlags.Assignment, antecedent, node });
}
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
setFlowNodeReferenced(antecedent);
const res: FlowArrayMutation = { flags: FlowFlags.ArrayMutation, antecedent, node };
const res: FlowArrayMutation = flowNodeCreated({ flags: FlowFlags.ArrayMutation, antecedent, node });
return res;
}
@@ -1080,8 +1085,16 @@ namespace ts {
function bindTryStatement(node: TryStatement): void {
const preFinallyLabel = createBranchLabel();
const preTryFlow = currentFlow;
// TODO: Every statement in try block is potentially an exit point!
const tryPriors: FlowNode[] = [];
const oldFlowNodeCreated = flowNodeCreated;
// We hook the creation of all flow nodes within the `try` scope and store them so we can add _all_ of them
// as possible antecedents of the start of the `catch` or `finally` blocks.
// Don't bother intercepting the call if there's no finally or catch block that needs the information
if (node.catchClause || node.finallyBlock) {
flowNodeCreated = node => (tryPriors.push(node), node);
}
bind(node.tryBlock);
flowNodeCreated = oldFlowNodeCreated;
addAntecedent(preFinallyLabel, currentFlow);
const flowAfterTry = currentFlow;
@@ -1089,12 +1102,32 @@ namespace ts {
if (node.catchClause) {
currentFlow = preTryFlow;
if (tryPriors.length) {
const preCatchFlow = createBranchLabel();
addAntecedent(preCatchFlow, currentFlow);
for (const p of tryPriors) {
addAntecedent(preCatchFlow, p);
}
currentFlow = finishFlowLabel(preCatchFlow);
}
bind(node.catchClause);
addAntecedent(preFinallyLabel, currentFlow);
flowAfterCatch = currentFlow;
}
if (node.finallyBlock) {
// We add the nodes within the `try` block to the `finally`'s antecedents if there's no catch block
// (If there is a `catch` block, it will have all these antecedents instead, and the `finally` will
// have the end of the `try` block and the end of the `catch` block)
if (!node.catchClause) {
if (tryPriors.length) {
for (const p of tryPriors) {
addAntecedent(preFinallyLabel, p);
}
}
}
// in finally flow is combined from pre-try/flow from try/flow from catch
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
@@ -1142,7 +1175,7 @@ namespace ts {
}
}
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
const afterFinallyFlow: AfterFinallyFlow = { flags: FlowFlags.AfterFinally, antecedent: currentFlow };
const afterFinallyFlow: AfterFinallyFlow = flowNodeCreated({ flags: FlowFlags.AfterFinally, antecedent: currentFlow });
preFinallyFlow.lock = afterFinallyFlow;
currentFlow = afterFinallyFlow;
}
+110 -101
View File
@@ -4855,7 +4855,7 @@ namespace ts {
function getLiteralPropertyNameText(name: PropertyName) {
const type = getLiteralTypeFromPropertyName(name);
return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (<LiteralType>type).value : undefined;
return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (<StringLiteralType | NumberLiteralType>type).value : undefined;
}
/** Return the inferred type for a binding element */
@@ -5280,17 +5280,18 @@ namespace ts {
let objectFlags = ObjectFlags.ObjectLiteral;
forEach(pattern.elements, e => {
const name = e.propertyName || <Identifier>e.name;
if (isComputedNonLiteralName(name)) {
// do not include computed properties in the implied type
objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
return;
}
if (e.dotDotDotToken) {
stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false);
return;
}
const text = getTextOfPropertyName(name);
const exprType = getLiteralTypeFromPropertyName(name);
if (!isTypeUsableAsPropertyName(exprType)) {
// do not include computed properties in the implied type
objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties;
return;
}
const text = getPropertyNameFromType(exprType);
const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0);
const symbol = createSymbol(flags, text);
symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors);
@@ -6399,9 +6400,9 @@ namespace ts {
}
/**
* Indicates whether a type can be used as a late-bound name.
* Indicates whether a type can be used as a property name.
*/
function isTypeUsableAsLateBoundName(type: Type): type is LiteralType | UniqueESSymbolType {
function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType {
return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique);
}
@@ -6416,7 +6417,7 @@ namespace ts {
function isLateBindableName(node: DeclarationName): node is LateBoundName {
return isComputedPropertyName(node)
&& isEntityNameExpression(node.expression)
&& isTypeUsableAsLateBoundName(checkComputedPropertyName(node));
&& isTypeUsableAsPropertyName(checkComputedPropertyName(node));
}
function isLateBoundName(name: __String): boolean {
@@ -6448,14 +6449,14 @@ namespace ts {
}
/**
* Gets the symbolic name for a late-bound member from its type.
* Gets the symbolic name for a member from its type.
*/
function getLateBoundNameFromType(type: LiteralType | UniqueESSymbolType): __String {
function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String {
if (type.flags & TypeFlags.UniqueESSymbol) {
return `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
return (<UniqueESSymbolType>type).escapedName;
}
if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
return escapeLeadingUnderscores("" + (<LiteralType>type).value);
return escapeLeadingUnderscores("" + (<StringLiteralType | NumberLiteralType>type).value);
}
return Debug.fail();
}
@@ -6518,8 +6519,8 @@ namespace ts {
// fall back to the early-bound name of this member.
links.resolvedSymbol = decl.symbol;
const type = checkComputedPropertyName(decl.name);
if (isTypeUsableAsLateBoundName(type)) {
const memberName = getLateBoundNameFromType(type);
if (isTypeUsableAsPropertyName(type)) {
const memberName = getPropertyNameFromType(type);
const symbolFlags = decl.symbol.flags;
// Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations.
@@ -6534,9 +6535,9 @@ namespace ts {
// If we have an existing early-bound member, combine its declarations so that we can
// report an error at each declaration.
const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations;
const name = declarationNameToString(decl.name);
forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Duplicate_declaration_0, name));
error(decl.name || decl, Diagnostics.Duplicate_declaration_0, name);
const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(decl.name);
forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name));
error(decl.name || decl, Diagnostics.Duplicate_property_0, name);
lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late);
}
lateSymbol.nameType = type;
@@ -7168,8 +7169,8 @@ namespace ts {
const propType = instantiateType(templateType, templateMapper);
// If the current iteration type constituent is a string literal type, create a property.
// Otherwise, for type string create a string index signature.
if (t.flags & TypeFlags.StringOrNumberLiteralOrUnique) {
const propName = getLateBoundNameFromType(t as LiteralType);
if (isTypeUsableAsPropertyName(t)) {
const propName = getPropertyNameFromType(t);
const modifiersProp = getPropertyOfType(modifiersType, propName);
const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional ||
!(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional);
@@ -7354,7 +7355,8 @@ namespace ts {
function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean {
const list = obj.properties as NodeArray<ObjectLiteralElementLike | JsxAttributeLike>;
return list.some(property => {
const name = property.name && getTextOfPropertyName(property.name);
const nameType = property.name && getLiteralTypeFromPropertyName(property.name);
const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name);
return !!expected && isLiteralType(expected) && !isTypeIdenticalTo(getTypeOfNode(property), expected);
});
@@ -7741,7 +7743,13 @@ namespace ts {
result.containingType = containingType;
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
result.valueDeclaration = firstValueDeclaration;
// Inherit information about parent type.
if (firstValueDeclaration.symbol.parent) {
result.parent = firstValueDeclaration.symbol.parent;
}
}
result.declarations = declarations!;
result.nameType = nameType;
result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes);
@@ -8698,21 +8706,17 @@ namespace ts {
* the type of this reference is just the type of the value we resolved to.
*/
function getJSDocTypeReference(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.JSDocTypeReference)) {
return errorType;
}
const assignedType = getAssignedClassType(symbol);
const valueType = getTypeOfSymbol(symbol);
const referenceType = valueType.symbol && valueType.symbol !== symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
if (!popTypeResolution()) {
getSymbolLinks(symbol).resolvedJSDocType = errorType;
error(node, Diagnostics.JSDoc_type_0_circularly_references_itself, symbolToString(symbol));
return errorType;
}
if (referenceType || assignedType) {
// TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?)
const type = (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType)!;
return getSymbolLinks(symbol).resolvedJSDocType = type;
// In the case of an assignment of a function expression (binary expressions, variable declarations, etc.), we will get the
// correct instance type for the symbol on the LHS by finding the type for RHS. For example if we want to get the type of the symbol `foo`:
// var foo = function() {}
// We will find the static type of the assigned anonymous function.
const staticType = getTypeOfSymbol(symbol);
const instanceType =
staticType.symbol &&
staticType.symbol !== symbol && // Make sure this is an assignment like expression by checking that symbol -> type -> symbol doesn't roundtrips.
getTypeReferenceTypeWorker(node, staticType.symbol, typeArguments); // Get the instance type of the RHS symbol.
if (instanceType) {
return getSymbolLinks(symbol).resolvedJSDocType = instanceType;
}
}
@@ -8733,8 +8737,11 @@ namespace ts {
if (symbol.flags & SymbolFlags.Function &&
isJSDocTypeReference(node) &&
(symbol.members || getJSDocClassTag(symbol.valueDeclaration))) {
return getInferredClassType(symbol);
isJSConstructor(symbol.valueDeclaration)) {
const resolved = resolveStructuredTypeMembers(<ObjectType>getTypeOfSymbol(symbol));
if (resolved.callSignatures.length === 1) {
return getReturnTypeOfSignature(resolved.callSignatures[0]);
}
}
}
@@ -9717,8 +9724,8 @@ namespace ts {
function getPropertyTypeForIndexType(objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
const propName = isTypeUsableAsLateBoundName(indexType) ?
getLateBoundNameFromType(indexType) :
const propName = isTypeUsableAsPropertyName(indexType) ?
getPropertyNameFromType(indexType) :
accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ?
getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>accessExpression.argumentExpression).name)) :
accessNode && isPropertyName(accessNode) ?
@@ -9809,7 +9816,7 @@ namespace ts {
if (accessNode) {
const indexNode = getIndexNodeForAccessExpression(accessNode);
if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) {
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (<LiteralType>indexType).value, typeToString(objectType));
error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (<StringLiteralType | NumberLiteralType>indexType).value, typeToString(objectType));
}
else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) {
error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType));
@@ -10408,6 +10415,7 @@ namespace ts {
function createUniqueESSymbolType(symbol: Symbol) {
const type = <UniqueESSymbolType>createType(TypeFlags.UniqueESSymbol);
type.symbol = symbol;
type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String;
return type;
}
@@ -10628,7 +10636,11 @@ namespace ts {
}
function getRestrictiveTypeParameter(tp: TypeParameter) {
return !tp.constraint ? tp : tp.restrictiveInstantiation || (tp.restrictiveInstantiation = createTypeParameter(tp.symbol));
return tp.constraint === unknownType ? tp : tp.restrictiveInstantiation || (
tp.restrictiveInstantiation = createTypeParameter(tp.symbol),
(tp.restrictiveInstantiation as TypeParameter).constraint = unknownType,
tp.restrictiveInstantiation
);
}
function restrictiveMapper(type: Type) {
@@ -11295,7 +11307,7 @@ namespace ts {
}
if (resultObj.error) {
const reportedDiag = resultObj.error;
const propertyName = isTypeUsableAsLateBoundName(nameType) ? getLateBoundNameFromType(nameType) : undefined;
const propertyName = isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined;
const targetProp = propertyName !== undefined ? getPropertyOfType(target, propertyName) : undefined;
let issuedElaboration = false;
@@ -11754,11 +11766,11 @@ namespace ts {
if (s & TypeFlags.StringLike && t & TypeFlags.String) return true;
if (s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral &&
t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) &&
(<LiteralType>source).value === (<LiteralType>target).value) return true;
(<StringLiteralType>source).value === (<StringLiteralType>target).value) return true;
if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true;
if (s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral &&
t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) &&
(<LiteralType>source).value === (<LiteralType>target).value) return true;
(<NumberLiteralType>source).value === (<NumberLiteralType>target).value) return true;
if (s & TypeFlags.BigIntLike && t & TypeFlags.BigInt) return true;
if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true;
if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true;
@@ -12671,7 +12683,7 @@ namespace ts {
}
else {
// An empty object type is related to any mapped type that includes a '?' modifier.
if (isPartialMappedType(target) && isEmptyObjectType(source)) {
if (relation !== subtypeRelation && isPartialMappedType(target) && isEmptyObjectType(source)) {
return Ternary.True;
}
if (isGenericMappedType(target)) {
@@ -13682,8 +13694,8 @@ namespace ts {
// no flags for all other types (including non-falsy literal types).
function getFalsyFlags(type: Type): TypeFlags {
return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((<UnionType>type).types) :
type.flags & TypeFlags.StringLiteral ? (<LiteralType>type).value === "" ? TypeFlags.StringLiteral : 0 :
type.flags & TypeFlags.NumberLiteral ? (<LiteralType>type).value === 0 ? TypeFlags.NumberLiteral : 0 :
type.flags & TypeFlags.StringLiteral ? (<StringLiteralType>type).value === "" ? TypeFlags.StringLiteral : 0 :
type.flags & TypeFlags.NumberLiteral ? (<NumberLiteralType>type).value === 0 ? TypeFlags.NumberLiteral : 0 :
type.flags & TypeFlags.BigIntLiteral ? isZeroBigInt(<BigIntLiteralType>type) ? TypeFlags.BigIntLiteral : 0 :
type.flags & TypeFlags.BooleanLiteral ? (type === falseType || type === regularFalseType) ? TypeFlags.BooleanLiteral : 0 :
type.flags & TypeFlags.PossiblyFalsy;
@@ -13706,8 +13718,8 @@ namespace ts {
type === regularFalseType ||
type === falseType ||
type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null) ||
type.flags & TypeFlags.StringLiteral && (<LiteralType>type).value === "" ||
type.flags & TypeFlags.NumberLiteral && (<LiteralType>type).value === 0 ||
type.flags & TypeFlags.StringLiteral && (<StringLiteralType>type).value === "" ||
type.flags & TypeFlags.NumberLiteral && (<NumberLiteralType>type).value === 0 ||
type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(<BigIntLiteralType>type) ? type :
neverType;
}
@@ -14562,7 +14574,12 @@ namespace ts {
priority |= InferencePriority.MappedTypeConstraint;
inferFromTypes(getIndexType(source), constraintType);
priority = savePriority;
inferFromTypes(getUnionType(map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(<MappedType>target));
const valueTypes = compact([
getIndexTypeOfType(source, IndexKind.String),
getIndexTypeOfType(source, IndexKind.Number),
...map(getPropertiesOfType(source), getTypeOfSymbol)
]);
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(<MappedType>target));
return true;
}
return false;
@@ -15095,7 +15112,7 @@ namespace ts {
return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts;
}
if (flags & TypeFlags.StringLiteral) {
const isEmpty = (<LiteralType>type).value === "";
const isEmpty = (<StringLiteralType>type).value === "";
return strictNullChecks ?
isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts :
isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts;
@@ -15104,7 +15121,7 @@ namespace ts {
return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts;
}
if (flags & TypeFlags.NumberLiteral) {
const isZero = (<LiteralType>type).value === 0;
const isZero = (<NumberLiteralType>type).value === 0;
return strictNullChecks ?
isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts :
isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts;
@@ -15167,7 +15184,9 @@ namespace ts {
}
function getTypeOfDestructuredProperty(type: Type, name: PropertyName) {
const text = getTextOfPropertyName(name);
const nameType = getLiteralTypeFromPropertyName(name);
if (!isTypeUsableAsPropertyName(nameType)) return errorType;
const text = getPropertyNameFromType(nameType);
return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) ||
isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) ||
getIndexTypeOfType(type, IndexKind.String) ||
@@ -15775,9 +15794,6 @@ namespace ts {
function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
const expr = flow.switchStatement.expression;
if (containsMatchingReferenceDiscriminant(reference, expr)) {
return declaredType;
}
const flowType = getTypeAtFlowNode(flow.antecedent);
let type = getTypeFromFlowType(flowType);
if (isMatchingReference(reference, expr)) {
@@ -15792,6 +15808,9 @@ namespace ts {
else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) {
type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
else if (containsMatchingReferenceDiscriminant(reference, expr)) {
type = declaredType;
}
return createFlowType(type, isIncomplete(flowType));
}
@@ -16871,7 +16890,7 @@ namespace ts {
else if (isInJS &&
(container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) &&
getJSDocClassTag(container)) {
const classType = getJSClassType(container.symbol);
const classType = getJSClassType(getMergedSymbol(container.symbol));
if (classType) {
return getFlowTypeOfReference(node, classType);
}
@@ -17299,9 +17318,10 @@ namespace ts {
const parentDeclaration = declaration.parent.parent;
const name = declaration.propertyName || declaration.name;
const parentType = getContextualTypeForVariableLikeDeclaration(parentDeclaration);
if (parentType && !isBindingPattern(name)) {
const text = getTextOfPropertyName(name);
if (text !== undefined) {
if (parentType && !isBindingPattern(name) && !isComputedNonLiteralName(name)) {
const nameType = getLiteralTypeFromPropertyName(name);
if (isTypeUsableAsPropertyName(nameType)) {
const text = getPropertyNameFromType(nameType);
return getTypeOfPropertyOfType(parentType, text);
}
}
@@ -18258,10 +18278,9 @@ namespace ts {
}
}
typeFlags |= type.flags;
const nameType = computedNameType && computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique ?
<LiteralType | UniqueESSymbolType>computedNameType : undefined;
const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined;
const prop = nameType ?
createSymbol(SymbolFlags.Property | member.flags, getLateBoundNameFromType(nameType), CheckFlags.Late) :
createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), CheckFlags.Late) :
createSymbol(SymbolFlags.Property | member.flags, member.escapedName);
if (nameType) {
prop.nameType = nameType;
@@ -18550,6 +18569,10 @@ namespace ts {
childrenPropSymbol.type = childrenTypes.length === 1 ?
childrenTypes[0] :
(getArrayLiteralTupleTypeIfApplicable(childrenTypes, childrenContextualType, /*hasRestElement*/ false) || createArrayType(getUnionType(childrenTypes)));
// Fake up a property declaration for the children
childrenPropSymbol.valueDeclaration = createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined);
childrenPropSymbol.valueDeclaration.parent = attributes;
childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol;
const childPropMap = createSymbolTable();
childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol);
spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined),
@@ -20412,6 +20435,12 @@ namespace ts {
if (inferenceContext) {
const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration));
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
candidateForArgumentArityError = checkCandidate;
continue;
}
}
if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) {
// Give preference to error candidates that have no rest parameters (as they are more specific)
@@ -21041,7 +21070,7 @@ namespace ts {
// If the symbol of the node has members, treat it like a constructor.
const symbol = getSymbolOfNode(func);
return !!symbol && symbol.members !== undefined;
return !!symbol && (symbol.members !== undefined || symbol.exports !== undefined && symbol.exports.get("prototype" as __String) !== undefined);
}
return false;
}
@@ -21060,10 +21089,6 @@ namespace ts {
inferred = getInferredClassType(symbol);
}
const assigned = getAssignedClassType(symbol);
const valueType = getTypeOfSymbol(symbol);
if (valueType.symbol && !isInferredClassType(valueType) && isJSConstructor(valueType.symbol.valueDeclaration)) {
inferred = getInferredClassType(valueType.symbol);
}
return assigned && inferred ?
getIntersectionType([inferred, assigned]) :
assigned || inferred;
@@ -21103,12 +21128,6 @@ namespace ts {
return links.inferredClassType;
}
function isInferredClassType(type: Type) {
return type.symbol
&& getObjectFlags(type) & ObjectFlags.Anonymous
&& getSymbolLinks(type.symbol).inferredClassType === type;
}
/**
* Syntactically and semantically checks a call or new expression.
* @param node The call/new expression to be checked.
@@ -21130,21 +21149,10 @@ namespace ts {
declaration.kind !== SyntaxKind.Constructor &&
declaration.kind !== SyntaxKind.ConstructSignature &&
declaration.kind !== SyntaxKind.ConstructorType &&
!isJSDocConstructSignature(declaration)) {
!isJSDocConstructSignature(declaration) &&
!isJSConstructor(declaration)) {
// When resolved signature is a call signature (and not a construct signature) the result type is any, unless
// the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations
// in a JS file
// Note:JS inferred classes might come from a variable declaration instead of a function declaration.
// In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration.
let funcSymbol = checkExpression(node.expression).symbol;
if (!funcSymbol && node.expression.kind === SyntaxKind.Identifier) {
funcSymbol = getResolvedSymbol(node.expression as Identifier);
}
const type = funcSymbol && getJSClassType(funcSymbol);
if (type) {
return signature.target ? instantiateType(type, signature.mapper) : type;
}
// When resolved signature is a call signature (and not a construct signature) the result type is any
if (noImplicitAny) {
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
}
@@ -22300,7 +22308,7 @@ namespace ts {
if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbolLike))) {
error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
}
if (!isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) {
if (!allTypesAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) {
error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
return booleanType;
@@ -22321,15 +22329,15 @@ namespace ts {
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, allProperties?: NodeArray<ObjectLiteralElementLike>, rightIsThis = false) {
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = property.name;
const text = getTextOfPropertyName(name);
if (text) {
const exprType = getLiteralTypeFromPropertyName(name);
if (isTypeUsableAsPropertyName(exprType)) {
const text = getPropertyNameFromType(exprType);
const prop = getPropertyOfType(objectLiteralType, text);
if (prop) {
markPropertyAsReferenced(prop, property, rightIsThis);
checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop);
}
}
const exprType = getLiteralTypeFromPropertyName(name);
const elementType = getIndexedAccessType(objectLiteralType, exprType, name);
const type = getFlowTypeOfDestructuring(property, elementType);
return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type);
@@ -25644,13 +25652,14 @@ namespace ts {
const parent = node.parent.parent;
const parentType = getTypeForBindingElementParent(parent);
const name = node.propertyName || node.name;
if (!isBindingPattern(name)) {
const nameText = getTextOfPropertyName(name);
if (nameText) {
const property = getPropertyOfType(parentType!, nameText); // TODO: GH#18217
if (!isBindingPattern(name) && parentType) {
const exprType = getLiteralTypeFromPropertyName(name);
if (isTypeUsableAsPropertyName(exprType)) {
const nameText = getPropertyNameFromType(exprType);
const property = getPropertyOfType(parentType, nameText);
if (property) {
markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference.
checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType!, property);
checkPropertyAccessibility(parent, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, parentType, property);
}
}
}
@@ -26053,7 +26062,7 @@ namespace ts {
? downlevelIteration
? Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator
: isIterable
? Diagnostics.Type_0_is_not_an_array_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators
? Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators
: Diagnostics.Type_0_is_not_an_array_type
: downlevelIteration
? Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator
@@ -31184,7 +31193,7 @@ namespace ts {
if (nodeArguments.length !== 1) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument);
}
checkGrammarForDisallowedTrailingComma(nodeArguments);
// see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
// parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
if (isSpreadElement(nodeArguments[0])) {
+5 -2
View File
@@ -884,8 +884,11 @@ namespace ts {
/**
* Compacts an array, removing any falsey elements.
*/
export function compact<T>(array: T[]): T[];
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>;
export function compact<T>(array: (T | undefined | null | false | 0 | "")[]): T[];
export function compact<T>(array: ReadonlyArray<T | undefined | null | false | 0 | "">): ReadonlyArray<T>;
// TSLint thinks these can be combined with the above - they cannot; they'd produce higher-priority inferences and prevent the falsey types from being stripped
export function compact<T>(array: T[]): T[]; // tslint:disable-line unified-signatures
export function compact<T>(array: ReadonlyArray<T>): ReadonlyArray<T>; // tslint:disable-line unified-signatures
export function compact<T>(array: T[]): T[] {
let result: T[] | undefined;
if (array) {
+5 -5
View File
@@ -2056,10 +2056,6 @@
"category": "Error",
"code": 2567
},
"Type '{0}' is not an array type. Use compiler option '--downlevelIteration' to allow iterating of iterators.": {
"category": "Error",
"code": 2568
},
"Type '{0}' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.": {
"category": "Error",
"code": 2569
@@ -2437,7 +2433,7 @@
"category": "Error",
"code": 2717
},
"Duplicate declaration '{0}'.": {
"Duplicate property '{0}'.": {
"category": "Error",
"code": 2718
},
@@ -2497,6 +2493,10 @@
"category": "Error",
"code": 2732
},
"Property '{0}' was also declared here.": {
"category": "Error",
"code": 2733
},
"It is highly likely that you are missing a semicolon.": {
"category": "Error",
"code": 2734
+14 -9
View File
@@ -38,17 +38,22 @@ namespace ts {
}
}
/*@internal*/
export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: boolean): EmitFileNames {
const outPath = options.outFile || options.out!;
const jsFilePath = options.emitDeclarationOnly ? undefined : outPath;
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
}
/*@internal*/
export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames {
const options = host.getCompilerOptions();
if (sourceFile.kind === SyntaxKind.Bundle) {
const outPath = options.outFile || options.out!;
const jsFilePath = options.emitDeclarationOnly ? undefined : outPath;
const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined;
const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
const bundleInfoPath = options.references && jsFilePath ? (removeFileExtension(jsFilePath) + infoExtension) : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
return getOutputPathsForBundle(options, forceDtsPaths);
}
else {
const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile, options));
@@ -4372,10 +4377,10 @@ namespace ts {
}
/**
* Skips trivia such as comments and white-space that can optionally overriden by the source map source
* Skips trivia such as comments and white-space that can be optionally overridden by the source-map source
*/
function skipSourceTrivia(source: SourceMapSource, pos: number): number {
return source.skipTrivia ? source.skipTrivia(pos) : skipTrivia(sourceMapSource.text, pos);
return source.skipTrivia ? source.skipTrivia(pos) : skipTrivia(source.text, pos);
}
/**
+64 -17
View File
@@ -2630,41 +2630,88 @@ namespace ts {
}
export function createUnparsedSourceFile(text: string): UnparsedSource;
export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts"): UnparsedSource;
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
export function createUnparsedSourceFile(text: string, mapPath?: string, map?: string): UnparsedSource {
export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, map?: string): UnparsedSource {
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
node.text = text;
node.sourceMapPath = mapPath;
node.sourceMapText = map;
if (!isString(textOrInputFiles)) {
Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
node.fileName = mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath;
node.sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath;
Object.defineProperties(node, {
text: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; } },
sourceMapText: { get() { return mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; } },
});
}
else {
node.text = textOrInputFiles;
node.sourceMapPath = mapPathOrType;
node.sourceMapText = map;
}
return node;
}
export function createInputFiles(
javascript: string,
declaration: string
javascriptText: string,
declarationText: string
): InputFiles;
export function createInputFiles(
javascript: string,
declaration: string,
readFileText: (path: string) => string | undefined,
javascriptPath: string,
javascriptMapPath: string | undefined,
declarationPath: string,
declarationMapPath: string | undefined,
): InputFiles;
export function createInputFiles(
javascriptText: string,
declarationText: string,
javascriptMapPath: string | undefined,
javascriptMapText: string | undefined,
declarationMapPath: string | undefined,
declarationMapText: string | undefined
): InputFiles;
export function createInputFiles(
javascript: string,
declaration: string,
javascriptTextOrReadFileText: string | ((path: string) => string | undefined),
declarationTextOrJavascriptPath: string,
javascriptMapPath?: string,
javascriptMapText?: string,
javascriptMapTextOrDeclarationPath?: string,
declarationMapPath?: string,
declarationMapText?: string
): InputFiles {
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
node.javascriptText = javascript;
node.javascriptMapPath = javascriptMapPath;
node.javascriptMapText = javascriptMapText;
node.declarationText = declaration;
node.declarationMapPath = declarationMapPath;
node.declarationMapText = declarationMapText;
if (!isString(javascriptTextOrReadFileText)) {
const cache = createMap<string | false>();
const textGetter = (path: string | undefined) => {
if (path === undefined) return undefined;
let value = cache.get(path);
if (value === undefined) {
value = javascriptTextOrReadFileText(path);
cache.set(path, value !== undefined ? value : false);
}
return value !== false ? value as string : undefined;
};
const definedTextGetter = (path: string) => {
const result = textGetter(path);
return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
};
node.javascriptPath = declarationTextOrJavascriptPath;
node.javascriptMapPath = javascriptMapPath;
node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath);
node.declarationMapPath = declarationMapPath;
Object.defineProperties(node, {
javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } },
declarationMapText: { get() { return textGetter(declarationMapPath); } } // TODO:: if there is inline sourceMap in dtsFile, use that
});
}
else {
node.javascriptText = javascriptTextOrReadFileText;
node.javascriptMapPath = javascriptMapPath;
node.javascriptMapText = javascriptMapTextOrDeclarationPath;
node.declarationText = declarationTextOrJavascriptPath;
node.declarationMapPath = declarationMapPath;
node.declarationMapText = declarationMapText;
}
return node;
}
+9 -3
View File
@@ -1093,6 +1093,10 @@ namespace ts {
return currentToken = scanner.reScanTemplateToken();
}
function reScanLessThanToken(): SyntaxKind {
return currentToken = scanner.reScanLessThanToken();
}
function scanJsxIdentifier(): SyntaxKind {
return currentToken = scanner.scanJsxIdentifier();
}
@@ -2276,7 +2280,7 @@ namespace ts {
function parseTypeReference(): TypeReferenceNode {
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference);
node.typeName = parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.LessThanToken) {
if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
}
return finishNode(node);
@@ -4523,7 +4527,8 @@ namespace ts {
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
while (true) {
expression = parseMemberExpressionRest(expression);
if (token() === SyntaxKind.LessThanToken) {
// handle 'foo<<T>()'
if (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken) {
// See if this is the start of a generic invocation. If so, consume it and
// keep checking for postfix expressions. Otherwise, it's just a '<' that's
// part of an arithmetic expression. Break out so we consume it higher in the
@@ -4565,9 +4570,10 @@ namespace ts {
}
function parseTypeArgumentsInExpression() {
if (!parseOptional(SyntaxKind.LessThanToken)) {
if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
return undefined;
}
nextToken();
const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
if (!parseExpected(SyntaxKind.GreaterThanToken)) {
+6 -8
View File
@@ -1456,14 +1456,12 @@ namespace ts {
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
if (!out) continue;
const dtsFilename = changeExtension(out, ".d.ts");
const js = host.readFile(out) || `/* Input file ${out} was missing */\r\n`;
const jsMapPath = out + ".map"; // TODO: try to read sourceMappingUrl comment from the file
const jsMap = host.readFile(jsMapPath);
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
const dtsMapPath = dtsFilename + ".map";
const dtsMap = host.readFile(dtsMapPath);
const node = createInputFiles(js, dts, jsMap && jsMapPath, jsMap, dtsMap && dtsMapPath, dtsMap);
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true);
const node = createInputFiles(fileName => {
const path = toPath(fileName);
const sourceFile = getSourceFileByPath(path);
return sourceFile ? sourceFile.text : filesByName.has(path) ? undefined : host.readFile(path);
}, jsFilePath! , sourceMapFilePath, declarationFilePath! , declarationMapPath);
nodes.push(node);
}
}
+10
View File
@@ -31,6 +31,7 @@ namespace ts {
scanJsxIdentifier(): SyntaxKind;
scanJsxAttributeValue(): SyntaxKind;
reScanJsxToken(): JsxTokenSyntaxKind;
reScanLessThanToken(): SyntaxKind;
scanJsxToken(): JsxTokenSyntaxKind;
scanJSDocToken(): JsDocSyntaxKind;
scan(): SyntaxKind;
@@ -874,6 +875,7 @@ namespace ts {
scanJsxIdentifier,
scanJsxAttributeValue,
reScanJsxToken,
reScanLessThanToken,
scanJsxToken,
scanJSDocToken,
scan,
@@ -1939,6 +1941,14 @@ namespace ts {
return token = scanJsxToken();
}
function reScanLessThanToken(): SyntaxKind {
if (token === SyntaxKind.LessThanLessThanToken) {
pos = tokenPos + 1;
return token = SyntaxKind.LessThanToken;
}
return token;
}
function scanJsxToken(): JsxTokenSyntaxKind {
startPos = tokenPos = pos;
+1 -1
View File
@@ -207,7 +207,7 @@ namespace ts {
}
), mapDefined(node.prepends, prepend => {
if (prepend.kind === SyntaxKind.InputFiles) {
return createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapPath, prepend.declarationMapText);
return createUnparsedSourceFile(prepend, "dts");
}
}));
bundle.syntheticFileReferences = [];
+1 -1
View File
@@ -101,7 +101,7 @@ namespace ts {
function transformBundle(node: Bundle) {
return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => {
if (prepend.kind === SyntaxKind.InputFiles) {
return createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapPath, prepend.javascriptMapText);
return createUnparsedSourceFile(prepend, "js");
}
return prepend;
}));
+4
View File
@@ -2761,9 +2761,11 @@ namespace ts {
export interface InputFiles extends Node {
kind: SyntaxKind.InputFiles;
javascriptPath?: string;
javascriptText: string;
javascriptMapPath?: string;
javascriptMapText?: string;
declarationPath?: string;
declarationText: string;
declarationMapPath?: string;
declarationMapText?: string;
@@ -2771,6 +2773,7 @@ namespace ts {
export interface UnparsedSource extends Node {
kind: SyntaxKind.UnparsedSource;
fileName?: string;
text: string;
sourceMapPath?: string;
sourceMapText?: string;
@@ -3952,6 +3955,7 @@ namespace ts {
// Unique symbol types (TypeFlags.UniqueESSymbol)
export interface UniqueESSymbolType extends Type {
symbol: Symbol;
escapedName: __String;
}
export interface StringLiteralType extends LiteralType {
+2 -1
View File
@@ -778,7 +778,8 @@ namespace ts {
case SyntaxKind.NoSubstitutionTemplateLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteralLike(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
if (isStringOrNumericLiteralLike(name.expression)) return escapeLeadingUnderscores(name.expression.text);
return Debug.fail("Text of property name cannot be read from non-literal-valued ComputedPropertyNames");
default:
return Debug.assertNever(name);
}
+1 -1
View File
@@ -4,5 +4,5 @@ The files within this directory are used to generate `lib.d.ts` and `lib.es6.d.t
## Generated files
Any files ending in `.generated.d.ts` aren't mean to be edited by hand.
Any files ending in `.generated.d.ts` aren't meant to be edited by hand.
If you need to make changes to such files, make a change to the input files for [**our library generator**](https://github.com/Microsoft/TSJS-lib-generator).
+64 -10
View File
@@ -587,7 +587,7 @@ interface TemplateStringsArray extends ReadonlyArray<string> {
/**
* The type of `import.meta`.
*
*
* If you need to declare that a given property exists on `import.meta`,
* this type may be augmented via interface merging.
*/
@@ -1913,13 +1913,19 @@ interface Int8ArrayConstructor {
*/
of(...items: number[]): Int8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Int8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Int8Array;
}
@@ -2183,13 +2189,19 @@ interface Uint8ArrayConstructor {
*/
of(...items: number[]): Uint8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Uint8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Uint8Array;
}
declare const Uint8Array: Uint8ArrayConstructor;
@@ -2452,13 +2464,19 @@ interface Uint8ClampedArrayConstructor {
*/
of(...items: number[]): Uint8ClampedArray;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Uint8ClampedArray;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Uint8ClampedArray;
}
declare const Uint8ClampedArray: Uint8ClampedArrayConstructor;
@@ -2719,13 +2737,19 @@ interface Int16ArrayConstructor {
*/
of(...items: number[]): Int16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Int16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Int16Array;
}
@@ -2989,13 +3013,19 @@ interface Uint16ArrayConstructor {
*/
of(...items: number[]): Uint16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Uint16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Uint16Array;
}
@@ -3258,13 +3288,19 @@ interface Int32ArrayConstructor {
*/
of(...items: number[]): Int32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Int32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Int32Array;
}
declare const Int32Array: Int32ArrayConstructor;
@@ -3526,13 +3562,19 @@ interface Uint32ArrayConstructor {
*/
of(...items: number[]): Uint32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Uint32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Uint32Array;
}
declare const Uint32Array: Uint32ArrayConstructor;
@@ -3795,13 +3837,19 @@ interface Float32ArrayConstructor {
*/
of(...items: number[]): Float32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Float32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Float32Array;
}
@@ -4065,13 +4113,19 @@ interface Float64ArrayConstructor {
*/
of(...items: number[]): Float64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
*/
from(arrayLike: ArrayLike<number>): Float64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): Float64Array;
}
declare const Float64Array: Float64ArrayConstructor;
+1
View File
@@ -2905,6 +2905,7 @@ namespace ts.server.protocol {
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
readonly allowRenameOfImportPath?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
+2 -1
View File
@@ -1774,7 +1774,8 @@ namespace ts.FindAllReferences.Core {
function isImplementation(node: Node): boolean {
return !!(node.flags & NodeFlags.Ambient)
|| (isVariableLike(node) ? hasInitializer(node)
? !(isInterfaceDeclaration(node) || isTypeAliasDeclaration(node))
: (isVariableLike(node) ? hasInitializer(node)
: isFunctionLikeDeclaration(node) ? !!node.body
: isClassLike(node) || isModuleOrEnumDeclaration(node));
}
+29 -1
View File
@@ -460,6 +460,12 @@ namespace ts.refactor {
const oldImportsNeededByNewFile = new SymbolSet();
const newFileImportsFromOldFile = new SymbolSet();
const containsJsx = find(toMove, statement => !!(statement.transformFlags & TransformFlags.ContainsJsx));
const jsxNamespaceSymbol = getJsxNamespaceSymbol(containsJsx);
if (jsxNamespaceSymbol) { // Might not exist (e.g. in non-compiling code)
oldImportsNeededByNewFile.add(jsxNamespaceSymbol);
}
for (const statement of toMove) {
forEachTopLevelDeclaration(statement, decl => {
movedSymbols.add(Debug.assertDefined(isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol));
@@ -485,6 +491,11 @@ namespace ts.refactor {
for (const statement of oldFile.statements) {
if (contains(toMove, statement)) continue;
// jsxNamespaceSymbol will only be set iff it is in oldImportsNeededByNewFile.
if (jsxNamespaceSymbol && !!(statement.transformFlags & TransformFlags.ContainsJsx)) {
unusedImportsFromOldFile.delete(jsxNamespaceSymbol);
}
forEachReference(statement, checker, symbol => {
if (movedSymbols.has(symbol)) oldFileImportsFromNewFile.add(symbol);
unusedImportsFromOldFile.delete(symbol);
@@ -492,6 +503,23 @@ namespace ts.refactor {
}
return { movedSymbols, newFileImportsFromOldFile, oldFileImportsFromNewFile, oldImportsNeededByNewFile, unusedImportsFromOldFile };
function getJsxNamespaceSymbol(containsJsx: Node | undefined) {
if (containsJsx === undefined) {
return undefined;
}
const jsxNamespace = checker.getJsxNamespace(containsJsx);
// Strictly speaking, this could resolve to a symbol other than the JSX namespace.
// This will produce erroneous output (probably, an incorrectly copied import) but
// is expected to be very rare and easily reversible.
const jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, SymbolFlags.Namespace, /*excludeGlobals*/ true);
return !!jsxNamespaceSymbol && some(jsxNamespaceSymbol.declarations, isInImport)
? jsxNamespaceSymbol
: undefined;
}
}
// Below should all be utilities
@@ -512,7 +540,7 @@ namespace ts.refactor {
}
function isVariableDeclarationInImport(decl: VariableDeclaration) {
return isSourceFile(decl.parent.parent.parent) &&
decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true);
!!decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true);
}
function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/run.js",
"composite": false,
@@ -129,5 +129,34 @@ namespace ts {
},
{ sourceMap: true }
);
emitsCorrectly("skipTriviaExternalSourceFiles",
[
{
file: "source.ts",
// The source file contains preceding trivia (e.g. whitespace) to try to confuse the `skipSourceTrivia` function.
text: " original;"
},
],
{
before: [
context => node => visitNode(node, function visitor(node: Node): Node {
if (isIdentifier(node) && node.text === "original") {
const newNode = createIdentifier("changed");
setSourceMapRange(newNode, {
pos: 0,
end: 7,
// Do not provide a custom skipTrivia function for `source`.
source: createSourceMapSource("another.html", "changed;")
});
return newNode;
}
return visitEachChild(node, visitor, context);
})
]
},
{ sourceMap: true }
);
});
}
+41
View File
@@ -469,11 +469,20 @@ export const b = new A();`);
describe("unittests:: tsbuild - baseline sectioned sourcemaps", () => {
let fs: vfs.FileSystem | undefined;
const actualReadFileMap = createMap<number>();
before(() => {
fs = outFileFs.shadow();
const host = new fakes.SolutionBuilderHost(fs);
const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: false });
host.clearDiagnostics();
const originalReadFile = host.readFile;
host.readFile = path => {
// Dont record libs
if (path.startsWith("/src/")) {
actualReadFileMap.set(path, (actualReadFileMap.get(path) || 0) + 1);
}
return originalReadFile.call(host, path);
};
builder.buildAllProjects();
host.assertDiagnosticMessages(/*none*/);
});
@@ -485,6 +494,38 @@ export const b = new A();`);
// tslint:disable-next-line:no-null-keyword
Harness.Baseline.runBaseline("outfile-concat.js", patch ? vfs.formatPatch(patch) : null);
});
it("verify readFile calls", () => {
const expected = [
// Configs
"/src/third/tsconfig.json",
"/src/second/tsconfig.json",
"/src/first/tsconfig.json",
// Source files
"/src/third/third_part1.ts",
"/src/second/second_part1.ts",
"/src/second/second_part2.ts",
"/src/first/first_PART1.ts",
"/src/first/first_part2.ts",
"/src/first/first_part3.ts",
// outputs
"/src/first/bin/first-output.js",
"/src/first/bin/first-output.js.map",
"/src/first/bin/first-output.d.ts",
"/src/first/bin/first-output.d.ts.map",
"/src/2/second-output.js",
"/src/2/second-output.js.map",
"/src/2/second-output.d.ts",
"/src/2/second-output.d.ts.map"
];
assert.equal(actualReadFileMap.size, expected.length, `Expected: ${JSON.stringify(expected)} \nActual: ${JSON.stringify(arrayFrom(actualReadFileMap.entries()))}`);
expected.forEach(expectedValue => {
const actual = actualReadFileMap.get(expectedValue);
assert.equal(actual, 1, `Mismatch in read file call number for: ${expectedValue}\nExpected: ${JSON.stringify(expected)} \nActual: ${JSON.stringify(arrayFrom(actualReadFileMap.entries()))}`);
});
});
});
describe("unittests:: tsbuild - downstream prepend projects always get rebuilt", () => {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/tsc.js"
},
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig-base",
"compilerOptions": {
"declaration": false,
"declarationMap": false,
"composite": false
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"outFile": "../../built/local/tsserver.js",
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../built/local/typingsInstaller.js",
+2 -2
View File
@@ -1,5 +1,5 @@
{
"extends": "../tsconfig-base",
"extends": "../tsconfig-noncomposite-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../built/local/watchGuard.js",
@@ -13,4 +13,4 @@
"files": [
"watchGuard.ts"
]
}
}