mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into incrementalBuildInfo
This commit is contained in:
+143
-114
@@ -390,10 +390,10 @@ namespace ts {
|
||||
const wildcardType = createIntrinsicType(TypeFlags.Any, "any");
|
||||
const errorType = createIntrinsicType(TypeFlags.Any, "error");
|
||||
const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
|
||||
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsWideningType, "undefined");
|
||||
const nullType = createIntrinsicType(TypeFlags.Null, "null");
|
||||
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
|
||||
const undefinedType = createNullableType(TypeFlags.Undefined, "undefined", 0);
|
||||
const undefinedWideningType = strictNullChecks ? undefinedType : createNullableType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
|
||||
const nullType = createNullableType(TypeFlags.Null, "null", 0);
|
||||
const nullWideningType = strictNullChecks ? nullType : createNullableType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType);
|
||||
const stringType = createIntrinsicType(TypeFlags.String, "string");
|
||||
const numberType = createIntrinsicType(TypeFlags.Number, "number");
|
||||
const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint");
|
||||
@@ -439,7 +439,7 @@ namespace ts {
|
||||
const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
// The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated
|
||||
// in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes.
|
||||
anyFunctionType.flags |= TypeFlags.ContainsAnyFunctionType;
|
||||
anyFunctionType.objectFlags |= ObjectFlags.ContainsAnyFunctionType;
|
||||
|
||||
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
@@ -1518,7 +1518,8 @@ namespace ts {
|
||||
!checkAndReportErrorForExtendingInterface(errorLocation) &&
|
||||
!checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
|
||||
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) &&
|
||||
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) {
|
||||
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) &&
|
||||
!checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) {
|
||||
let suggestion: Symbol | undefined;
|
||||
if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) {
|
||||
suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning);
|
||||
@@ -1708,6 +1709,17 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkAndReportErrorForUsingValueAsType(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
|
||||
if (meaning & (SymbolFlags.Type & ~SymbolFlags.Namespace)) {
|
||||
const symbol = resolveSymbol(resolveName(errorLocation, name, ~SymbolFlags.Type & SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
|
||||
if (symbol && !(symbol.flags & SymbolFlags.Namespace)) {
|
||||
error(errorLocation, Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here, unescapeLeadingUnderscores(name));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
|
||||
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
|
||||
if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") {
|
||||
@@ -2741,6 +2753,12 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function createNullableType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags): NullableType {
|
||||
const type = createIntrinsicType(kind, intrinsicName);
|
||||
type.objectFlags = objectFlags;
|
||||
return type;
|
||||
}
|
||||
|
||||
function createBooleanType(trueFalseTypes: ReadonlyArray<Type>): IntrinsicType & UnionType {
|
||||
const type = <IntrinsicType & UnionType>getUnionType(trueFalseTypes);
|
||||
type.flags |= TypeFlags.Boolean;
|
||||
@@ -5128,7 +5146,7 @@ namespace ts {
|
||||
definedInConstructor = true;
|
||||
}
|
||||
}
|
||||
const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes : types; // TODO: GH#18217
|
||||
const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217
|
||||
type = getUnionType(sourceTypes!, UnionReduction.Subtype);
|
||||
}
|
||||
const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor));
|
||||
@@ -5293,7 +5311,7 @@ namespace ts {
|
||||
function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type {
|
||||
const members = createSymbolTable();
|
||||
let stringIndexInfo: IndexInfo | undefined;
|
||||
let objectFlags = ObjectFlags.ObjectLiteral;
|
||||
let objectFlags = ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral;
|
||||
forEach(pattern.elements, e => {
|
||||
const name = e.propertyName || <Identifier>e.name;
|
||||
if (e.dotDotDotToken) {
|
||||
@@ -5315,7 +5333,6 @@ namespace ts {
|
||||
members.set(symbol.escapedName, symbol);
|
||||
});
|
||||
const result = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, undefined);
|
||||
result.flags |= TypeFlags.ContainsObjectLiteral;
|
||||
result.objectFlags |= objectFlags;
|
||||
if (includePatternInType) {
|
||||
result.pattern = pattern;
|
||||
@@ -5408,7 +5425,16 @@ namespace ts {
|
||||
|
||||
function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type {
|
||||
const links = getSymbolLinks(symbol);
|
||||
return links.type || (links.type = getTypeOfVariableOrParameterOrPropertyWorker(symbol));
|
||||
if (!links.type) {
|
||||
const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol);
|
||||
// For a contextually typed parameter it is possible that a type has already
|
||||
// been assigned (in assignTypeToParameterAndFixTypeParameters), and we want
|
||||
// to preserve this type.
|
||||
if (!links.type) {
|
||||
links.type = type;
|
||||
}
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
|
||||
function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol) {
|
||||
@@ -5452,7 +5478,7 @@ namespace ts {
|
||||
if (symbol.flags & SymbolFlags.ValueModule) {
|
||||
return getTypeOfFuncClassEnumModule(symbol);
|
||||
}
|
||||
return errorType;
|
||||
return reportCircularityError(symbol);
|
||||
}
|
||||
let type: Type | undefined;
|
||||
if (isInJSFile(declaration) &&
|
||||
@@ -5511,7 +5537,7 @@ namespace ts {
|
||||
if (symbol.flags & SymbolFlags.ValueModule) {
|
||||
return getTypeOfFuncClassEnumModule(symbol);
|
||||
}
|
||||
type = reportCircularityError(symbol);
|
||||
return reportCircularityError(symbol);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -8540,14 +8566,14 @@ namespace ts {
|
||||
// It is only necessary to do so if a constituent type might be the undefined type, the null type, the type
|
||||
// of an object literal or the anyFunctionType. This is because there are operations in the type checker
|
||||
// that care about the presence of such types at arbitrary depth in a containing type.
|
||||
function getPropagatingFlagsOfTypes(types: ReadonlyArray<Type>, excludeKinds: TypeFlags): TypeFlags {
|
||||
let result: TypeFlags = 0;
|
||||
function getPropagatingFlagsOfTypes(types: ReadonlyArray<Type>, excludeKinds: TypeFlags): ObjectFlags {
|
||||
let result: ObjectFlags = 0;
|
||||
for (const type of types) {
|
||||
if (!(type.flags & excludeKinds)) {
|
||||
result |= type.flags;
|
||||
result |= getObjectFlags(type);
|
||||
}
|
||||
}
|
||||
return result & TypeFlags.PropagatingFlags;
|
||||
return result & ObjectFlags.PropagatingFlags;
|
||||
}
|
||||
|
||||
function createTypeReference(target: GenericType, typeArguments: ReadonlyArray<Type> | undefined): TypeReference {
|
||||
@@ -8556,7 +8582,7 @@ namespace ts {
|
||||
if (!type) {
|
||||
type = <TypeReference>createObjectType(ObjectFlags.Reference, target.symbol);
|
||||
target.instantiations.set(id, type);
|
||||
type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0;
|
||||
type.objectFlags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0;
|
||||
type.target = target;
|
||||
type.typeArguments = typeArguments;
|
||||
}
|
||||
@@ -9235,10 +9261,11 @@ namespace ts {
|
||||
// intersections of unit types into 'never' upon construction, but deferring the reduction makes it
|
||||
// easier to reason about their origin.
|
||||
if (!(flags & TypeFlags.Never || flags & TypeFlags.Intersection && isEmptyIntersectionType(<IntersectionType>type))) {
|
||||
includes |= flags & ~TypeFlags.ConstructionFlags;
|
||||
if (type === wildcardType) includes |= TypeFlags.Wildcard;
|
||||
includes |= flags & TypeFlags.IncludesMask;
|
||||
if (flags & TypeFlags.StructuredOrInstantiable) includes |= TypeFlags.IncludesStructuredOrInstantiable;
|
||||
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
|
||||
if (!strictNullChecks && flags & TypeFlags.Nullable) {
|
||||
if (!(flags & TypeFlags.ContainsWideningType)) includes |= TypeFlags.NonWideningType;
|
||||
if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType;
|
||||
}
|
||||
else {
|
||||
const len = typeSet.length;
|
||||
@@ -9349,27 +9376,27 @@ namespace ts {
|
||||
const includes = addTypesToUnion(typeSet, 0, types);
|
||||
if (unionReduction !== UnionReduction.None) {
|
||||
if (includes & TypeFlags.AnyOrUnknown) {
|
||||
return includes & TypeFlags.Any ? includes & TypeFlags.Wildcard ? wildcardType : anyType : unknownType;
|
||||
return includes & TypeFlags.Any ? includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : unknownType;
|
||||
}
|
||||
switch (unionReduction) {
|
||||
case UnionReduction.Literal:
|
||||
if (includes & TypeFlags.StringOrNumberLiteralOrUnique | TypeFlags.BooleanLiteral) {
|
||||
if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol)) {
|
||||
removeRedundantLiteralTypes(typeSet, includes);
|
||||
}
|
||||
break;
|
||||
case UnionReduction.Subtype:
|
||||
if (!removeSubtypes(typeSet, !(includes & TypeFlags.StructuredOrInstantiable))) {
|
||||
if (!removeSubtypes(typeSet, !(includes & TypeFlags.IncludesStructuredOrInstantiable))) {
|
||||
return errorType;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (typeSet.length === 0) {
|
||||
return includes & TypeFlags.Null ? includes & TypeFlags.NonWideningType ? nullType : nullWideningType :
|
||||
includes & TypeFlags.Undefined ? includes & TypeFlags.NonWideningType ? undefinedType : undefinedWideningType :
|
||||
return includes & TypeFlags.Null ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType :
|
||||
includes & TypeFlags.Undefined ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType :
|
||||
neverType;
|
||||
}
|
||||
}
|
||||
return getUnionTypeFromSortedList(typeSet, !(includes & TypeFlags.NotPrimitiveUnion), aliasSymbol, aliasTypeArguments);
|
||||
return getUnionTypeFromSortedList(typeSet, includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion, aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
|
||||
function getUnionTypePredicate(signatures: ReadonlyArray<Signature>): TypePredicate | undefined {
|
||||
@@ -9409,7 +9436,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// This function assumes the constituent type list is sorted and deduplicated.
|
||||
function getUnionTypeFromSortedList(types: Type[], primitiveTypesOnly: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>): Type {
|
||||
function getUnionTypeFromSortedList(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>): Type {
|
||||
if (types.length === 0) {
|
||||
return neverType;
|
||||
}
|
||||
@@ -9419,11 +9446,10 @@ namespace ts {
|
||||
const id = getTypeListId(types);
|
||||
let type = unionTypes.get(id);
|
||||
if (!type) {
|
||||
const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type = <UnionType>createType(TypeFlags.Union | propagatedFlags);
|
||||
type = <UnionType>createType(TypeFlags.Union);
|
||||
unionTypes.set(id, type);
|
||||
type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type.types = types;
|
||||
type.primitiveTypesOnly = primitiveTypesOnly;
|
||||
/*
|
||||
Note: This is the alias symbol (or lack thereof) that we see when we first encounter this union type.
|
||||
For aliases of identical unions, eg `type T = A | B; type U = A | B`, the symbol of the first alias encountered is the aliasSymbol.
|
||||
@@ -9452,15 +9478,15 @@ namespace ts {
|
||||
return addTypesToIntersection(typeSet, includes, (<IntersectionType>type).types);
|
||||
}
|
||||
if (isEmptyAnonymousObjectType(type)) {
|
||||
if (!(includes & TypeFlags.EmptyObject)) {
|
||||
includes |= TypeFlags.EmptyObject;
|
||||
if (!(includes & TypeFlags.IncludesEmptyObject)) {
|
||||
includes |= TypeFlags.IncludesEmptyObject;
|
||||
typeSet.push(type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
includes |= flags & ~TypeFlags.ConstructionFlags;
|
||||
includes |= flags & TypeFlags.IncludesMask;
|
||||
if (flags & TypeFlags.AnyOrUnknown) {
|
||||
if (type === wildcardType) includes |= TypeFlags.Wildcard;
|
||||
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
|
||||
}
|
||||
else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
|
||||
typeSet.push(type);
|
||||
@@ -9518,7 +9544,7 @@ namespace ts {
|
||||
// other unions and return true. Otherwise, do nothing and return false.
|
||||
function intersectUnionsOfPrimitiveTypes(types: Type[]) {
|
||||
let unionTypes: UnionType[] | undefined;
|
||||
const index = findIndex(types, t => !!(t.flags & TypeFlags.Union) && (<UnionType>t).primitiveTypesOnly);
|
||||
const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFlags.PrimitiveUnion));
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -9527,7 +9553,7 @@ namespace ts {
|
||||
// the unionTypes array.
|
||||
while (i < types.length) {
|
||||
const t = types[i];
|
||||
if (t.flags & TypeFlags.Union && (<UnionType>t).primitiveTypesOnly) {
|
||||
if (getObjectFlags(t) & ObjectFlags.PrimitiveUnion) {
|
||||
(unionTypes || (unionTypes = [<UnionType>types[index]])).push(<UnionType>t);
|
||||
orderedRemoveItemAt(types, i);
|
||||
}
|
||||
@@ -9554,7 +9580,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
// Finally replace the first union with the result
|
||||
types[index] = getUnionTypeFromSortedList(result, /*primitiveTypesOnly*/ true);
|
||||
types[index] = getUnionTypeFromSortedList(result, ObjectFlags.PrimitiveUnion);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9575,7 +9601,7 @@ namespace ts {
|
||||
return neverType;
|
||||
}
|
||||
if (includes & TypeFlags.Any) {
|
||||
return includes & TypeFlags.Wildcard ? wildcardType : anyType;
|
||||
return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType;
|
||||
}
|
||||
if (!strictNullChecks && includes & TypeFlags.Nullable) {
|
||||
return includes & TypeFlags.Undefined ? undefinedType : nullType;
|
||||
@@ -9586,7 +9612,7 @@ namespace ts {
|
||||
includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol) {
|
||||
removeRedundantPrimitiveTypes(typeSet, includes);
|
||||
}
|
||||
if (includes & TypeFlags.EmptyObject && includes & TypeFlags.Object) {
|
||||
if (includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.Object) {
|
||||
orderedRemoveItemAt(typeSet, findIndex(typeSet, isEmptyAnonymousObjectType));
|
||||
}
|
||||
if (typeSet.length === 0) {
|
||||
@@ -9612,9 +9638,9 @@ namespace ts {
|
||||
const id = getTypeListId(typeSet);
|
||||
let type = intersectionTypes.get(id);
|
||||
if (!type) {
|
||||
const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type = <IntersectionType>createType(TypeFlags.Intersection | propagatedFlags);
|
||||
type = <IntersectionType>createType(TypeFlags.Intersection);
|
||||
intersectionTypes.set(id, type);
|
||||
type.objectFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
type.types = typeSet;
|
||||
type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`.
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
@@ -10273,7 +10299,7 @@ namespace ts {
|
||||
* this function should be called in a left folding style, with left = previous result of getSpreadType
|
||||
* and right = the new element to be spread.
|
||||
*/
|
||||
function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, typeFlags: TypeFlags, objectFlags: ObjectFlags, readonly: boolean): Type {
|
||||
function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type {
|
||||
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
|
||||
return anyType;
|
||||
}
|
||||
@@ -10287,10 +10313,10 @@ namespace ts {
|
||||
return left;
|
||||
}
|
||||
if (left.flags & TypeFlags.Union) {
|
||||
return mapType(left, t => getSpreadType(t, right, symbol, typeFlags, objectFlags, readonly));
|
||||
return mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly));
|
||||
}
|
||||
if (right.flags & TypeFlags.Union) {
|
||||
return mapType(right, t => getSpreadType(left, t, symbol, typeFlags, objectFlags, readonly));
|
||||
return mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly));
|
||||
}
|
||||
if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) {
|
||||
return left;
|
||||
@@ -10307,7 +10333,7 @@ namespace ts {
|
||||
const types = (<IntersectionType>left).types;
|
||||
const lastLeft = types[types.length - 1];
|
||||
if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) {
|
||||
return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, typeFlags, objectFlags, readonly)]));
|
||||
return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)]));
|
||||
}
|
||||
}
|
||||
return getIntersectionType([left, right]);
|
||||
@@ -10367,8 +10393,7 @@ namespace ts {
|
||||
emptyArray,
|
||||
getIndexInfoWithReadonly(stringIndexInfo, readonly),
|
||||
getIndexInfoWithReadonly(numberIndexInfo, readonly));
|
||||
spread.flags |= TypeFlags.ContainsObjectLiteral | typeFlags;
|
||||
spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsSpread | objectFlags;
|
||||
spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral | ObjectFlags.ContainsSpread | objectFlags;
|
||||
return spread;
|
||||
}
|
||||
|
||||
@@ -12570,6 +12595,7 @@ namespace ts {
|
||||
|
||||
let result: Ternary;
|
||||
let originalErrorInfo: DiagnosticMessageChain | undefined;
|
||||
let varianceCheckFailed = false;
|
||||
const saveErrorInfo = errorInfo;
|
||||
|
||||
// We limit alias variance probing to only object and conditional types since their alias behavior
|
||||
@@ -12579,11 +12605,10 @@ namespace ts {
|
||||
source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol &&
|
||||
!(source.aliasTypeArgumentsContainsMarker || target.aliasTypeArgumentsContainsMarker)) {
|
||||
const variances = getAliasVariances(source.aliasSymbol);
|
||||
if (result = typeArgumentsRelatedTo(source.aliasTypeArguments, target.aliasTypeArguments, variances, reportErrors)) {
|
||||
return result;
|
||||
const varianceResult = relateVariances(source.aliasTypeArguments, target.aliasTypeArguments, variances);
|
||||
if (varianceResult !== undefined) {
|
||||
return varianceResult;
|
||||
}
|
||||
originalErrorInfo = errorInfo;
|
||||
errorInfo = saveErrorInfo;
|
||||
}
|
||||
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
@@ -12748,31 +12773,9 @@ namespace ts {
|
||||
// type references (which are intended by be compared structurally). Obtain the variance
|
||||
// information for the type parameters and relate the type arguments accordingly.
|
||||
const variances = getVariances((<TypeReference>source).target);
|
||||
if (result = typeArgumentsRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, variances, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
// The type arguments did not relate appropriately, but it may be because we have no variance
|
||||
// information (in which case typeArgumentsRelatedTo defaulted to covariance for all type
|
||||
// arguments). It might also be the case that the target type has a 'void' type argument for
|
||||
// a covariant type parameter that is only used in return positions within the generic type
|
||||
// (in which case any type argument is permitted on the source side). In those cases we proceed
|
||||
// with a structural comparison. Otherwise, we know for certain the instantiations aren't
|
||||
// related and we can return here.
|
||||
if (variances !== emptyArray && !hasCovariantVoidArgument(<TypeReference>target, variances)) {
|
||||
// In some cases generic types that are covariant in regular type checking mode become
|
||||
// invariant in --strictFunctionTypes mode because one or more type parameters are used in
|
||||
// both co- and contravariant positions. In order to make it easier to diagnose *why* such
|
||||
// types are invariant, if any of the type parameters are invariant we reset the reported
|
||||
// errors and instead force a structural comparison (which will include elaborations that
|
||||
// reveal the reason).
|
||||
if (!(reportErrors && some(variances, v => v === Variance.Invariant))) {
|
||||
return Ternary.False;
|
||||
}
|
||||
// We remember the original error information so we can restore it in case the structural
|
||||
// comparison unexpectedly succeeds. This can happen when the structural comparison result
|
||||
// is a Ternary.Maybe for example caused by the recursion depth limiter.
|
||||
originalErrorInfo = errorInfo;
|
||||
errorInfo = saveErrorInfo;
|
||||
const varianceResult = relateVariances((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, variances);
|
||||
if (varianceResult !== undefined) {
|
||||
return varianceResult;
|
||||
}
|
||||
}
|
||||
else if (isReadonlyArrayType(target) ? isArrayType(source) || isTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
|
||||
@@ -12799,16 +12802,48 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result) {
|
||||
if (!originalErrorInfo) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
errorInfo = originalErrorInfo;
|
||||
if (varianceCheckFailed && result) {
|
||||
errorInfo = originalErrorInfo || errorInfo || saveErrorInfo; // Use variance error (there is no structural one) and return false
|
||||
}
|
||||
else if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
|
||||
function relateVariances(sourceTypeArguments: ReadonlyArray<Type> | undefined, targetTypeArguments: ReadonlyArray<Type> | undefined, variances: Variance[]) {
|
||||
if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
const isCovariantVoid = targetTypeArguments && hasCovariantVoidArgument(targetTypeArguments, variances);
|
||||
varianceCheckFailed = !isCovariantVoid;
|
||||
// The type arguments did not relate appropriately, but it may be because we have no variance
|
||||
// information (in which case typeArgumentsRelatedTo defaulted to covariance for all type
|
||||
// arguments). It might also be the case that the target type has a 'void' type argument for
|
||||
// a covariant type parameter that is only used in return positions within the generic type
|
||||
// (in which case any type argument is permitted on the source side). In those cases we proceed
|
||||
// with a structural comparison. Otherwise, we know for certain the instantiations aren't
|
||||
// related and we can return here.
|
||||
if (variances !== emptyArray && !isCovariantVoid) {
|
||||
// In some cases generic types that are covariant in regular type checking mode become
|
||||
// invariant in --strictFunctionTypes mode because one or more type parameters are used in
|
||||
// both co- and contravariant positions. In order to make it easier to diagnose *why* such
|
||||
// types are invariant, if any of the type parameters are invariant we reset the reported
|
||||
// errors and instead force a structural comparison (which will include elaborations that
|
||||
// reveal the reason).
|
||||
// We can switch on `reportErrors` here, since varianceCheckFailed guarantees we return `False`,
|
||||
// we can return `False` early here to skip calculating the structural error message we don't need.
|
||||
if (varianceCheckFailed && !(reportErrors && some(variances, v => v === Variance.Invariant))) {
|
||||
return Ternary.False;
|
||||
}
|
||||
// We remember the original error information so we can restore it in case the structural
|
||||
// comparison unexpectedly succeeds. This can happen when the structural comparison result
|
||||
// is a Ternary.Maybe for example caused by the recursion depth limiter.
|
||||
originalErrorInfo = errorInfo;
|
||||
errorInfo = saveErrorInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is
|
||||
@@ -13317,7 +13352,7 @@ namespace ts {
|
||||
|
||||
function getVariances(type: GenericType): Variance[] {
|
||||
// Arrays and tuples are known to be covariant, no need to spend time computing this (emptyArray implies covariance for all parameters)
|
||||
if (!strictFunctionTypes || type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple) {
|
||||
if (type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple) {
|
||||
return emptyArray;
|
||||
}
|
||||
return getVariancesWorker(type.typeParameters, type, getMarkerTypeReference);
|
||||
@@ -13325,9 +13360,9 @@ namespace ts {
|
||||
|
||||
// Return true if the given type reference has a 'void' type argument for a covariant type parameter.
|
||||
// See comment at call in recursiveTypeRelatedTo for when this case matters.
|
||||
function hasCovariantVoidArgument(type: TypeReference, variances: Variance[]): boolean {
|
||||
function hasCovariantVoidArgument(typeArguments: ReadonlyArray<Type>, variances: Variance[]): boolean {
|
||||
for (let i = 0; i < variances.length; i++) {
|
||||
if (variances[i] === Variance.Covariant && type.typeArguments![i].flags & TypeFlags.Void) {
|
||||
if (variances[i] === Variance.Covariant && typeArguments[i].flags & TypeFlags.Void) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -13853,7 +13888,7 @@ namespace ts {
|
||||
resolved.stringIndexInfo,
|
||||
resolved.numberIndexInfo);
|
||||
regularNew.flags = resolved.flags;
|
||||
regularNew.objectFlags |= ObjectFlags.ObjectLiteral | (getObjectFlags(resolved) & ObjectFlags.JSLiteral);
|
||||
regularNew.objectFlags |= resolved.objectFlags & ~ObjectFlags.FreshLiteral;
|
||||
(<FreshObjectLiteralType>type).regularType = regularNew;
|
||||
return regularNew;
|
||||
}
|
||||
@@ -13944,7 +13979,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type {
|
||||
if (type.flags & TypeFlags.RequiresWidening) {
|
||||
if (getObjectFlags(type) & ObjectFlags.RequiresWidening) {
|
||||
if (type.flags & TypeFlags.Nullable) {
|
||||
return anyType;
|
||||
}
|
||||
@@ -13982,7 +14017,7 @@ namespace ts {
|
||||
*/
|
||||
function reportWideningErrorsInType(type: Type): boolean {
|
||||
let errorReported = false;
|
||||
if (type.flags & TypeFlags.ContainsWideningType) {
|
||||
if (getObjectFlags(type) & ObjectFlags.ContainsWideningType) {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
if (some((<UnionType>type).types, isEmptyObjectType)) {
|
||||
errorReported = true;
|
||||
@@ -14005,7 +14040,7 @@ namespace ts {
|
||||
if (isObjectLiteralType(type)) {
|
||||
for (const p of getPropertiesOfObjectType(type)) {
|
||||
const t = getTypeOfSymbol(p);
|
||||
if (t.flags & TypeFlags.ContainsWideningType) {
|
||||
if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) {
|
||||
if (!reportWideningErrorsInType(t)) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t)));
|
||||
}
|
||||
@@ -14080,7 +14115,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
|
||||
if (produceDiagnostics && noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
|
||||
if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType) {
|
||||
// Report implicit any error within type if possible, otherwise report error on declaration
|
||||
if (!reportWideningErrorsInType(type)) {
|
||||
reportImplicitAny(declaration, type);
|
||||
@@ -14225,7 +14260,7 @@ namespace ts {
|
||||
// If any property contains context sensitive functions that have been skipped, the source type
|
||||
// is incomplete and we can't infer a meaningful input type.
|
||||
for (const prop of properties) {
|
||||
if (getTypeOfSymbol(prop).flags & TypeFlags.ContainsAnyFunctionType) {
|
||||
if (getObjectFlags(getTypeOfSymbol(prop)) & ObjectFlags.ContainsAnyFunctionType) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -14383,7 +14418,7 @@ namespace ts {
|
||||
// not contain anyFunctionType when we come back to this argument for its second round
|
||||
// of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard
|
||||
// when constructing types from type parameters that had no inference candidates).
|
||||
if (source.flags & TypeFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
|
||||
if (getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
|
||||
return;
|
||||
}
|
||||
const inference = getInferenceInfoForType(target);
|
||||
@@ -14686,7 +14721,7 @@ namespace ts {
|
||||
const sourceLen = sourceSignatures.length;
|
||||
const targetLen = targetSignatures.length;
|
||||
const len = sourceLen < targetLen ? sourceLen : targetLen;
|
||||
const skipParameters = !!(source.flags & TypeFlags.ContainsAnyFunctionType);
|
||||
const skipParameters = !!(getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType);
|
||||
for (let i = 0; i < len; i++) {
|
||||
inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i]), skipParameters);
|
||||
}
|
||||
@@ -15444,7 +15479,7 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
const types = (<UnionType>type).types;
|
||||
const filtered = filter(types, f);
|
||||
return filtered === types ? type : getUnionTypeFromSortedList(filtered, (<UnionType>type).primitiveTypesOnly);
|
||||
return filtered === types ? type : getUnionTypeFromSortedList(filtered, (<UnionType>type).objectFlags);
|
||||
}
|
||||
return f(type) ? type : neverType;
|
||||
}
|
||||
@@ -18350,7 +18385,6 @@ namespace ts {
|
||||
let propertiesTable: SymbolTable;
|
||||
let propertiesArray: Symbol[] = [];
|
||||
let spread: Type = emptyObjectType;
|
||||
let propagatedFlags: TypeFlags = 0;
|
||||
|
||||
const contextualType = getApparentTypeOfContextualType(node);
|
||||
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
||||
@@ -18360,7 +18394,7 @@ namespace ts {
|
||||
const isInJavascript = isInJSFile(node) && !isInJsonFile(node);
|
||||
const enumTag = getJSDocEnumTag(node);
|
||||
const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag;
|
||||
let typeFlags: TypeFlags = 0;
|
||||
let objectFlags: ObjectFlags = freshObjectLiteralFlag;
|
||||
let patternWithComputedProperties = false;
|
||||
let hasComputedStringProperty = false;
|
||||
let hasComputedNumberProperty = false;
|
||||
@@ -18388,7 +18422,7 @@ namespace ts {
|
||||
checkTypeAssignableTo(type, getTypeFromTypeNode(enumTag.typeExpression), memberDecl);
|
||||
}
|
||||
}
|
||||
typeFlags |= type.flags;
|
||||
objectFlags |= getObjectFlags(type) & ObjectFlags.PropagatingFlags;
|
||||
const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined;
|
||||
const prop = nameType ?
|
||||
createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | CheckFlags.Late) :
|
||||
@@ -18436,19 +18470,18 @@ namespace ts {
|
||||
checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign);
|
||||
}
|
||||
if (propertiesArray.length > 0) {
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext);
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
|
||||
propertiesArray = [];
|
||||
propertiesTable = createSymbolTable();
|
||||
hasComputedStringProperty = false;
|
||||
hasComputedNumberProperty = false;
|
||||
typeFlags = 0;
|
||||
}
|
||||
const type = checkExpression(memberDecl.expression);
|
||||
if (!isValidSpreadType(type)) {
|
||||
error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
|
||||
return errorType;
|
||||
}
|
||||
spread = getSpreadType(spread, type, node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext);
|
||||
spread = getSpreadType(spread, type, node.symbol, objectFlags, inConstContext);
|
||||
offset = i + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -18498,7 +18531,7 @@ namespace ts {
|
||||
|
||||
if (spread !== emptyObjectType) {
|
||||
if (propertiesArray.length > 0) {
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, ObjectFlags.FreshLiteral, inConstContext);
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
|
||||
}
|
||||
return spread;
|
||||
}
|
||||
@@ -18509,8 +18542,7 @@ namespace ts {
|
||||
const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, offset, propertiesArray, IndexKind.String) : undefined;
|
||||
const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, offset, propertiesArray, IndexKind.Number) : undefined;
|
||||
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags & TypeFlags.PropagatingFlags;
|
||||
result.objectFlags |= ObjectFlags.ObjectLiteral | freshObjectLiteralFlag;
|
||||
result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral;
|
||||
if (isJSObjectLiteral) {
|
||||
result.objectFlags |= ObjectFlags.JSLiteral;
|
||||
}
|
||||
@@ -18520,7 +18552,6 @@ namespace ts {
|
||||
if (inDestructuringPattern) {
|
||||
result.pattern = node;
|
||||
}
|
||||
propagatedFlags |= result.flags & TypeFlags.PropagatingFlags;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -18611,7 +18642,6 @@ namespace ts {
|
||||
let hasSpreadAnyType = false;
|
||||
let typeToIntersect: Type | undefined;
|
||||
let explicitlySpecifyChildrenAttribute = false;
|
||||
let typeFlags: TypeFlags = 0;
|
||||
let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes;
|
||||
const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement));
|
||||
|
||||
@@ -18619,7 +18649,7 @@ namespace ts {
|
||||
const member = attributeDecl.symbol;
|
||||
if (isJsxAttribute(attributeDecl)) {
|
||||
const exprType = checkJsxAttribute(attributeDecl, checkMode);
|
||||
typeFlags |= exprType.flags & TypeFlags.PropagatingFlags;
|
||||
objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags;
|
||||
|
||||
const attributeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.escapedName);
|
||||
attributeSymbol.declarations = member.declarations;
|
||||
@@ -18637,7 +18667,7 @@ namespace ts {
|
||||
else {
|
||||
Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute);
|
||||
if (attributesTable.size > 0) {
|
||||
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags, /*readonly*/ false);
|
||||
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
|
||||
attributesTable = createSymbolTable();
|
||||
}
|
||||
const exprType = checkExpressionCached(attributeDecl.expression, checkMode);
|
||||
@@ -18645,7 +18675,7 @@ namespace ts {
|
||||
hasSpreadAnyType = true;
|
||||
}
|
||||
if (isValidSpreadType(exprType)) {
|
||||
spread = getSpreadType(spread, exprType, attributes.symbol, typeFlags, objectFlags, /*readonly*/ false);
|
||||
spread = getSpreadType(spread, exprType, attributes.symbol, objectFlags, /*readonly*/ false);
|
||||
}
|
||||
else {
|
||||
typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType;
|
||||
@@ -18655,7 +18685,7 @@ namespace ts {
|
||||
|
||||
if (!hasSpreadAnyType) {
|
||||
if (attributesTable.size > 0) {
|
||||
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, typeFlags, objectFlags, /*readonly*/ false);
|
||||
spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18687,7 +18717,7 @@ namespace ts {
|
||||
const childPropMap = createSymbolTable();
|
||||
childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol);
|
||||
spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined),
|
||||
attributes.symbol, typeFlags, objectFlags, /*readonly*/ false);
|
||||
attributes.symbol, objectFlags, /*readonly*/ false);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -18708,8 +18738,7 @@ namespace ts {
|
||||
function createJsxAttributesType() {
|
||||
objectFlags |= freshObjectLiteralFlag;
|
||||
const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
|
||||
result.flags |= TypeFlags.ContainsObjectLiteral | typeFlags;
|
||||
result.objectFlags |= ObjectFlags.ObjectLiteral | objectFlags;
|
||||
result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectLiteral;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -21374,7 +21403,7 @@ namespace ts {
|
||||
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
|
||||
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
|
||||
anonymousSymbol.type = defaultContainingObject;
|
||||
synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*typeFLags*/ 0, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject;
|
||||
synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject;
|
||||
}
|
||||
else {
|
||||
synthType.syntheticType = type;
|
||||
@@ -22052,7 +22081,7 @@ namespace ts {
|
||||
const returnType = getReturnTypeFromBody(node, checkMode);
|
||||
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined);
|
||||
returnOnlyType.flags |= TypeFlags.ContainsAnyFunctionType;
|
||||
returnOnlyType.objectFlags |= ObjectFlags.ContainsAnyFunctionType;
|
||||
return links.contextFreeType = returnOnlyType;
|
||||
}
|
||||
return anyFunctionType;
|
||||
|
||||
@@ -2581,6 +2581,10 @@
|
||||
"category": "Error",
|
||||
"code": 2748
|
||||
},
|
||||
"'{0}' refers to a value, but is being used as a type here.": {
|
||||
"category": "Error",
|
||||
"code": 2749
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
+1
-7
@@ -632,7 +632,7 @@ namespace ts {
|
||||
getModifiedTime,
|
||||
setModifiedTime,
|
||||
deleteFile,
|
||||
createHash: _crypto ? createMD5HashUsingNativeCrypto : generateDjb2Hash,
|
||||
createHash: _crypto ? createSHA256Hash : generateDjb2Hash,
|
||||
createSHA256Hash: _crypto ? createSHA256Hash : undefined,
|
||||
getMemoryUsage() {
|
||||
if (global.gc) {
|
||||
@@ -1125,12 +1125,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createMD5HashUsingNativeCrypto(data: string): string {
|
||||
const hash = _crypto!.createHash("md5");
|
||||
hash.update(data);
|
||||
return hash.digest("hex");
|
||||
}
|
||||
|
||||
function createSHA256Hash(data: string): string {
|
||||
const hash = _crypto!.createHash("sha256");
|
||||
hash.update(data);
|
||||
|
||||
+60
-45
@@ -3881,39 +3881,33 @@ namespace ts {
|
||||
}
|
||||
|
||||
export const enum TypeFlags {
|
||||
Any = 1 << 0,
|
||||
Unknown = 1 << 1,
|
||||
String = 1 << 2,
|
||||
Number = 1 << 3,
|
||||
Boolean = 1 << 4,
|
||||
Enum = 1 << 5,
|
||||
BigInt = 1 << 6,
|
||||
StringLiteral = 1 << 7,
|
||||
NumberLiteral = 1 << 8,
|
||||
BooleanLiteral = 1 << 9,
|
||||
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
|
||||
BigIntLiteral = 1 << 11,
|
||||
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
|
||||
UniqueESSymbol = 1 << 13, // unique symbol
|
||||
Void = 1 << 14,
|
||||
Undefined = 1 << 15,
|
||||
Null = 1 << 16,
|
||||
Never = 1 << 17, // Never type
|
||||
TypeParameter = 1 << 18, // Type parameter
|
||||
Object = 1 << 19, // Object type
|
||||
Union = 1 << 20, // Union (T | U)
|
||||
Intersection = 1 << 21, // Intersection (T & U)
|
||||
Index = 1 << 22, // keyof T
|
||||
IndexedAccess = 1 << 23, // T[K]
|
||||
Conditional = 1 << 24, // T extends U ? X : Y
|
||||
Substitution = 1 << 25, // Type parameter substitution
|
||||
NonPrimitive = 1 << 26, // intrinsic object type
|
||||
/* @internal */
|
||||
ContainsWideningType = 1 << 27, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 1 << 28, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 29, // Type is or contains the anyFunctionType
|
||||
Any = 1 << 0,
|
||||
Unknown = 1 << 1,
|
||||
String = 1 << 2,
|
||||
Number = 1 << 3,
|
||||
Boolean = 1 << 4,
|
||||
Enum = 1 << 5,
|
||||
BigInt = 1 << 6,
|
||||
StringLiteral = 1 << 7,
|
||||
NumberLiteral = 1 << 8,
|
||||
BooleanLiteral = 1 << 9,
|
||||
EnumLiteral = 1 << 10, // Always combined with StringLiteral, NumberLiteral, or Union
|
||||
BigIntLiteral = 1 << 11,
|
||||
ESSymbol = 1 << 12, // Type of symbol primitive introduced in ES6
|
||||
UniqueESSymbol = 1 << 13, // unique symbol
|
||||
Void = 1 << 14,
|
||||
Undefined = 1 << 15,
|
||||
Null = 1 << 16,
|
||||
Never = 1 << 17, // Never type
|
||||
TypeParameter = 1 << 18, // Type parameter
|
||||
Object = 1 << 19, // Object type
|
||||
Union = 1 << 20, // Union (T | U)
|
||||
Intersection = 1 << 21, // Intersection (T & U)
|
||||
Index = 1 << 22, // keyof T
|
||||
IndexedAccess = 1 << 23, // T[K]
|
||||
Conditional = 1 << 24, // T extends U ? X : Y
|
||||
Substitution = 1 << 25, // Type parameter substitution
|
||||
NonPrimitive = 1 << 26, // intrinsic object type
|
||||
|
||||
/* @internal */
|
||||
AnyOrUnknown = Any | Unknown,
|
||||
@@ -3947,29 +3941,29 @@ namespace ts {
|
||||
InstantiablePrimitive = Index,
|
||||
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
|
||||
StructuredOrInstantiable = StructuredType | Instantiable,
|
||||
|
||||
/* @internal */
|
||||
ObjectFlagsType = Nullable | Object | Union | Intersection,
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
// This *should* be every type other than null, undefined, void, and never
|
||||
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
|
||||
NotUnionOrUnit = Any | Unknown | ESSymbol | Object | NonPrimitive,
|
||||
/* @internal */
|
||||
NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | StructuredOrInstantiable,
|
||||
// The following flags are aggregated during union and intersection type construction
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType,
|
||||
IncludesMask = Any | Unknown | Primitive | Never | Object | Union,
|
||||
// The following flags are used for different purposes during union and intersection type construction
|
||||
/* @internal */
|
||||
NonWideningType = ContainsWideningType,
|
||||
IncludesStructuredOrInstantiable = TypeParameter,
|
||||
/* @internal */
|
||||
Wildcard = ContainsObjectLiteral,
|
||||
IncludesNonWideningType = Intersection,
|
||||
/* @internal */
|
||||
EmptyObject = ContainsAnyFunctionType,
|
||||
IncludesWildcard = Index,
|
||||
/* @internal */
|
||||
ConstructionFlags = NonWideningType | Wildcard | EmptyObject,
|
||||
IncludesEmptyObject = IndexedAccess,
|
||||
// The following flag is used for different purposes by maybeTypeOfKind
|
||||
/* @internal */
|
||||
GenericMappedType = ContainsWideningType
|
||||
GenericMappedType = Never,
|
||||
}
|
||||
|
||||
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
|
||||
@@ -3996,6 +3990,12 @@ namespace ts {
|
||||
// Intrinsic types (TypeFlags.Intrinsic)
|
||||
export interface IntrinsicType extends Type {
|
||||
intrinsicName: string; // Name of intrinsic type
|
||||
objectFlags: ObjectFlags;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface NullableType extends IntrinsicType {
|
||||
objectFlags: ObjectFlags;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -4055,9 +4055,24 @@ namespace ts {
|
||||
MarkerType = 1 << 13, // Marker type used for variance probing
|
||||
JSLiteral = 1 << 14, // Object type declared in JS - disables errors on read/write of nonexisting members
|
||||
FreshLiteral = 1 << 15, // Fresh object literal
|
||||
ClassOrInterface = Class | Interface
|
||||
/* @internal */
|
||||
PrimitiveUnion = 1 << 16, // Union of only primitive types
|
||||
/* @internal */
|
||||
ContainsWideningType = 1 << 17, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 1 << 18, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
ContainsAnyFunctionType = 1 << 19, // Type is or contains the anyFunctionType
|
||||
ClassOrInterface = Class | Interface,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type ObjectFlagsType = NullableType | ObjectType | UnionType | IntersectionType;
|
||||
|
||||
// Object types (TypeFlags.ObjectType)
|
||||
export interface ObjectType extends Type {
|
||||
objectFlags: ObjectFlags;
|
||||
@@ -4138,6 +4153,8 @@ namespace ts {
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
objectFlags: ObjectFlags;
|
||||
/* @internal */
|
||||
propertyCache: SymbolTable; // Cache of resolved properties
|
||||
/* @internal */
|
||||
resolvedProperties: Symbol[];
|
||||
@@ -4152,8 +4169,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface UnionType extends UnionOrIntersectionType {
|
||||
/* @internal */
|
||||
primitiveTypesOnly: boolean;
|
||||
}
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType {
|
||||
|
||||
@@ -4520,7 +4520,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getObjectFlags(type: Type): ObjectFlags {
|
||||
return type.flags & TypeFlags.Object ? (<ObjectType>type).objectFlags : 0;
|
||||
return type.flags & TypeFlags.ObjectFlagsType ? (<ObjectFlagsType>type).objectFlags : 0;
|
||||
}
|
||||
|
||||
export function typeHasCallOrConstructSignatures(type: Type, checker: TypeChecker) {
|
||||
|
||||
@@ -361,9 +361,9 @@ namespace ts {
|
||||
function getWatchFactoryWith<X, Y = undefined>(watchLogLevel: WatchLogLevel, log: (s: string) => void, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined,
|
||||
watchFile: (host: WatchFileHost, file: string, callback: FileWatcherCallback, watchPriority: PollingInterval) => FileWatcher,
|
||||
watchDirectory: (host: WatchDirectoryHost, directory: string, callback: DirectoryWatcherCallback, flags: WatchDirectoryFlags) => FileWatcher): WatchFactory<X, Y> {
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, undefined, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
return {
|
||||
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
|
||||
createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
@@ -402,7 +402,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
log(`${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`);
|
||||
const watcher = createFileWatcherWithTriggerLogging(host, file, cb, flags, passThrough, detailInfo1, detailInfo2, addWatch, log, watchCaption, getDetailWatchInfo);
|
||||
return {
|
||||
@@ -413,7 +413,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createDirectoryWatcherWithLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
const watchInfo = `${watchCaption}:: Added:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(watchInfo);
|
||||
const start = timestamp();
|
||||
@@ -432,7 +432,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, V>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
|
||||
return addWatch(host, file, (fileName, cbOptional) => {
|
||||
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName} ${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
|
||||
log(triggerredInfo);
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Harness.Parallel.Host {
|
||||
const Base = Mocha.reporters.Base;
|
||||
const color = Base.color;
|
||||
const cursor = Base.cursor;
|
||||
const ms = require("mocha/lib/ms") as typeof import("mocha/lib/ms");
|
||||
const ms = require("ms") as typeof import("ms");
|
||||
const readline = require("readline") as typeof import("readline");
|
||||
const os = require("os") as typeof import("os");
|
||||
const tty = require("tty") as typeof import("tty");
|
||||
@@ -530,6 +530,8 @@ namespace Harness.Parallel.Host {
|
||||
|
||||
const replayRunner = new Mocha.Runner(new Mocha.Suite(""), /*delay*/ false);
|
||||
replayRunner.started = true;
|
||||
const createStatsCollector = require("mocha/lib/stats-collector");
|
||||
createStatsCollector(replayRunner); // manually init stats collector like mocha.run would
|
||||
|
||||
const consoleReporter = new Base(replayRunner);
|
||||
patchStats(consoleReporter.stats);
|
||||
|
||||
@@ -1684,9 +1684,9 @@ namespace ts.projectSystem {
|
||||
TI.getNpmCommandForInstallation(npmPath, tsVersion, packageNames, packageNames.length - Math.ceil(packageNames.length / 2)).command
|
||||
];
|
||||
it("works when the command is too long to install all packages at once", () => {
|
||||
const commands: string[] = [];
|
||||
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, command => {
|
||||
commands.push(command);
|
||||
const commands: [string, string[]][] = [];
|
||||
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, (file, args) => {
|
||||
commands.push([file, args]);
|
||||
return false;
|
||||
});
|
||||
assert.isFalse(hasError);
|
||||
@@ -1694,9 +1694,9 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
it("installs remaining packages when one of the partial command fails", () => {
|
||||
const commands: string[] = [];
|
||||
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, command => {
|
||||
commands.push(command);
|
||||
const commands: [string, string[]][] = [];
|
||||
const hasError = TI.installNpmPackages(npmPath, tsVersion, packageNames, (file, args) => {
|
||||
commands.push([file, args]);
|
||||
return commands.length === 1;
|
||||
});
|
||||
assert.isTrue(hasError);
|
||||
|
||||
@@ -70,10 +70,10 @@ namespace ts.server.typingsInstaller {
|
||||
cwd: string;
|
||||
encoding: "utf-8";
|
||||
}
|
||||
type ExecSync = (command: string, options: ExecSyncOptions) => string;
|
||||
type ExecFileSync = (file: string, args: string[], options: ExecSyncOptions) => string;
|
||||
|
||||
export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
private readonly nodeExecSync: ExecSync;
|
||||
private readonly nodeExecFileSync: ExecFileSync;
|
||||
private readonly npmPath: string;
|
||||
readonly typesRegistry: Map<MapLike<string>>;
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace ts.server.typingsInstaller {
|
||||
this.log.writeLine(`Process id: ${process.pid}`);
|
||||
this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`);
|
||||
}
|
||||
({ execSync: this.nodeExecSync } = require("child_process"));
|
||||
({ execFileSync: this.nodeExecFileSync } = require("child_process"));
|
||||
|
||||
this.ensurePackageDirectoryExists(globalTypingsCacheLocation);
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace ts.server.typingsInstaller {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`);
|
||||
}
|
||||
this.execSyncAndLog(`${this.npmPath} install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`, { cwd: globalTypingsCacheLocation });
|
||||
this.execFileSyncAndLog(this.npmPath, ["install", "--ignore-scripts", `${typesRegistryPackageName}@${this.latestDistTag}`], { cwd: globalTypingsCacheLocation });
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`);
|
||||
}
|
||||
@@ -189,7 +189,7 @@ namespace ts.server.typingsInstaller {
|
||||
this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`);
|
||||
}
|
||||
const start = Date.now();
|
||||
const hasError = installNpmPackages(this.npmPath, version, packageNames, command => this.execSyncAndLog(command, { cwd }));
|
||||
const hasError = installNpmPackages(this.npmPath, version, packageNames, (file, args) => this.execFileSyncAndLog(file, args, { cwd }));
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms`);
|
||||
}
|
||||
@@ -197,12 +197,12 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
|
||||
/** Returns 'true' in case of error. */
|
||||
private execSyncAndLog(command: string, options: Pick<ExecSyncOptions, "cwd">): boolean {
|
||||
private execFileSyncAndLog(file: string, args: string[], options: Pick<ExecSyncOptions, "cwd">): boolean {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Exec: ${command}`);
|
||||
this.log.writeLine(`Exec: ${file} ${args.join(" ")}`);
|
||||
}
|
||||
try {
|
||||
const stdout = this.nodeExecSync(command, { ...options, encoding: "utf-8" });
|
||||
const stdout = this.nodeExecFileSync(file, args, { ...options, encoding: "utf-8" });
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(` Succeeded. stdout:${indent(sys.newLine, stdout)}`);
|
||||
}
|
||||
|
||||
@@ -31,28 +31,35 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function installNpmPackages(npmPath: string, tsVersion: string, packageNames: string[], install: (command: string) => boolean) {
|
||||
export function installNpmPackages(npmPath: string, tsVersion: string, packageNames: string[], install: (file: string, args: string[]) => boolean) {
|
||||
let hasError = false;
|
||||
for (let remaining = packageNames.length; remaining > 0;) {
|
||||
const result = getNpmCommandForInstallation(npmPath, tsVersion, packageNames, remaining);
|
||||
remaining = result.remaining;
|
||||
hasError = install(result.command) || hasError;
|
||||
hasError = install(result.command[0], result.command[1]) || hasError;
|
||||
}
|
||||
return hasError;
|
||||
}
|
||||
|
||||
function getUserAgent(tsVersion: string) {
|
||||
return `--user-agent="typesInstaller/${tsVersion}"`;
|
||||
}
|
||||
const npmInstall = "install", ignoreScripts = "--ignore-scripts", saveDev = "--save-dev";
|
||||
const commandBaseLength = npmInstall.length + ignoreScripts.length + saveDev.length + getUserAgent("").length + 5;
|
||||
/*@internal*/
|
||||
export function getNpmCommandForInstallation(npmPath: string, tsVersion: string, packageNames: string[], remaining: number) {
|
||||
const sliceStart = packageNames.length - remaining;
|
||||
let command: string, toSlice = remaining;
|
||||
let packages: string[], toSlice = remaining;
|
||||
while (true) {
|
||||
command = `${npmPath} install --ignore-scripts ${(toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice)).join(" ")} --save-dev --user-agent="typesInstaller/${tsVersion}"`;
|
||||
if (command.length < 8000) {
|
||||
packages = toSlice === packageNames.length ? packageNames : packageNames.slice(sliceStart, sliceStart + toSlice);
|
||||
const commandLength = npmPath.length + commandBaseLength + packages.join(" ").length + tsVersion.length;
|
||||
if (commandLength < 8000) {
|
||||
break;
|
||||
}
|
||||
|
||||
toSlice = toSlice - Math.floor(toSlice / 2);
|
||||
}
|
||||
const command: [string, string[]] = [npmPath, [npmInstall, ignoreScripts, ...packages, saveDev, getUserAgent(tsVersion)]];
|
||||
return { command, remaining: remaining - toSlice };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user