mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'main' into server-vfs-support
This commit is contained in:
@@ -31,7 +31,7 @@ module.exports = minimist(process.argv.slice(2), {
|
||||
reporter: process.env.reporter || process.env.r,
|
||||
lint: process.env.lint || true,
|
||||
fix: process.env.fix || process.env.f,
|
||||
workers: process.env.workerCount || os.cpus().length,
|
||||
workers: process.env.workerCount || ((os.cpus().length - (process.env.CI ? 0 : 1)) || 1),
|
||||
failed: false,
|
||||
keepFailed: false,
|
||||
lkg: true,
|
||||
|
||||
+180
-46
@@ -5009,7 +5009,20 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) {
|
||||
if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) {
|
||||
context.approximateLength += (symbolName(type.symbol).length + 6);
|
||||
return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, /*constraintNode*/ undefined));
|
||||
let constraintNode: TypeNode | undefined;
|
||||
const constraint = getConstraintOfTypeParameter(type as TypeParameter);
|
||||
if (constraint) {
|
||||
// If the infer type has a constraint that is not the same as the constraint
|
||||
// we would have normally inferred based on context, we emit the constraint
|
||||
// using `infer T extends ?`. We omit inferred constraints from type references
|
||||
// as they may be elided.
|
||||
const inferredConstraint = getInferredTypeParameterConstraint(type as TypeParameter, /*omitTypeReferences*/ true);
|
||||
if (!(inferredConstraint && isTypeIdenticalTo(constraint, inferredConstraint))) {
|
||||
context.approximateLength += 9;
|
||||
constraintNode = constraint && typeToTypeNodeHelper(constraint, context);
|
||||
}
|
||||
}
|
||||
return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, constraintNode));
|
||||
}
|
||||
if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams &&
|
||||
type.flags & TypeFlags.TypeParameter &&
|
||||
@@ -5089,13 +5102,49 @@ namespace ts {
|
||||
|
||||
function conditionalTypeToTypeNode(type: ConditionalType) {
|
||||
const checkTypeNode = typeToTypeNodeHelper(type.checkType, context);
|
||||
context.approximateLength += 15;
|
||||
if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive && !(type.checkType.flags & TypeFlags.TypeParameter)) {
|
||||
const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String));
|
||||
const name = typeParameterToName(newParam, context);
|
||||
const newTypeVariable = factory.createTypeReferenceNode(name);
|
||||
context.approximateLength += 37; // 15 each for two added conditionals, 7 for an added infer type
|
||||
const newMapper = prependTypeMapping(type.root.checkType, newParam, type.combinedMapper || type.mapper);
|
||||
const saveInferTypeParameters = context.inferTypeParameters;
|
||||
context.inferTypeParameters = type.root.inferTypeParameters;
|
||||
const extendsTypeNode = typeToTypeNodeHelper(instantiateType(type.root.extendsType, newMapper), context);
|
||||
context.inferTypeParameters = saveInferTypeParameters;
|
||||
const trueTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.trueType), newMapper));
|
||||
const falseTypeNode = typeToTypeNodeOrCircularityElision(instantiateType(getTypeFromTypeNode(type.root.node.falseType), newMapper));
|
||||
|
||||
|
||||
// outermost conditional makes `T` a type parameter, allowing the inner conditionals to be distributive
|
||||
// second conditional makes `T` have `T & checkType` substitution, so it is correctly usable as the checkType
|
||||
// inner conditional runs the check the user provided on the check type (distributively) and returns the result
|
||||
// checkType extends infer T ? T extends checkType ? T extends extendsType<T> ? trueType<T> : falseType<T> : never : never;
|
||||
// this is potentially simplifiable to
|
||||
// checkType extends infer T ? T extends checkType & extendsType<T> ? trueType<T> : falseType<T> : never;
|
||||
// but that may confuse users who read the output more.
|
||||
// On the other hand,
|
||||
// checkType extends infer T extends checkType ? T extends extendsType<T> ? trueType<T> : falseType<T> : never;
|
||||
// may also work with `infer ... extends ...` in, but would produce declarations only compatible with the latest TS.
|
||||
return factory.createConditionalTypeNode(
|
||||
checkTypeNode,
|
||||
factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable.typeName) as Identifier)),
|
||||
factory.createConditionalTypeNode(
|
||||
factory.createTypeReferenceNode(factory.cloneNode(name)),
|
||||
typeToTypeNodeHelper(type.checkType, context),
|
||||
factory.createConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode),
|
||||
factory.createKeywordTypeNode(SyntaxKind.NeverKeyword)
|
||||
),
|
||||
factory.createKeywordTypeNode(SyntaxKind.NeverKeyword)
|
||||
);
|
||||
}
|
||||
const saveInferTypeParameters = context.inferTypeParameters;
|
||||
context.inferTypeParameters = type.root.inferTypeParameters;
|
||||
const extendsTypeNode = typeToTypeNodeHelper(type.extendsType, context);
|
||||
context.inferTypeParameters = saveInferTypeParameters;
|
||||
const trueTypeNode = typeToTypeNodeOrCircularityElision(getTrueTypeFromConditionalType(type));
|
||||
const falseTypeNode = typeToTypeNodeOrCircularityElision(getFalseTypeFromConditionalType(type));
|
||||
context.approximateLength += 15;
|
||||
return factory.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
|
||||
}
|
||||
|
||||
@@ -13257,7 +13306,7 @@ namespace ts {
|
||||
return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0];
|
||||
}
|
||||
|
||||
function getInferredTypeParameterConstraint(typeParameter: TypeParameter) {
|
||||
function getInferredTypeParameterConstraint(typeParameter: TypeParameter, omitTypeReferences?: boolean) {
|
||||
let inferences: Type[] | undefined;
|
||||
if (typeParameter.symbol?.declarations) {
|
||||
for (const declaration of typeParameter.symbol.declarations) {
|
||||
@@ -13267,7 +13316,7 @@ namespace ts {
|
||||
// corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are
|
||||
// present, we form an intersection of the inferred constraint types.
|
||||
const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent);
|
||||
if (grandParent.kind === SyntaxKind.TypeReference) {
|
||||
if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) {
|
||||
const typeReference = grandParent as TypeReferenceNode;
|
||||
const typeParameters = getTypeParametersForTypeReference(typeReference);
|
||||
if (typeParameters) {
|
||||
@@ -15860,7 +15909,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isSingletonTupleType(node: TypeNode) {
|
||||
return isTupleTypeNode(node) && length(node.elements) === 1 && !isOptionalTypeNode(node.elements[0]) && !isRestTypeNode(node.elements[0]);
|
||||
return isTupleTypeNode(node) &&
|
||||
length(node.elements) === 1 &&
|
||||
!isOptionalTypeNode(node.elements[0]) &&
|
||||
!isRestTypeNode(node.elements[0]) &&
|
||||
!(isNamedTupleMember(node.elements[0]) && (node.elements[0].questionToken || node.elements[0].dotDotDotToken));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20640,6 +20693,9 @@ namespace ts {
|
||||
function createMarkerType(symbol: Symbol, source: TypeParameter, target: Type) {
|
||||
const mapper = makeUnaryTypeMapper(source, target);
|
||||
const type = getDeclaredTypeOfSymbol(symbol);
|
||||
if (isErrorType(type)) {
|
||||
return type;
|
||||
}
|
||||
const result = symbol.flags & SymbolFlags.TypeAlias ?
|
||||
getTypeAliasInstantiation(symbol, instantiateTypes(getSymbolLinks(symbol).typeParameters!, mapper)) :
|
||||
createTypeReference(type as GenericType, instantiateTypes((type as GenericType).typeParameters, mapper));
|
||||
@@ -21729,6 +21785,9 @@ namespace ts {
|
||||
const inference = inferences[i];
|
||||
if (t === inference.typeParameter) {
|
||||
if (fix && !inference.isFixed) {
|
||||
// Before we commit to a particular inference (and thus lock out any further inferences),
|
||||
// we infer from any intra-expression inference sites we have collected.
|
||||
inferFromIntraExpressionSites(context);
|
||||
clearCachedInferences(inferences);
|
||||
inference.isFixed = true;
|
||||
}
|
||||
@@ -21746,6 +21805,37 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function addIntraExpressionInferenceSite(context: InferenceContext, node: Expression | MethodDeclaration, type: Type) {
|
||||
(context.intraExpressionInferenceSites ??= []).push({ node, type });
|
||||
}
|
||||
|
||||
// We collect intra-expression inference sites within object and array literals to handle cases where
|
||||
// inferred types flow between context sensitive element expressions. For example:
|
||||
//
|
||||
// declare function foo<T>(arg: [(n: number) => T, (x: T) => void]): void;
|
||||
// foo([_a => 0, n => n.toFixed()]);
|
||||
//
|
||||
// Above, both arrow functions in the tuple argument are context sensitive, thus both are omitted from the
|
||||
// pass that collects inferences from the non-context sensitive parts of the arguments. In the subsequent
|
||||
// pass where nothing is omitted, we need to commit to an inference for T in order to contextually type the
|
||||
// parameter in the second arrow function, but we want to first infer from the return type of the first
|
||||
// arrow function. This happens automatically when the arrow functions are discrete arguments (because we
|
||||
// infer from each argument before processing the next), but when the arrow functions are elements of an
|
||||
// object or array literal, we need to perform intra-expression inferences early.
|
||||
function inferFromIntraExpressionSites(context: InferenceContext) {
|
||||
if (context.intraExpressionInferenceSites) {
|
||||
for (const { node, type } of context.intraExpressionInferenceSites) {
|
||||
const contextualType = node.kind === SyntaxKind.MethodDeclaration ?
|
||||
getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) :
|
||||
getContextualType(node, ContextFlags.NoConstraints);
|
||||
if (contextualType) {
|
||||
inferTypes(context.inferences, type, contextualType);
|
||||
}
|
||||
}
|
||||
context.intraExpressionInferenceSites = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo {
|
||||
return {
|
||||
typeParameter,
|
||||
@@ -25304,6 +25394,7 @@ namespace ts {
|
||||
// a generic type without a nullable constraint and x is a generic type. This is because when both obj
|
||||
// and x are of generic types T and K, we want the resulting type to be T[K].
|
||||
return parent.kind === SyntaxKind.PropertyAccessExpression ||
|
||||
parent.kind === SyntaxKind.QualifiedName ||
|
||||
parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node ||
|
||||
parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node &&
|
||||
!(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression)));
|
||||
@@ -27408,6 +27499,11 @@ namespace ts {
|
||||
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple);
|
||||
elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
|
||||
elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
|
||||
if (contextualType && someType(contextualType, isTupleLikeType) && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) {
|
||||
const inferenceContext = getInferenceContext(node);
|
||||
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
|
||||
addIntraExpressionInferenceSite(inferenceContext, e, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inDestructuringPattern) {
|
||||
@@ -27625,6 +27721,14 @@ namespace ts {
|
||||
prop.target = member;
|
||||
member = prop;
|
||||
allPropertiesTable?.set(prop.escapedName, prop);
|
||||
|
||||
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
|
||||
(memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) {
|
||||
const inferenceContext = getInferenceContext(node);
|
||||
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
|
||||
const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
|
||||
addIntraExpressionInferenceSite(inferenceContext, inferenceNode, type);
|
||||
}
|
||||
}
|
||||
else if (memberDecl.kind === SyntaxKind.SpreadAssignment) {
|
||||
if (languageVersion < ScriptTarget.ES2015) {
|
||||
@@ -29727,34 +29831,36 @@ namespace ts {
|
||||
if (node.kind !== SyntaxKind.Decorator) {
|
||||
const contextualType = getContextualType(node, every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ContextFlags.SkipBindingPatterns : ContextFlags.None);
|
||||
if (contextualType) {
|
||||
// We clone the inference context to avoid disturbing a resolution in progress for an
|
||||
// outer call expression. Effectively we just want a snapshot of whatever has been
|
||||
// inferred for any outer call expression so far.
|
||||
const outerContext = getInferenceContext(node);
|
||||
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
|
||||
const instantiatedType = instantiateType(contextualType, outerMapper);
|
||||
// If the contextual type is a generic function type with a single call signature, we
|
||||
// instantiate the type with its own type parameters and type arguments. This ensures that
|
||||
// the type parameters are not erased to type any during type inference such that they can
|
||||
// be inferred as actual types from the contextual type. For example:
|
||||
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
|
||||
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
|
||||
// Above, the type of the 'value' parameter is inferred to be 'A'.
|
||||
const contextualSignature = getSingleCallSignature(instantiatedType);
|
||||
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
|
||||
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
|
||||
instantiatedType;
|
||||
const inferenceTargetType = getReturnTypeOfSignature(signature);
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
|
||||
// Create a type mapper for instantiating generic contextual types using the inferences made
|
||||
// from the return type. We need a separate inference pass here because (a) instantiation of
|
||||
// the source type uses the outer context's return mapper (which excludes inferences made from
|
||||
// outer arguments), and (b) we don't want any further inferences going into this context.
|
||||
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
|
||||
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
|
||||
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
|
||||
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
|
||||
if (couldContainTypeVariables(inferenceTargetType)) {
|
||||
// We clone the inference context to avoid disturbing a resolution in progress for an
|
||||
// outer call expression. Effectively we just want a snapshot of whatever has been
|
||||
// inferred for any outer call expression so far.
|
||||
const outerContext = getInferenceContext(node);
|
||||
const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault));
|
||||
const instantiatedType = instantiateType(contextualType, outerMapper);
|
||||
// If the contextual type is a generic function type with a single call signature, we
|
||||
// instantiate the type with its own type parameters and type arguments. This ensures that
|
||||
// the type parameters are not erased to type any during type inference such that they can
|
||||
// be inferred as actual types from the contextual type. For example:
|
||||
// declare function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[];
|
||||
// const boxElements: <A>(a: A[]) => { value: A }[] = arrayMap(value => ({ value }));
|
||||
// Above, the type of the 'value' parameter is inferred to be 'A'.
|
||||
const contextualSignature = getSingleCallSignature(instantiatedType);
|
||||
const inferenceSourceType = contextualSignature && contextualSignature.typeParameters ?
|
||||
getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) :
|
||||
instantiatedType;
|
||||
// Inferences made from return types have lower priority than all other inferences.
|
||||
inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType);
|
||||
// Create a type mapper for instantiating generic contextual types using the inferences made
|
||||
// from the return type. We need a separate inference pass here because (a) instantiation of
|
||||
// the source type uses the outer context's return mapper (which excludes inferences made from
|
||||
// outer arguments), and (b) we don't want any further inferences going into this context.
|
||||
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
|
||||
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
|
||||
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
|
||||
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29768,7 +29874,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const thisType = getThisTypeOfSignature(signature);
|
||||
if (thisType) {
|
||||
if (thisType && couldContainTypeVariables(thisType)) {
|
||||
const thisArgumentNode = getThisArgumentOfCall(node);
|
||||
inferTypes(context.inferences, getThisArgumentType(thisArgumentNode), thisType);
|
||||
}
|
||||
@@ -29777,12 +29883,14 @@ namespace ts {
|
||||
const arg = args[i];
|
||||
if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg))) {
|
||||
const paramType = getTypeAtPosition(signature, i);
|
||||
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
|
||||
inferTypes(context.inferences, argType, paramType);
|
||||
if (couldContainTypeVariables(paramType)) {
|
||||
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
|
||||
inferTypes(context.inferences, argType, paramType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (restType) {
|
||||
if (restType && couldContainTypeVariables(restType)) {
|
||||
const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, context, checkMode);
|
||||
inferTypes(context.inferences, spreadType, restType);
|
||||
}
|
||||
@@ -34141,6 +34249,11 @@ namespace ts {
|
||||
context.contextualType = contextualType;
|
||||
context.inferenceContext = inferenceContext;
|
||||
const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0));
|
||||
// In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type
|
||||
// parameters. This information is no longer needed after the call to checkExpression.
|
||||
if (inferenceContext && inferenceContext.intraExpressionInferenceSites) {
|
||||
inferenceContext.intraExpressionInferenceSites = undefined;
|
||||
}
|
||||
// We strip literal freshness when an appropriate contextual type is present such that contextually typed
|
||||
// literals always preserve their literal types (otherwise they might widen during type inference). An alternative
|
||||
// here would be to not mark contextually typed literals as fresh in the first place.
|
||||
@@ -34718,14 +34831,19 @@ namespace ts {
|
||||
}
|
||||
if (node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.ClassDeclaration || node.parent.kind === SyntaxKind.TypeAliasDeclaration) {
|
||||
const modifiers = getVarianceModifiers(typeParameter);
|
||||
if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) {
|
||||
if (modifiers) {
|
||||
const symbol = getSymbolOfNode(node.parent);
|
||||
const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubType : markerSuperType);
|
||||
const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperType : markerSubType);
|
||||
const saveVarianceTypeParameter = typeParameter;
|
||||
varianceTypeParameter = typeParameter;
|
||||
checkTypeAssignableTo(source, target, node, Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation);
|
||||
varianceTypeParameter = saveVarianceTypeParameter;
|
||||
if (node.parent.kind === SyntaxKind.TypeAliasDeclaration && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) {
|
||||
error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types);
|
||||
}
|
||||
else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) {
|
||||
const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubType : markerSuperType);
|
||||
const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperType : markerSubType);
|
||||
const saveVarianceTypeParameter = typeParameter;
|
||||
varianceTypeParameter = typeParameter;
|
||||
checkTypeAssignableTo(source, target, node, Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation);
|
||||
varianceTypeParameter = saveVarianceTypeParameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0));
|
||||
@@ -35606,6 +35724,22 @@ namespace ts {
|
||||
grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type);
|
||||
}
|
||||
checkSourceElement(node.typeParameter);
|
||||
const symbol = getSymbolOfNode(node.typeParameter);
|
||||
if (symbol.declarations && symbol.declarations.length > 1) {
|
||||
const links = getSymbolLinks(symbol);
|
||||
if (!links.typeParametersChecked) {
|
||||
links.typeParametersChecked = true;
|
||||
const typeParameter = getDeclaredTypeOfTypeParameter(symbol);
|
||||
const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind(symbol, SyntaxKind.TypeParameter);
|
||||
if (!areTypeParametersIdentical(declarations, [typeParameter], decl => [decl])) {
|
||||
// Report an error on every conflicting declaration.
|
||||
const name = symbolToString(symbol);
|
||||
for (const declaration of declarations) {
|
||||
error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_constraints, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
registerForUnusedIdentifiersCheck(node);
|
||||
}
|
||||
|
||||
@@ -39116,7 +39250,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType;
|
||||
if (!areTypeParametersIdentical(declarations, type.localTypeParameters!)) {
|
||||
if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, getEffectiveTypeParameterDeclarations)) {
|
||||
// Report an error on every conflicting declaration.
|
||||
const name = symbolToString(symbol);
|
||||
for (const declaration of declarations) {
|
||||
@@ -39126,13 +39260,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function areTypeParametersIdentical(declarations: readonly (ClassDeclaration | InterfaceDeclaration)[], targetParameters: TypeParameter[]) {
|
||||
function areTypeParametersIdentical<T extends DeclarationWithTypeParameters | TypeParameterDeclaration>(declarations: readonly T[], targetParameters: TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[]) {
|
||||
const maxTypeArgumentCount = length(targetParameters);
|
||||
const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters);
|
||||
|
||||
for (const declaration of declarations) {
|
||||
// If this declaration has too few or too many type parameters, we report an error
|
||||
const sourceParameters = getEffectiveTypeParameterDeclarations(declaration);
|
||||
const sourceParameters = getTypeParameterDeclarations(declaration);
|
||||
const numTypeParameters = sourceParameters.length;
|
||||
if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) {
|
||||
return false;
|
||||
|
||||
@@ -2743,6 +2743,10 @@
|
||||
"category": "Error",
|
||||
"code": 2636
|
||||
},
|
||||
"Variance annotations are only supported in type aliases for object, function, constructor, and mapped types.": {
|
||||
"category": "Error",
|
||||
"code": 2637
|
||||
},
|
||||
|
||||
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
|
||||
"category": "Error",
|
||||
@@ -3433,6 +3437,10 @@
|
||||
"category": "Error",
|
||||
"code": 2837
|
||||
},
|
||||
"All declarations of '{0}' must have identical constraints.": {
|
||||
"category": "Error",
|
||||
"code": 2838
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
+49
-19
@@ -909,6 +909,9 @@ namespace ts {
|
||||
let currentParenthesizerRule: ((node: Node) => Node) | undefined;
|
||||
const { enter: enterComment, exit: exitComment } = performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment");
|
||||
const parenthesizer = factory.parenthesizer;
|
||||
const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector<Node> = {
|
||||
select: index => index === 0 ? parenthesizer.parenthesizeLeadingTypeArgument : undefined
|
||||
};
|
||||
const emitBinaryExpression = createEmitBinaryExpression();
|
||||
|
||||
reset();
|
||||
@@ -2241,7 +2244,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitArrayType(node: ArrayTypeNode) {
|
||||
emit(node.elementType, parenthesizer.parenthesizeElementTypeOfArrayType);
|
||||
emit(node.elementType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType);
|
||||
writePunctuation("[");
|
||||
writePunctuation("]");
|
||||
}
|
||||
@@ -2254,7 +2257,7 @@ namespace ts {
|
||||
function emitTupleType(node: TupleTypeNode) {
|
||||
emitTokenWithComment(SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node);
|
||||
const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements : ListFormat.MultiLineTupleTypeElements;
|
||||
emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty);
|
||||
emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty, parenthesizer.parenthesizeElementTypeOfTupleType);
|
||||
emitTokenWithComment(SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node);
|
||||
}
|
||||
|
||||
@@ -2268,24 +2271,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitOptionalType(node: OptionalTypeNode) {
|
||||
emit(node.type, parenthesizer.parenthesizeElementTypeOfArrayType);
|
||||
emit(node.type, parenthesizer.parenthesizeTypeOfOptionalType);
|
||||
writePunctuation("?");
|
||||
}
|
||||
|
||||
function emitUnionType(node: UnionTypeNode) {
|
||||
emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeMemberOfElementType);
|
||||
emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfUnionType);
|
||||
}
|
||||
|
||||
function emitIntersectionType(node: IntersectionTypeNode) {
|
||||
emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeMemberOfElementType);
|
||||
emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfIntersectionType);
|
||||
}
|
||||
|
||||
function emitConditionalType(node: ConditionalTypeNode) {
|
||||
emit(node.checkType, parenthesizer.parenthesizeMemberOfConditionalType);
|
||||
emit(node.checkType, parenthesizer.parenthesizeCheckTypeOfConditionalType);
|
||||
writeSpace();
|
||||
writeKeyword("extends");
|
||||
writeSpace();
|
||||
emit(node.extendsType, parenthesizer.parenthesizeMemberOfConditionalType);
|
||||
emit(node.extendsType, parenthesizer.parenthesizeExtendsTypeOfConditionalType);
|
||||
writeSpace();
|
||||
writePunctuation("?");
|
||||
writeSpace();
|
||||
@@ -2315,11 +2318,15 @@ namespace ts {
|
||||
function emitTypeOperator(node: TypeOperatorNode) {
|
||||
writeTokenText(node.operator, writeKeyword);
|
||||
writeSpace();
|
||||
emit(node.type, parenthesizer.parenthesizeMemberOfElementType);
|
||||
|
||||
const parenthesizerRule = node.operator === SyntaxKind.ReadonlyKeyword ?
|
||||
parenthesizer.parenthesizeOperandOfReadonlyTypeOperator :
|
||||
parenthesizer.parenthesizeOperandOfTypeOperator;
|
||||
emit(node.type, parenthesizerRule);
|
||||
}
|
||||
|
||||
function emitIndexedAccessType(node: IndexedAccessTypeNode) {
|
||||
emit(node.objectType, parenthesizer.parenthesizeMemberOfElementType);
|
||||
emit(node.objectType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType);
|
||||
writePunctuation("[");
|
||||
emit(node.indexType);
|
||||
writePunctuation("]");
|
||||
@@ -4256,7 +4263,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeNode> | undefined) {
|
||||
emitList(parentNode, typeArguments, ListFormat.TypeArguments, parenthesizer.parenthesizeMemberOfElementType);
|
||||
emitList(parentNode, typeArguments, ListFormat.TypeArguments, typeArgumentParenthesizerRuleSelector);
|
||||
}
|
||||
|
||||
function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray<TypeParameterDeclaration> | undefined) {
|
||||
@@ -4324,15 +4331,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: (node: Node) => Node, start?: number, count?: number) {
|
||||
function emitList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector<Node>, start?: number, count?: number) {
|
||||
emitNodeList(emit, parentNode, children, format, parenthesizerRule, start, count);
|
||||
}
|
||||
|
||||
function emitExpressionList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: (node: Expression) => Expression, start?: number, count?: number) {
|
||||
function emitExpressionList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector<Expression>, start?: number, count?: number) {
|
||||
emitNodeList(emitExpression, parentNode, children, format, parenthesizerRule, start, count);
|
||||
}
|
||||
|
||||
function emitNodeList(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule: ((node: Node) => Node) | undefined, start = 0, count = children ? children.length - start : 0) {
|
||||
function emitNodeList(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector<Node> | undefined, start = 0, count = children ? children.length - start : 0) {
|
||||
const isUndefined = children === undefined;
|
||||
if (isUndefined && format & ListFormat.OptionalIfUndefined) {
|
||||
return;
|
||||
@@ -4388,6 +4395,8 @@ namespace ts {
|
||||
increaseIndent();
|
||||
}
|
||||
|
||||
const emitListItem = getEmitListItem(emit, parenthesizerRule);
|
||||
|
||||
// Emit each child.
|
||||
let previousSibling: Node | undefined;
|
||||
let previousSourceFileTextKind: ReturnType<typeof recordBundleFileInternalSectionStart>;
|
||||
@@ -4443,12 +4452,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
nextListElementPos = child.pos;
|
||||
if (emit.length === 1) {
|
||||
emit(child);
|
||||
}
|
||||
else {
|
||||
emit(child, parenthesizerRule);
|
||||
}
|
||||
emitListItem(child, emit, parenthesizerRule, i);
|
||||
|
||||
if (shouldDecreaseIndentAfterEmit) {
|
||||
decreaseIndent();
|
||||
@@ -5890,4 +5894,30 @@ namespace ts {
|
||||
CountMask = 0x0FFFFFFF, // Temp variable counter
|
||||
_i = 0x10000000, // Use/preference flag for '_i'
|
||||
}
|
||||
|
||||
interface OrdinalParentheizerRuleSelector<T extends Node> {
|
||||
select(index: number): ((node: T) => T) | undefined;
|
||||
}
|
||||
|
||||
type ParenthesizerRule<T extends Node> = (node: T) => T;
|
||||
|
||||
type ParenthesizerRuleOrSelector<T extends Node> = OrdinalParentheizerRuleSelector<T> | ParenthesizerRule<T>;
|
||||
|
||||
function emitListItemNoParenthesizer(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, _parenthesizerRule: ParenthesizerRuleOrSelector<Node> | undefined, _index: number) {
|
||||
emit(node);
|
||||
}
|
||||
|
||||
function emitListItemWithParenthesizerRuleSelector(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRuleSelector: OrdinalParentheizerRuleSelector<Node>, index: number) {
|
||||
emit(node, parenthesizerRuleSelector.select(index));
|
||||
}
|
||||
|
||||
function emitListItemWithParenthesizerRule(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: ParenthesizerRule<Node> | undefined, _index: number) {
|
||||
emit(node, parenthesizerRule);
|
||||
}
|
||||
|
||||
function getEmitListItem<T extends Node, R extends ParenthesizerRuleOrSelector<T> | undefined>(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R): (node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R, index: number) => void {
|
||||
return emit.length === 1 ? emitListItemNoParenthesizer :
|
||||
typeof parenthesizerRule === "object" ? emitListItemWithParenthesizerRuleSelector :
|
||||
emitListItemWithParenthesizerRule;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace ts {
|
||||
const getJSDocPrimaryTypeCreateFunction = memoizeOne(<T extends JSDocType>(kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind));
|
||||
const getJSDocUnaryTypeCreateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker<T>(kind, type));
|
||||
const getJSDocUnaryTypeUpdateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker<T>(kind, node, type));
|
||||
const getJSDocPrePostfixUnaryTypeCreateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"]) => (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker<T>(kind, type, postfix));
|
||||
const getJSDocPrePostfixUnaryTypeUpdateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker<T>(kind, node, type));
|
||||
const getJSDocSimpleTagCreateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (tagName: Identifier | undefined, comment?: NodeArray<JSDocComment>) => createJSDocSimpleTagWorker(kind, tagName, comment));
|
||||
const getJSDocSimpleTagUpdateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (node: T, tagName: Identifier | undefined, comment?: NodeArray<JSDocComment>) => updateJSDocSimpleTagWorker(kind, node, tagName, comment));
|
||||
const getJSDocTypeLikeTagCreateFunction = memoizeOne(<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"]) => (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray<JSDocComment>) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment));
|
||||
@@ -42,6 +44,8 @@ namespace ts {
|
||||
const factory: NodeFactory = {
|
||||
get parenthesizer() { return parenthesizerRules(); },
|
||||
get converters() { return converters(); },
|
||||
baseFactory,
|
||||
flags,
|
||||
createNodeArray,
|
||||
createNumericLiteral,
|
||||
createBigIntLiteral,
|
||||
@@ -317,10 +321,10 @@ namespace ts {
|
||||
// lazily load factory members for JSDoc types with similar structure
|
||||
get createJSDocAllType() { return getJSDocPrimaryTypeCreateFunction<JSDocAllType>(SyntaxKind.JSDocAllType); },
|
||||
get createJSDocUnknownType() { return getJSDocPrimaryTypeCreateFunction<JSDocUnknownType>(SyntaxKind.JSDocUnknownType); },
|
||||
get createJSDocNonNullableType() { return getJSDocUnaryTypeCreateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
||||
get updateJSDocNonNullableType() { return getJSDocUnaryTypeUpdateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
||||
get createJSDocNullableType() { return getJSDocUnaryTypeCreateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
||||
get updateJSDocNullableType() { return getJSDocUnaryTypeUpdateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
||||
get createJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
||||
get updateJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
||||
get createJSDocNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
||||
get updateJSDocNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
||||
get createJSDocOptionalType() { return getJSDocUnaryTypeCreateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
|
||||
get updateJSDocOptionalType() { return getJSDocUnaryTypeUpdateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
|
||||
get createJSDocVariadicType() { return getJSDocUnaryTypeCreateFunction<JSDocVariadicType>(SyntaxKind.JSDocVariadicType); },
|
||||
@@ -1912,7 +1916,7 @@ namespace ts {
|
||||
// @api
|
||||
function createArrayTypeNode(elementType: TypeNode) {
|
||||
const node = createBaseNode<ArrayTypeNode>(SyntaxKind.ArrayType);
|
||||
node.elementType = parenthesizerRules().parenthesizeElementTypeOfArrayType(elementType);
|
||||
node.elementType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(elementType);
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
@@ -1927,7 +1931,7 @@ namespace ts {
|
||||
// @api
|
||||
function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) {
|
||||
const node = createBaseNode<TupleTypeNode>(SyntaxKind.TupleType);
|
||||
node.elements = createNodeArray(elements);
|
||||
node.elements = createNodeArray(parenthesizerRules().parenthesizeElementTypesOfTupleType(elements));
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
@@ -1963,7 +1967,7 @@ namespace ts {
|
||||
// @api
|
||||
function createOptionalTypeNode(type: TypeNode) {
|
||||
const node = createBaseNode<OptionalTypeNode>(SyntaxKind.OptionalType);
|
||||
node.type = parenthesizerRules().parenthesizeElementTypeOfArrayType(type);
|
||||
node.type = parenthesizerRules().parenthesizeTypeOfOptionalType(type);
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
@@ -1990,44 +1994,44 @@ namespace ts {
|
||||
: node;
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) {
|
||||
function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[], parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]) {
|
||||
const node = createBaseNode<UnionTypeNode | IntersectionTypeNode>(kind);
|
||||
node.types = parenthesizerRules().parenthesizeConstituentTypesOfUnionOrIntersectionType(types);
|
||||
node.types = factory.createNodeArray(parenthesize(types));
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
|
||||
function updateUnionOrIntersectionTypeNode<T extends UnionOrIntersectionTypeNode>(node: T, types: NodeArray<TypeNode>): T {
|
||||
function updateUnionOrIntersectionTypeNode<T extends UnionOrIntersectionTypeNode>(node: T, types: NodeArray<TypeNode>, parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]): T {
|
||||
return node.types !== types
|
||||
? update(createUnionOrIntersectionTypeNode(node.kind, types) as T, node)
|
||||
? update(createUnionOrIntersectionTypeNode(node.kind, types, parenthesize) as T, node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// @api
|
||||
function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode {
|
||||
return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types) as UnionTypeNode;
|
||||
return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as UnionTypeNode;
|
||||
}
|
||||
|
||||
// @api
|
||||
function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray<TypeNode>) {
|
||||
return updateUnionOrIntersectionTypeNode(node, types);
|
||||
return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType);
|
||||
}
|
||||
|
||||
// @api
|
||||
function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode {
|
||||
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types) as IntersectionTypeNode;
|
||||
return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode;
|
||||
}
|
||||
|
||||
// @api
|
||||
function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray<TypeNode>) {
|
||||
return updateUnionOrIntersectionTypeNode(node, types);
|
||||
return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType);
|
||||
}
|
||||
|
||||
// @api
|
||||
function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
|
||||
const node = createBaseNode<ConditionalTypeNode>(SyntaxKind.ConditionalType);
|
||||
node.checkType = parenthesizerRules().parenthesizeMemberOfConditionalType(checkType);
|
||||
node.extendsType = parenthesizerRules().parenthesizeMemberOfConditionalType(extendsType);
|
||||
node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType);
|
||||
node.extendsType = parenthesizerRules().parenthesizeExtendsTypeOfConditionalType(extendsType);
|
||||
node.trueType = trueType;
|
||||
node.falseType = falseType;
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
@@ -2154,7 +2158,9 @@ namespace ts {
|
||||
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode {
|
||||
const node = createBaseNode<TypeOperatorNode>(SyntaxKind.TypeOperator);
|
||||
node.operator = operator;
|
||||
node.type = parenthesizerRules().parenthesizeMemberOfElementType(type);
|
||||
node.type = operator === SyntaxKind.ReadonlyKeyword ?
|
||||
parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) :
|
||||
parenthesizerRules().parenthesizeOperandOfTypeOperator(type);
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
}
|
||||
@@ -2169,7 +2175,7 @@ namespace ts {
|
||||
// @api
|
||||
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) {
|
||||
const node = createBaseNode<IndexedAccessTypeNode>(SyntaxKind.IndexedAccessType);
|
||||
node.objectType = parenthesizerRules().parenthesizeMemberOfElementType(objectType);
|
||||
node.objectType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(objectType);
|
||||
node.indexType = indexType;
|
||||
node.transformFlags = TransformFlags.ContainsTypeScript;
|
||||
return node;
|
||||
@@ -4360,12 +4366,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
// @api
|
||||
// createJSDocNonNullableType
|
||||
// createJSDocNullableType
|
||||
// createJSDocNonNullableType
|
||||
function createJSDocPrePostfixUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean }>(kind: T["kind"], type: T["type"], postfix = false): T {
|
||||
const node = createJSDocUnaryTypeWorker(
|
||||
kind,
|
||||
postfix ? type && parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(type) : type
|
||||
) as Mutable<T>;
|
||||
node.postfix = postfix;
|
||||
return node;
|
||||
}
|
||||
|
||||
// @api
|
||||
// createJSDocOptionalType
|
||||
// createJSDocVariadicType
|
||||
// createJSDocNamepathType
|
||||
|
||||
function createJSDocUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"], type: T["type"]): T {
|
||||
const node = createBaseNode<T>(kind);
|
||||
node.type = type;
|
||||
@@ -4375,6 +4390,13 @@ namespace ts {
|
||||
// @api
|
||||
// updateJSDocNonNullableType
|
||||
// updateJSDocNullableType
|
||||
function updateJSDocPrePostfixUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"], node: T, type: T["type"]): T {
|
||||
return node.type !== type
|
||||
? update(createJSDocPrePostfixUnaryTypeWorker(kind, type, node.postfix), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
// @api
|
||||
// updateJSDocOptionalType
|
||||
// updateJSDocVariadicType
|
||||
// updateJSDocNamepathType
|
||||
|
||||
@@ -25,11 +25,20 @@ namespace ts {
|
||||
parenthesizeExpressionForDisallowedComma,
|
||||
parenthesizeExpressionOfExpressionStatement,
|
||||
parenthesizeConciseBodyOfArrowFunction,
|
||||
parenthesizeMemberOfConditionalType,
|
||||
parenthesizeMemberOfElementType,
|
||||
parenthesizeElementTypeOfArrayType,
|
||||
parenthesizeConstituentTypesOfUnionOrIntersectionType,
|
||||
parenthesizeCheckTypeOfConditionalType,
|
||||
parenthesizeExtendsTypeOfConditionalType,
|
||||
parenthesizeConstituentTypesOfUnionType,
|
||||
parenthesizeConstituentTypeOfUnionType,
|
||||
parenthesizeConstituentTypesOfIntersectionType,
|
||||
parenthesizeConstituentTypeOfIntersectionType,
|
||||
parenthesizeOperandOfTypeOperator,
|
||||
parenthesizeOperandOfReadonlyTypeOperator,
|
||||
parenthesizeNonArrayTypeOfPostfixType,
|
||||
parenthesizeElementTypesOfTupleType,
|
||||
parenthesizeElementTypeOfTupleType,
|
||||
parenthesizeTypeOfOptionalType,
|
||||
parenthesizeTypeArguments,
|
||||
parenthesizeLeadingTypeArgument,
|
||||
};
|
||||
|
||||
function getParenthesizeLeftSideOfBinaryForOperator(operatorKind: BinaryOperator) {
|
||||
@@ -388,38 +397,199 @@ namespace ts {
|
||||
return body;
|
||||
}
|
||||
|
||||
function parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode {
|
||||
return member.kind === SyntaxKind.ConditionalType ? factory.createParenthesizedType(member) : member;
|
||||
}
|
||||
// Type[Extends] :
|
||||
// FunctionOrConstructorType
|
||||
// ConditionalType[?Extends]
|
||||
|
||||
function parenthesizeMemberOfElementType(member: TypeNode): TypeNode {
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
// ConditionalType[Extends] :
|
||||
// UnionType[?Extends]
|
||||
// [~Extends] UnionType[~Extends] `extends` Type[+Extends] `?` Type[~Extends] `:` Type[~Extends]
|
||||
//
|
||||
// - The check type (the `UnionType`, above) does not allow function, constructor, or conditional types (they must be parenthesized)
|
||||
// - The extends type (the first `Type`, above) does not allow conditional types (they must be parenthesized). Function and constructor types are fine.
|
||||
// - The true and false branch types (the second and third `Type` non-terminals, above) allow any type
|
||||
function parenthesizeCheckTypeOfConditionalType(checkType: TypeNode): TypeNode {
|
||||
switch (checkType.kind) {
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return factory.createParenthesizedType(member);
|
||||
case SyntaxKind.ConditionalType:
|
||||
return factory.createParenthesizedType(checkType);
|
||||
}
|
||||
return parenthesizeMemberOfConditionalType(member);
|
||||
return checkType;
|
||||
}
|
||||
|
||||
function parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode {
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.TypeQuery:
|
||||
function parenthesizeExtendsTypeOfConditionalType(extendsType: TypeNode): TypeNode {
|
||||
switch (extendsType.kind) {
|
||||
case SyntaxKind.ConditionalType:
|
||||
return factory.createParenthesizedType(extendsType);
|
||||
}
|
||||
return extendsType;
|
||||
}
|
||||
|
||||
// UnionType[Extends] :
|
||||
// `|`? IntersectionType[?Extends]
|
||||
// UnionType[?Extends] `|` IntersectionType[?Extends]
|
||||
//
|
||||
// - A union type constituent has the same precedence as the check type of a conditional type
|
||||
function parenthesizeConstituentTypeOfUnionType(type: TypeNode) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.UnionType: // Not strictly necessary, but a union containing a union should have been flattened
|
||||
case SyntaxKind.IntersectionType: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests
|
||||
return factory.createParenthesizedType(type);
|
||||
}
|
||||
return parenthesizeCheckTypeOfConditionalType(type);
|
||||
}
|
||||
|
||||
function parenthesizeConstituentTypesOfUnionType(members: readonly TypeNode[]): NodeArray<TypeNode> {
|
||||
return factory.createNodeArray(sameMap(members, parenthesizeConstituentTypeOfUnionType));
|
||||
}
|
||||
|
||||
// IntersectionType[Extends] :
|
||||
// `&`? TypeOperator[?Extends]
|
||||
// IntersectionType[?Extends] `&` TypeOperator[?Extends]
|
||||
//
|
||||
// - An intersection type constituent does not allow function, constructor, conditional, or union types (they must be parenthesized)
|
||||
function parenthesizeConstituentTypeOfIntersectionType(type: TypeNode) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType: // Not strictly necessary, but an intersection containing an intersection should have been flattened
|
||||
return factory.createParenthesizedType(type);
|
||||
}
|
||||
return parenthesizeConstituentTypeOfUnionType(type);
|
||||
}
|
||||
|
||||
function parenthesizeConstituentTypesOfIntersectionType(members: readonly TypeNode[]): NodeArray<TypeNode> {
|
||||
return factory.createNodeArray(sameMap(members, parenthesizeConstituentTypeOfIntersectionType));
|
||||
}
|
||||
|
||||
// TypeOperator[Extends] :
|
||||
// PostfixType
|
||||
// InferType[?Extends]
|
||||
// `keyof` TypeOperator[?Extends]
|
||||
// `unique` TypeOperator[?Extends]
|
||||
// `readonly` TypeOperator[?Extends]
|
||||
//
|
||||
function parenthesizeOperandOfTypeOperator(type: TypeNode) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.IntersectionType:
|
||||
return factory.createParenthesizedType(type);
|
||||
}
|
||||
return parenthesizeConstituentTypeOfIntersectionType(type);
|
||||
}
|
||||
|
||||
function parenthesizeOperandOfReadonlyTypeOperator(type: TypeNode) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.TypeOperator:
|
||||
case SyntaxKind.InferType:
|
||||
return factory.createParenthesizedType(member);
|
||||
return factory.createParenthesizedType(type);
|
||||
}
|
||||
return parenthesizeMemberOfElementType(member);
|
||||
return parenthesizeOperandOfTypeOperator(type);
|
||||
}
|
||||
|
||||
function parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray<TypeNode> {
|
||||
return factory.createNodeArray(sameMap(members, parenthesizeMemberOfElementType));
|
||||
// PostfixType :
|
||||
// NonArrayType
|
||||
// NonArrayType [no LineTerminator here] `!` // JSDoc
|
||||
// NonArrayType [no LineTerminator here] `?` // JSDoc
|
||||
// IndexedAccessType
|
||||
// ArrayType
|
||||
//
|
||||
// IndexedAccessType :
|
||||
// NonArrayType `[` Type[~Extends] `]`
|
||||
//
|
||||
// ArrayType :
|
||||
// NonArrayType `[` `]`
|
||||
//
|
||||
function parenthesizeNonArrayTypeOfPostfixType(type: TypeNode) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.InferType:
|
||||
case SyntaxKind.TypeOperator:
|
||||
case SyntaxKind.TypeQuery: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests
|
||||
return factory.createParenthesizedType(type);
|
||||
}
|
||||
return parenthesizeOperandOfTypeOperator(type);
|
||||
}
|
||||
|
||||
// TupleType :
|
||||
// `[` Elision? `]`
|
||||
// `[` NamedTupleElementTypes `]`
|
||||
// `[` NamedTupleElementTypes `,` Elision? `]`
|
||||
// `[` TupleElementTypes `]`
|
||||
// `[` TupleElementTypes `,` Elision? `]`
|
||||
//
|
||||
// NamedTupleElementTypes :
|
||||
// Elision? NamedTupleMember
|
||||
// NamedTupleElementTypes `,` Elision? NamedTupleMember
|
||||
//
|
||||
// NamedTupleMember :
|
||||
// Identifier `?`? `:` Type[~Extends]
|
||||
// `...` Identifier `:` Type[~Extends]
|
||||
//
|
||||
// TupleElementTypes :
|
||||
// Elision? TupleElementType
|
||||
// TupleElementTypes `,` Elision? TupleElementType
|
||||
//
|
||||
// TupleElementType :
|
||||
// Type[~Extends] // NOTE: Needs cover grammar to disallow JSDoc postfix-optional
|
||||
// OptionalType
|
||||
// RestType
|
||||
//
|
||||
// OptionalType :
|
||||
// Type[~Extends] `?` // NOTE: Needs cover grammar to disallow JSDoc postfix-optional
|
||||
//
|
||||
// RestType :
|
||||
// `...` Type[~Extends]
|
||||
//
|
||||
function parenthesizeElementTypesOfTupleType(types: readonly (TypeNode | NamedTupleMember)[]): NodeArray<TypeNode> {
|
||||
return factory.createNodeArray(sameMap(types, parenthesizeElementTypeOfTupleType));
|
||||
}
|
||||
|
||||
function parenthesizeElementTypeOfTupleType(type: TypeNode | NamedTupleMember): TypeNode {
|
||||
if (hasJSDocPostfixQuestion(type)) return factory.createParenthesizedType(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
function hasJSDocPostfixQuestion(type: TypeNode | NamedTupleMember): boolean {
|
||||
if (isJSDocNullableType(type)) return type.postfix;
|
||||
if (isNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.type);
|
||||
if (isFunctionTypeNode(type) || isConstructorTypeNode(type) || isTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.type);
|
||||
if (isConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.falseType);
|
||||
if (isUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types));
|
||||
if (isIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types));
|
||||
if (isInferTypeNode(type)) return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint);
|
||||
return false;
|
||||
}
|
||||
|
||||
function parenthesizeTypeOfOptionalType(type: TypeNode): TypeNode {
|
||||
if (hasJSDocPostfixQuestion(type)) return factory.createParenthesizedType(type);
|
||||
return parenthesizeNonArrayTypeOfPostfixType(type);
|
||||
}
|
||||
|
||||
// function parenthesizeMemberOfElementType(member: TypeNode): TypeNode {
|
||||
// switch (member.kind) {
|
||||
// case SyntaxKind.UnionType:
|
||||
// case SyntaxKind.IntersectionType:
|
||||
// case SyntaxKind.FunctionType:
|
||||
// case SyntaxKind.ConstructorType:
|
||||
// return factory.createParenthesizedType(member);
|
||||
// }
|
||||
// return parenthesizeMemberOfConditionalType(member);
|
||||
// }
|
||||
|
||||
// function parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode {
|
||||
// switch (member.kind) {
|
||||
// case SyntaxKind.TypeQuery:
|
||||
// case SyntaxKind.TypeOperator:
|
||||
// case SyntaxKind.InferType:
|
||||
// return factory.createParenthesizedType(member);
|
||||
// }
|
||||
// return parenthesizeMemberOfElementType(member);
|
||||
// }
|
||||
|
||||
function parenthesizeLeadingTypeArgument(node: TypeNode) {
|
||||
return isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node;
|
||||
}
|
||||
|
||||
function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) {
|
||||
return i === 0 && isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node;
|
||||
return i === 0 ? parenthesizeLeadingTypeArgument(node) : node;
|
||||
}
|
||||
|
||||
function parenthesizeTypeArguments(typeArguments: NodeArray<TypeNode> | undefined): NodeArray<TypeNode> | undefined {
|
||||
@@ -446,10 +616,19 @@ namespace ts {
|
||||
parenthesizeExpressionForDisallowedComma: identity,
|
||||
parenthesizeExpressionOfExpressionStatement: identity,
|
||||
parenthesizeConciseBodyOfArrowFunction: identity,
|
||||
parenthesizeMemberOfConditionalType: identity,
|
||||
parenthesizeMemberOfElementType: identity,
|
||||
parenthesizeElementTypeOfArrayType: identity,
|
||||
parenthesizeConstituentTypesOfUnionOrIntersectionType: nodes => cast(nodes, isNodeArray),
|
||||
parenthesizeCheckTypeOfConditionalType: identity,
|
||||
parenthesizeExtendsTypeOfConditionalType: identity,
|
||||
parenthesizeConstituentTypesOfUnionType: nodes => cast(nodes, isNodeArray),
|
||||
parenthesizeConstituentTypeOfUnionType: identity,
|
||||
parenthesizeConstituentTypesOfIntersectionType: nodes => cast(nodes, isNodeArray),
|
||||
parenthesizeConstituentTypeOfIntersectionType: identity,
|
||||
parenthesizeOperandOfTypeOperator: identity,
|
||||
parenthesizeOperandOfReadonlyTypeOperator: identity,
|
||||
parenthesizeNonArrayTypeOfPostfixType: identity,
|
||||
parenthesizeElementTypesOfTupleType: nodes => cast(nodes, isNodeArray),
|
||||
parenthesizeElementTypeOfTupleType: identity,
|
||||
parenthesizeTypeOfOptionalType: identity,
|
||||
parenthesizeTypeArguments: nodes => nodes && cast(nodes, isNodeArray),
|
||||
parenthesizeLeadingTypeArgument: identity,
|
||||
};
|
||||
}
|
||||
|
||||
+86
-39
@@ -1391,6 +1391,14 @@ namespace ts {
|
||||
return doInsideOfContext(NodeFlags.DisallowInContext, func);
|
||||
}
|
||||
|
||||
function allowConditionalTypesAnd<T>(func: () => T): T {
|
||||
return doOutsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
|
||||
}
|
||||
|
||||
function disallowConditionalTypesAnd<T>(func: () => T): T {
|
||||
return doInsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
|
||||
}
|
||||
|
||||
function doInYieldContext<T>(func: () => T): T {
|
||||
return doInsideOfContext(NodeFlags.YieldContext, func);
|
||||
}
|
||||
@@ -1427,6 +1435,10 @@ namespace ts {
|
||||
return inContext(NodeFlags.DisallowInContext);
|
||||
}
|
||||
|
||||
function inDisallowConditionalTypesContext() {
|
||||
return inContext(NodeFlags.DisallowConditionalTypesContext);
|
||||
}
|
||||
|
||||
function inDecoratorContext() {
|
||||
return inContext(NodeFlags.DecoratorContext);
|
||||
}
|
||||
@@ -2374,7 +2386,7 @@ namespace ts {
|
||||
return createNodeArray(list, listPos);
|
||||
}
|
||||
|
||||
function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
|
||||
function parseListElement<T extends Node | undefined>(parsingContext: ParsingContext, parseElement: () => T): T {
|
||||
const node = currentNode(parsingContext);
|
||||
if (node) {
|
||||
return consumeNode(node) as T;
|
||||
@@ -2719,7 +2731,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Parses a comma-delimited list of elements
|
||||
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T> {
|
||||
function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T>;
|
||||
function parseDelimitedList<T extends Node | undefined>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<NonNullable<T>> | undefined;
|
||||
function parseDelimitedList<T extends Node | undefined>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<NonNullable<T>> | undefined {
|
||||
const saveParsingContext = parsingContext;
|
||||
parsingContext |= 1 << kind;
|
||||
const list = [];
|
||||
@@ -2729,7 +2743,11 @@ namespace ts {
|
||||
while (true) {
|
||||
if (isListElement(kind, /*inErrorRecovery*/ false)) {
|
||||
const startPos = scanner.getStartPos();
|
||||
list.push(parseListElement(kind, parseElement));
|
||||
const result = parseListElement(kind, parseElement);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
list.push(result as NonNullable<T>);
|
||||
commaStart = scanner.getTokenPos();
|
||||
|
||||
if (parseOptional(SyntaxKind.CommaToken)) {
|
||||
@@ -3067,7 +3085,7 @@ namespace ts {
|
||||
function parseJSDocNonNullableType(): TypeNode {
|
||||
const pos = getNodePos();
|
||||
nextToken();
|
||||
return finishNode(factory.createJSDocNonNullableType(parseNonArrayType()), pos);
|
||||
return finishNode(factory.createJSDocNonNullableType(parseNonArrayType(), /*postfix*/ false), pos);
|
||||
}
|
||||
|
||||
function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
|
||||
@@ -3094,7 +3112,7 @@ namespace ts {
|
||||
return finishNode(factory.createJSDocUnknownType(), pos);
|
||||
}
|
||||
else {
|
||||
return finishNode(factory.createJSDocNullableType(parseType()), pos);
|
||||
return finishNode(factory.createJSDocNullableType(parseType(), /*postfix*/ false), pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3239,15 +3257,24 @@ namespace ts {
|
||||
return name;
|
||||
}
|
||||
|
||||
function parseParameterInOuterAwaitContext() {
|
||||
return parseParameterWorker(/*inOuterAwaitContext*/ true);
|
||||
function isParameterNameStart() {
|
||||
// Be permissive about await and yield by calling isBindingIdentifier instead of isIdentifier; disallowing
|
||||
// them during a speculative parse leads to many more follow-on errors than allowing the function to parse then later
|
||||
// complaining about the use of the keywords.
|
||||
return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken;
|
||||
}
|
||||
|
||||
function parseParameter(): ParameterDeclaration {
|
||||
return parseParameterWorker(/*inOuterAwaitContext*/ false);
|
||||
function parseParameter(inOuterAwaitContext: boolean): ParameterDeclaration {
|
||||
return parseParameterWorker(inOuterAwaitContext);
|
||||
}
|
||||
|
||||
function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration {
|
||||
function parseParameterForSpeculation(inOuterAwaitContext: boolean): ParameterDeclaration | undefined {
|
||||
return parseParameterWorker(inOuterAwaitContext, /*allowAmbiguity*/ false);
|
||||
}
|
||||
|
||||
function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration;
|
||||
function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ParameterDeclaration | undefined;
|
||||
function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ParameterDeclaration | undefined {
|
||||
const pos = getNodePos();
|
||||
const hasJSDoc = hasPrecedingJSDocComment();
|
||||
|
||||
@@ -3277,13 +3304,20 @@ namespace ts {
|
||||
|
||||
const savedTopLevel = topLevel;
|
||||
topLevel = false;
|
||||
|
||||
const modifiers = parseModifiers();
|
||||
const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
|
||||
if (!allowAmbiguity && !isParameterNameStart()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const node = withJSDoc(
|
||||
finishNode(
|
||||
factory.createParameterDeclaration(
|
||||
decorators,
|
||||
modifiers,
|
||||
parseOptionalToken(SyntaxKind.DotDotDotToken),
|
||||
dotDotDotToken,
|
||||
parseNameOfParameter(modifiers),
|
||||
parseOptionalToken(SyntaxKind.QuestionToken),
|
||||
parseTypeAnnotation(),
|
||||
@@ -3301,7 +3335,7 @@ namespace ts {
|
||||
function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined;
|
||||
function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) {
|
||||
if (shouldParseReturnType(returnToken, isType)) {
|
||||
return parseTypeOrTypePredicate();
|
||||
return allowConditionalTypesAnd(parseTypeOrTypePredicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3322,7 +3356,9 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseParametersWorker(flags: SignatureFlags) {
|
||||
function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): NodeArray<ParameterDeclaration>;
|
||||
function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): NodeArray<ParameterDeclaration> | undefined;
|
||||
function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): NodeArray<ParameterDeclaration> | undefined {
|
||||
// FormalParameters [Yield,Await]: (modified)
|
||||
// [empty]
|
||||
// FormalParameterList[?Yield,Await]
|
||||
@@ -3344,7 +3380,7 @@ namespace ts {
|
||||
|
||||
const parameters = flags & SignatureFlags.JSDoc ?
|
||||
parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) :
|
||||
parseDelimitedList(ParsingContext.Parameters, savedAwaitContext ? parseParameterInOuterAwaitContext : parseParameter);
|
||||
parseDelimitedList(ParsingContext.Parameters, () => allowAmbiguity ? parseParameter(savedAwaitContext) : parseParameterForSpeculation(savedAwaitContext));
|
||||
|
||||
setYieldContext(savedYieldContext);
|
||||
setAwaitContext(savedAwaitContext);
|
||||
@@ -3370,7 +3406,7 @@ namespace ts {
|
||||
return createMissingList<ParameterDeclaration>();
|
||||
}
|
||||
|
||||
const parameters = parseParametersWorker(flags);
|
||||
const parameters = parseParametersWorker(flags, /*allowAmbiguity*/ true);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
return parameters;
|
||||
}
|
||||
@@ -3463,7 +3499,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): IndexSignatureDeclaration {
|
||||
const parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
const parameters = parseBracketedList<ParameterDeclaration>(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
const type = parseTypeAnnotation();
|
||||
parseTypeMemberSemicolon();
|
||||
const node = factory.createIndexSignature(decorators, modifiers, parameters, type);
|
||||
@@ -3924,7 +3960,7 @@ namespace ts {
|
||||
switch (token()) {
|
||||
case SyntaxKind.ExclamationToken:
|
||||
nextToken();
|
||||
type = finishNode(factory.createJSDocNonNullableType(type), pos);
|
||||
type = finishNode(factory.createJSDocNonNullableType(type, /*postfix*/ true), pos);
|
||||
break;
|
||||
case SyntaxKind.QuestionToken:
|
||||
// If next token is start of a type we have a conditional type
|
||||
@@ -3932,7 +3968,7 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
nextToken();
|
||||
type = finishNode(factory.createJSDocNullableType(type), pos);
|
||||
type = finishNode(factory.createJSDocNullableType(type, /*postfix*/ true), pos);
|
||||
break;
|
||||
case SyntaxKind.OpenBracketToken:
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
@@ -3959,17 +3995,21 @@ namespace ts {
|
||||
return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
|
||||
}
|
||||
|
||||
function parseTypeParameterOfInferType() {
|
||||
function tryParseConstraintOfInferType() {
|
||||
if (parseOptional(SyntaxKind.ExtendsKeyword)) {
|
||||
const constraint = disallowConditionalTypesAnd(parseType);
|
||||
if (inDisallowConditionalTypesContext() || token() !== SyntaxKind.QuestionToken) {
|
||||
return constraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseTypeParameterOfInferType(): TypeParameterDeclaration {
|
||||
const pos = getNodePos();
|
||||
return finishNode(
|
||||
factory.createTypeParameterDeclaration(
|
||||
/*modifiers*/ undefined,
|
||||
parseIdentifier(),
|
||||
/*constraint*/ undefined,
|
||||
/*defaultType*/ undefined
|
||||
),
|
||||
pos
|
||||
);
|
||||
const name = parseIdentifier();
|
||||
const constraint = tryParse(tryParseConstraintOfInferType);
|
||||
const node = factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, constraint);
|
||||
return finishNode(node, pos);
|
||||
}
|
||||
|
||||
function parseInferType(): InferTypeNode {
|
||||
@@ -3988,7 +4028,7 @@ namespace ts {
|
||||
case SyntaxKind.InferKeyword:
|
||||
return parseInferType();
|
||||
}
|
||||
return parsePostfixTypeOrHigher();
|
||||
return allowConditionalTypesAnd(parsePostfixTypeOrHigher);
|
||||
}
|
||||
|
||||
function parseFunctionOrConstructorTypeToError(
|
||||
@@ -4137,24 +4177,22 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
// The rules about 'yield' only apply to actual code/expression contexts. They don't
|
||||
// apply to 'type' contexts. So we disable these parameters here before moving on.
|
||||
return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseTypeWorker);
|
||||
}
|
||||
if (contextFlags & NodeFlags.TypeExcludesFlags) {
|
||||
return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType);
|
||||
}
|
||||
|
||||
function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
|
||||
if (isStartOfFunctionTypeOrConstructorType()) {
|
||||
return parseFunctionOrConstructorType();
|
||||
}
|
||||
const pos = getNodePos();
|
||||
const type = parseUnionTypeOrHigher();
|
||||
if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
|
||||
if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
|
||||
// The type following 'extends' is not permitted to be another conditional type
|
||||
const extendsType = parseTypeWorker(/*noConditionalTypes*/ true);
|
||||
const extendsType = disallowConditionalTypesAnd(parseType);
|
||||
parseExpected(SyntaxKind.QuestionToken);
|
||||
const trueType = parseTypeWorker();
|
||||
const trueType = allowConditionalTypesAnd(parseType);
|
||||
parseExpected(SyntaxKind.ColonToken);
|
||||
const falseType = parseTypeWorker();
|
||||
const falseType = allowConditionalTypesAnd(parseType);
|
||||
return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos);
|
||||
}
|
||||
return type;
|
||||
@@ -4641,7 +4679,16 @@ namespace ts {
|
||||
parameters = createMissingList<ParameterDeclaration>();
|
||||
}
|
||||
else {
|
||||
parameters = parseParametersWorker(isAsync);
|
||||
if (!allowAmbiguity) {
|
||||
const maybeParameters = parseParametersWorker(isAsync, allowAmbiguity);
|
||||
if (!maybeParameters) {
|
||||
return undefined;
|
||||
}
|
||||
parameters = maybeParameters;
|
||||
}
|
||||
else {
|
||||
parameters = parseParametersWorker(isAsync, allowAmbiguity);
|
||||
}
|
||||
if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
+4
-15
@@ -1958,6 +1958,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isSourceFileDefaultLibrary(file: SourceFile): boolean {
|
||||
if (!file.isDeclarationFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.hasNoDefaultLib) {
|
||||
return true;
|
||||
}
|
||||
@@ -3326,21 +3330,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
function verifyCompilerOptions() {
|
||||
const isNightly = stringContains(version, "-dev") || stringContains(version, "-insiders");
|
||||
if (!isNightly) {
|
||||
if (getEmitModuleKind(options) === ModuleKind.Node12) {
|
||||
createOptionValueDiagnostic("module", Diagnostics.Compiler_option_0_of_value_1_is_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, "module", "node12");
|
||||
}
|
||||
else if (getEmitModuleKind(options) === ModuleKind.NodeNext) {
|
||||
createOptionValueDiagnostic("module", Diagnostics.Compiler_option_0_of_value_1_is_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, "module", "nodenext");
|
||||
}
|
||||
else if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node12) {
|
||||
createOptionValueDiagnostic("moduleResolution", Diagnostics.Compiler_option_0_of_value_1_is_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, "moduleResolution", "node12");
|
||||
}
|
||||
else if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) {
|
||||
createOptionValueDiagnostic("moduleResolution", Diagnostics.Compiler_option_0_of_value_1_is_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next, "moduleResolution", "nodenext");
|
||||
}
|
||||
}
|
||||
if (options.strictPropertyInitialization && !getStrictOptionValue(options, "strictNullChecks")) {
|
||||
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks");
|
||||
}
|
||||
|
||||
@@ -1163,6 +1163,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) {
|
||||
if (lateMarkedStatements) {
|
||||
while (orderedRemoveItem(lateMarkedStatements, input));
|
||||
}
|
||||
if (shouldStripInternal(input)) return;
|
||||
switch (input.kind) {
|
||||
case SyntaxKind.ImportEqualsDeclaration: {
|
||||
|
||||
+41
-21
@@ -763,10 +763,11 @@ namespace ts {
|
||||
YieldContext = 1 << 13, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 14, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 15, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 16, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 17, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 18, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 19, // If we've computed data from children and cached it in this node
|
||||
DisallowConditionalTypesContext = 1 << 16, // If node was parsed in a context where conditional types are not allowed
|
||||
ThisNodeHasError = 1 << 17, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 18, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 19, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 20, // If we've computed data from children and cached it in this node
|
||||
|
||||
// These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid
|
||||
// walking the tree if the flags are not set. However, these flags are just a approximation
|
||||
@@ -777,15 +778,15 @@ namespace ts {
|
||||
// removal, it is likely that users will add the import anyway.
|
||||
// The advantage of this approach is its simplicity. For the case of batch compilation,
|
||||
// we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used.
|
||||
/* @internal */ PossiblyContainsDynamicImport = 1 << 20,
|
||||
/* @internal */ PossiblyContainsImportMeta = 1 << 21,
|
||||
/* @internal */ PossiblyContainsDynamicImport = 1 << 21,
|
||||
/* @internal */ PossiblyContainsImportMeta = 1 << 22,
|
||||
|
||||
JSDoc = 1 << 22, // If node was parsed inside jsdoc
|
||||
/* @internal */ Ambient = 1 << 23, // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier.
|
||||
/* @internal */ InWithStatement = 1 << 24, // If any ancestor of node was the `statement` of a WithStatement (not the `expression`)
|
||||
JsonFile = 1 << 25, // If node was parsed in a Json
|
||||
/* @internal */ TypeCached = 1 << 26, // If a type was cached for node at any point
|
||||
/* @internal */ Deprecated = 1 << 27, // If has '@deprecated' JSDoc tag
|
||||
JSDoc = 1 << 23, // If node was parsed inside jsdoc
|
||||
/* @internal */ Ambient = 1 << 24, // If node was inside an ambient context -- a declaration file, or inside something with the `declare` modifier.
|
||||
/* @internal */ InWithStatement = 1 << 25, // If any ancestor of node was the `statement` of a WithStatement (not the `expression`)
|
||||
JsonFile = 1 << 26, // If node was parsed in a Json
|
||||
/* @internal */ TypeCached = 1 << 27, // If a type was cached for node at any point
|
||||
/* @internal */ Deprecated = 1 << 28, // If has '@deprecated' JSDoc tag
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@@ -793,7 +794,7 @@ namespace ts {
|
||||
ReachabilityAndEmitFlags = ReachabilityCheckFlags | HasAsyncFunctions,
|
||||
|
||||
// Parsing context flags
|
||||
ContextFlags = DisallowInContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile | InWithStatement | Ambient,
|
||||
ContextFlags = DisallowInContext | DisallowConditionalTypesContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile | InWithStatement | Ambient,
|
||||
|
||||
// Exclude these flags when parsing a Type
|
||||
TypeExcludesFlags = YieldContext | AwaitContext,
|
||||
@@ -3234,11 +3235,13 @@ namespace ts {
|
||||
export interface JSDocNonNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNonNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
|
||||
export interface JSDocNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
|
||||
export interface JSDocOptionalType extends JSDocType {
|
||||
@@ -3458,7 +3461,6 @@ namespace ts {
|
||||
| FlowStart
|
||||
| FlowLabel
|
||||
| FlowAssignment
|
||||
| FlowCall
|
||||
| FlowCondition
|
||||
| FlowSwitchClause
|
||||
| FlowArrayMutation
|
||||
@@ -5913,6 +5915,13 @@ namespace ts {
|
||||
nonFixingMapper: TypeMapper; // Mapper that doesn't fix inferences
|
||||
returnMapper?: TypeMapper; // Type mapper for inferences from return types (if any)
|
||||
inferredTypeParameters?: readonly TypeParameter[]; // Inferred type parameters for function result
|
||||
intraExpressionInferenceSites?: IntraExpressionInferenceSite[];
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface IntraExpressionInferenceSite {
|
||||
node: Expression | MethodDeclaration;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -6613,7 +6622,7 @@ namespace ts {
|
||||
realpath?(path: string): string;
|
||||
getCurrentDirectory?(): string;
|
||||
getDirectories?(path: string): string[];
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean);
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean) | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7130,10 +7139,19 @@ namespace ts {
|
||||
parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression;
|
||||
parenthesizeConciseBodyOfArrowFunction(body: Expression): Expression;
|
||||
parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody;
|
||||
parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode;
|
||||
parenthesizeMemberOfElementType(member: TypeNode): TypeNode;
|
||||
parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode;
|
||||
parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray<TypeNode>;
|
||||
parenthesizeCheckTypeOfConditionalType(type: TypeNode): TypeNode;
|
||||
parenthesizeExtendsTypeOfConditionalType(type: TypeNode): TypeNode;
|
||||
parenthesizeOperandOfTypeOperator(type: TypeNode): TypeNode;
|
||||
parenthesizeOperandOfReadonlyTypeOperator(type: TypeNode): TypeNode;
|
||||
parenthesizeNonArrayTypeOfPostfixType(type: TypeNode): TypeNode;
|
||||
parenthesizeElementTypesOfTupleType(types: readonly (TypeNode | NamedTupleMember)[]): NodeArray<TypeNode>;
|
||||
parenthesizeElementTypeOfTupleType(type: TypeNode | NamedTupleMember): TypeNode | NamedTupleMember;
|
||||
parenthesizeTypeOfOptionalType(type: TypeNode): TypeNode;
|
||||
parenthesizeConstituentTypeOfUnionType(type: TypeNode): TypeNode;
|
||||
parenthesizeConstituentTypesOfUnionType(constituents: readonly TypeNode[]): NodeArray<TypeNode>;
|
||||
parenthesizeConstituentTypeOfIntersectionType(type: TypeNode): TypeNode;
|
||||
parenthesizeConstituentTypesOfIntersectionType(constituents: readonly TypeNode[]): NodeArray<TypeNode>;
|
||||
parenthesizeLeadingTypeArgument(typeNode: TypeNode): TypeNode;
|
||||
parenthesizeTypeArguments(typeParameters: readonly TypeNode[] | undefined): NodeArray<TypeNode> | undefined;
|
||||
}
|
||||
|
||||
@@ -7152,6 +7170,8 @@ namespace ts {
|
||||
export interface NodeFactory {
|
||||
/* @internal */ readonly parenthesizer: ParenthesizerRules;
|
||||
/* @internal */ readonly converters: NodeConverters;
|
||||
/* @internal */ readonly baseFactory: BaseNodeFactory;
|
||||
/* @internal */ readonly flags: NodeFactoryFlags;
|
||||
createNodeArray<T extends Node>(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray<T>;
|
||||
|
||||
//
|
||||
@@ -7550,9 +7570,9 @@ namespace ts {
|
||||
|
||||
createJSDocAllType(): JSDocAllType;
|
||||
createJSDocUnknownType(): JSDocUnknownType;
|
||||
createJSDocNonNullableType(type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNonNullableType(type: TypeNode, postfix?: boolean): JSDocNonNullableType;
|
||||
updateJSDocNonNullableType(node: JSDocNonNullableType, type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNullableType(type: TypeNode): JSDocNullableType;
|
||||
createJSDocNullableType(type: TypeNode, postfix?: boolean): JSDocNullableType;
|
||||
updateJSDocNullableType(node: JSDocNullableType, type: TypeNode): JSDocNullableType;
|
||||
createJSDocOptionalType(type: TypeNode): JSDocOptionalType;
|
||||
updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType;
|
||||
|
||||
@@ -2825,7 +2825,11 @@ namespace ts {
|
||||
|
||||
export function getHostSignatureFromJSDoc(node: Node): SignatureDeclaration | undefined {
|
||||
const host = getEffectiveJSDocHost(node);
|
||||
return host && isFunctionLike(host) ? host : undefined;
|
||||
if (host) {
|
||||
return isPropertySignature(host) && host.type && isFunctionLike(host.type) ? host.type :
|
||||
isFunctionLike(host) ? host : undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getEffectiveJSDocHost(node: Node): Node | undefined {
|
||||
|
||||
@@ -649,7 +649,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export type ExecuteCommandLineCallbacks = (program: Program | EmitAndSemanticDiagnosticsBuilderProgram | ParsedCommandLine) => void;
|
||||
export type ExecuteCommandLineCallbacks = (program: Program | BuilderProgram | ParsedCommandLine) => void;
|
||||
export function executeCommandLine(
|
||||
system: System,
|
||||
cb: ExecuteCommandLineCallbacks,
|
||||
|
||||
@@ -583,7 +583,6 @@ namespace ts.server {
|
||||
fileName: entry.file,
|
||||
textSpan: this.decodeSpan(entry),
|
||||
isWriteAccess: entry.isWriteAccess,
|
||||
isDefinition: false
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+11
-10
@@ -510,18 +510,19 @@ ${indentText}${text}`;
|
||||
buildInfo.version = ts.version;
|
||||
return ts.getBuildInfoText(buildInfo);
|
||||
};
|
||||
return patchHostForBuildInfoWrite(sys, version);
|
||||
}
|
||||
|
||||
export function patchHostForBuildInfoWrite<T extends ts.System>(sys: T, version: string) {
|
||||
const originalWrite = sys.write;
|
||||
sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version));
|
||||
|
||||
if (sys.writeFile) {
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
|
||||
if (!ts.isBuildInfoFile(fileName)) return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
const buildInfo = ts.getBuildInfo(content);
|
||||
buildInfo.version = version;
|
||||
originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
|
||||
};
|
||||
}
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
|
||||
if (!ts.isBuildInfoFile(fileName)) return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
const buildInfo = ts.getBuildInfo(content);
|
||||
buildInfo.version = version;
|
||||
originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
|
||||
};
|
||||
return sys;
|
||||
}
|
||||
|
||||
|
||||
@@ -1122,83 +1122,18 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private verifyDocumentHighlightsRespectFilesList(files: readonly string[]): void {
|
||||
const startFile = this.activeFile.fileName;
|
||||
for (const fileName of files) {
|
||||
const searchFileNames = startFile === fileName ? [startFile] : [startFile, fileName];
|
||||
const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames);
|
||||
if (highlights && !highlights.every(dh => ts.contains(searchFileNames, dh.fileName))) {
|
||||
this.raiseError(`When asking for document highlights only in files ${searchFileNames}, got document highlights in ${unique(highlights, dh => dh.fileName)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public verifyReferenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<Range>, parts: readonly FourSlashInterface.ReferenceGroup[]): void {
|
||||
interface ReferenceGroupJson {
|
||||
definition: string | { text: string, range: ts.TextSpan };
|
||||
references: ts.ReferenceEntry[];
|
||||
}
|
||||
interface RangeMarkerData {
|
||||
id?: string;
|
||||
isWriteAccess?: boolean,
|
||||
isDefinition?: boolean,
|
||||
isInString?: true,
|
||||
contextRangeIndex?: number,
|
||||
contextRangeDelta?: number,
|
||||
contextRangeId?: string
|
||||
}
|
||||
const fullExpected = ts.map<FourSlashInterface.ReferenceGroup, ReferenceGroupJson>(parts, ({ definition, ranges }) => ({
|
||||
definition: typeof definition === "string" ? definition : { ...definition, range: ts.createTextSpanFromRange(definition.range) },
|
||||
references: ranges.map<ts.ReferenceEntry>(r => {
|
||||
const { isWriteAccess = false, isDefinition = false, isInString, contextRangeIndex, contextRangeDelta, contextRangeId } = (r.marker && r.marker.data || {}) as RangeMarkerData;
|
||||
let contextSpan: ts.TextSpan | undefined;
|
||||
if (contextRangeDelta !== undefined) {
|
||||
const allRanges = this.getRanges();
|
||||
const index = allRanges.indexOf(r);
|
||||
if (index !== -1) {
|
||||
contextSpan = ts.createTextSpanFromRange(allRanges[index + contextRangeDelta]);
|
||||
}
|
||||
}
|
||||
else if (contextRangeId !== undefined) {
|
||||
const allRanges = this.getRanges();
|
||||
const contextRange = ts.find(allRanges, range => (range.marker?.data as RangeMarkerData)?.id === contextRangeId);
|
||||
if (contextRange) {
|
||||
contextSpan = ts.createTextSpanFromRange(contextRange);
|
||||
}
|
||||
}
|
||||
else if (contextRangeIndex !== undefined) {
|
||||
contextSpan = ts.createTextSpanFromRange(this.getRanges()[contextRangeIndex]);
|
||||
}
|
||||
return {
|
||||
textSpan: ts.createTextSpanFromRange(r),
|
||||
fileName: r.fileName,
|
||||
...(contextSpan ? { contextSpan } : undefined),
|
||||
isWriteAccess,
|
||||
isDefinition,
|
||||
...(isInString ? { isInString: true } : undefined),
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
for (const start of toArray<string | Range>(starts)) {
|
||||
this.goToMarkerOrRange(start);
|
||||
const fullActual = ts.map<ts.ReferencedSymbol, ReferenceGroupJson>(this.findReferencesAtCaret(), ({ definition, references }, i) => {
|
||||
const text = definition.displayParts.map(d => d.text).join("");
|
||||
return {
|
||||
definition: fullExpected.length > i && typeof fullExpected[i].definition === "string" ? text : { text, range: definition.textSpan },
|
||||
references,
|
||||
};
|
||||
});
|
||||
this.assertObjectsEqual(fullActual, fullExpected);
|
||||
|
||||
if (parts) {
|
||||
this.verifyDocumentHighlightsRespectFilesList(unique(ts.flatMap(parts, p => p.ranges), r => r.fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public verifyBaselineFindAllReferences(...markerNames: string[]) {
|
||||
ts.Debug.assert(markerNames.length > 0, "Must pass at least one marker name to `verifyBaselineFindAllReferences()`");
|
||||
this.verifyBaselineFindAllReferencesWorker("", markerNames);
|
||||
}
|
||||
|
||||
// Used when a single test needs to produce multiple baselines
|
||||
public verifyBaselineFindAllReferencesMulti(seq: number, ...markerNames: string[]) {
|
||||
ts.Debug.assert(markerNames.length > 0, "Must pass at least one marker name to `baselineFindAllReferences()`");
|
||||
this.verifyBaselineFindAllReferencesWorker(`.${seq}`, markerNames);
|
||||
}
|
||||
|
||||
private verifyBaselineFindAllReferencesWorker(suffix: string, markerNames: string[]) {
|
||||
const baseline = markerNames.map(markerName => {
|
||||
this.goToMarker(markerName);
|
||||
const marker = this.getMarkerByName(markerName);
|
||||
@@ -1213,7 +1148,7 @@ namespace FourSlash {
|
||||
// Write response JSON
|
||||
return baselineContent + JSON.stringify(references, undefined, 2);
|
||||
}).join("\n\n");
|
||||
Harness.Baseline.runBaseline(this.getBaselineFileNameForContainingTestFile(".baseline.jsonc"), baseline);
|
||||
Harness.Baseline.runBaseline(this.getBaselineFileNameForContainingTestFile(`${suffix}.baseline.jsonc`), baseline);
|
||||
}
|
||||
|
||||
public verifyBaselineGetFileReferences(fileName: string) {
|
||||
@@ -1280,11 +1215,6 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[] | string) {
|
||||
ranges = ts.isString(ranges) ? this.rangesByText().get(ranges)! : ranges || this.getRanges();
|
||||
this.verifyReferenceGroups(ranges, [{ definition, ranges }]);
|
||||
}
|
||||
|
||||
private assertObjectsEqual<T>(fullActual: T, fullExpected: T, msgPrefix = ""): void {
|
||||
const recur = <U>(actual: U, expected: U, path: string) => {
|
||||
const fail = (msg: string) => {
|
||||
@@ -2120,7 +2050,8 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private getBaselineFileNameForContainingTestFile(ext = ".baseline") {
|
||||
return ts.getBaseFileName(this.originalInputFileName).replace(ts.Extension.Ts, ext);
|
||||
return this.testData.globalOptions[MetadataOptionNames.baselineFile] ||
|
||||
ts.getBaseFileName(this.originalInputFileName).replace(ts.Extension.Ts, ext);
|
||||
}
|
||||
|
||||
private getSignatureHelp({ triggerReason }: FourSlashInterface.VerifySignatureHelpOptions): ts.SignatureHelpItems | undefined {
|
||||
@@ -2402,15 +2333,6 @@ namespace FourSlash {
|
||||
this.goToPosition(len);
|
||||
}
|
||||
|
||||
private goToMarkerOrRange(markerOrRange: string | Range) {
|
||||
if (typeof markerOrRange === "string") {
|
||||
this.goToMarker(markerOrRange);
|
||||
}
|
||||
else {
|
||||
this.goToRangeStart(markerOrRange);
|
||||
}
|
||||
}
|
||||
|
||||
public goToRangeStart({ fileName, pos }: Range) {
|
||||
this.openFile(fileName);
|
||||
this.goToPosition(pos);
|
||||
@@ -3528,9 +3450,10 @@ namespace FourSlash {
|
||||
};
|
||||
}
|
||||
|
||||
public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) {
|
||||
public verifyRefactorAvailable(negative: boolean, triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string, actionDescription?: string) {
|
||||
let refactors = this.getApplicableRefactorsAtSelection(triggerReason);
|
||||
refactors = refactors.filter(r => r.name === name && (actionName === undefined || r.actions.some(a => a.name === actionName)));
|
||||
refactors = refactors.filter(r =>
|
||||
r.name === name && (actionName === undefined || r.actions.some(a => a.name === actionName)) && (actionDescription === undefined || r.actions.some(a => a.description === actionDescription)));
|
||||
const isAvailable = refactors.length > 0;
|
||||
|
||||
if (negative) {
|
||||
|
||||
@@ -215,8 +215,8 @@ namespace FourSlashInterface {
|
||||
this.state.verifyRefactorsAvailable(names);
|
||||
}
|
||||
|
||||
public refactorAvailable(name: string, actionName?: string) {
|
||||
this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName);
|
||||
public refactorAvailable(name: string, actionName?: string, actionDescription?: string) {
|
||||
this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName, actionDescription);
|
||||
}
|
||||
|
||||
public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) {
|
||||
@@ -352,12 +352,12 @@ namespace FourSlashInterface {
|
||||
this.state.verifyBaselineFindAllReferences(...markerNames);
|
||||
}
|
||||
|
||||
public baselineGetFileReferences(fileName: string) {
|
||||
this.state.verifyBaselineGetFileReferences(fileName);
|
||||
public baselineFindAllReferencesMulti(seq: number, ...markerNames: string[]) {
|
||||
this.state.verifyBaselineFindAllReferencesMulti(seq, ...markerNames);
|
||||
}
|
||||
|
||||
public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[] | string) {
|
||||
this.state.verifySingleReferenceGroup(definition, ranges);
|
||||
public baselineGetFileReferences(fileName: string) {
|
||||
this.state.verifyBaselineGetFileReferences(fileName);
|
||||
}
|
||||
|
||||
public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) {
|
||||
|
||||
+14
-1
@@ -809,7 +809,11 @@ namespace vfs {
|
||||
const baseBuffer = base._getBuffer(baseNode);
|
||||
|
||||
// no difference if both buffers are the same reference
|
||||
if (changedBuffer === baseBuffer) return false;
|
||||
if (changedBuffer === baseBuffer) {
|
||||
if (!options.includeChangedFileWithSameContent || changedNode.mtimeMs === baseNode.mtimeMs) return false;
|
||||
container[basename] = new SameFileWithModifiedTime(changedBuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
// no difference if both buffers are identical
|
||||
if (Buffer.compare(changedBuffer, baseBuffer) === 0) {
|
||||
@@ -1391,6 +1395,12 @@ namespace vfs {
|
||||
}
|
||||
}
|
||||
|
||||
export class SameFileWithModifiedTime extends File {
|
||||
constructor(data: Buffer | string, metaAndEncoding?: { encoding?: string, meta?: Record<string, any> }) {
|
||||
super(data, metaAndEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
/** Extended options for a hard link in a `FileSet` */
|
||||
export class Link {
|
||||
public readonly path: string;
|
||||
@@ -1579,6 +1589,9 @@ namespace vfs {
|
||||
else if (entry instanceof Directory) {
|
||||
text += formatPatchWorker(file, entry.files);
|
||||
}
|
||||
else if (entry instanceof SameFileWithModifiedTime) {
|
||||
text += `//// [${file}] file changed its modified time\r\n`;
|
||||
}
|
||||
else if (entry instanceof SameFileContentFile) {
|
||||
text += `//// [${file}] file written with same contents\r\n`;
|
||||
}
|
||||
|
||||
Vendored
+404
-31
@@ -701,6 +701,19 @@ interface LockOptions {
|
||||
steal?: boolean;
|
||||
}
|
||||
|
||||
interface MIDIConnectionEventInit extends EventInit {
|
||||
port?: MIDIPort;
|
||||
}
|
||||
|
||||
interface MIDIMessageEventInit extends EventInit {
|
||||
data?: Uint8Array;
|
||||
}
|
||||
|
||||
interface MIDIOptions {
|
||||
software?: boolean;
|
||||
sysex?: boolean;
|
||||
}
|
||||
|
||||
interface MediaCapabilitiesDecodingInfo extends MediaCapabilitiesInfo {
|
||||
configuration?: MediaDecodingConfiguration;
|
||||
}
|
||||
@@ -931,6 +944,11 @@ interface MutationObserverInit {
|
||||
subtree?: boolean;
|
||||
}
|
||||
|
||||
interface NavigationPreloadState {
|
||||
enabled?: boolean;
|
||||
headerValue?: string;
|
||||
}
|
||||
|
||||
interface NotificationAction {
|
||||
action: string;
|
||||
icon?: string;
|
||||
@@ -1243,6 +1261,35 @@ interface RTCDtlsFingerprint {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
interface RTCEncodedAudioFrameMetadata {
|
||||
contributingSources?: number[];
|
||||
synchronizationSource?: number;
|
||||
}
|
||||
|
||||
interface RTCEncodedVideoFrameMetadata {
|
||||
contributingSources?: number[];
|
||||
dependencies?: number[];
|
||||
frameId?: number;
|
||||
height?: number;
|
||||
spatialIndex?: number;
|
||||
synchronizationSource?: number;
|
||||
temporalIndex?: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
interface RTCErrorEventInit extends EventInit {
|
||||
error: RTCError;
|
||||
}
|
||||
|
||||
interface RTCErrorInit {
|
||||
errorDetail: RTCErrorDetailType;
|
||||
httpRequestStatusCode?: number;
|
||||
receivedAlert?: number;
|
||||
sctpCauseCode?: number;
|
||||
sdpLineNumber?: number;
|
||||
sentAlert?: number;
|
||||
}
|
||||
|
||||
interface RTCIceCandidateInit {
|
||||
candidate?: string;
|
||||
sdpMLineIndex?: number | null;
|
||||
@@ -1748,6 +1795,13 @@ interface UnderlyingSource<R = any> {
|
||||
type?: undefined;
|
||||
}
|
||||
|
||||
interface VideoColorSpaceInit {
|
||||
fullRange?: boolean;
|
||||
matrix?: VideoMatrixCoefficients;
|
||||
primaries?: VideoColorPrimaries;
|
||||
transfer?: VideoTransferCharacteristics;
|
||||
}
|
||||
|
||||
interface VideoConfiguration {
|
||||
bitrate: number;
|
||||
colorGamut?: ColorGamut;
|
||||
@@ -1760,6 +1814,19 @@ interface VideoConfiguration {
|
||||
width: number;
|
||||
}
|
||||
|
||||
interface VideoFrameMetadata {
|
||||
captureTime?: DOMHighResTimeStamp;
|
||||
expectedDisplayTime: DOMHighResTimeStamp;
|
||||
height: number;
|
||||
mediaTime: number;
|
||||
presentationTime: DOMHighResTimeStamp;
|
||||
presentedFrames: number;
|
||||
processingDuration?: number;
|
||||
receiveTime?: DOMHighResTimeStamp;
|
||||
rtpTimestamp?: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
interface WaveShaperOptions extends AudioNodeOptions {
|
||||
curve?: number[] | Float32Array;
|
||||
oversample?: OverSampleType;
|
||||
@@ -1894,6 +1961,8 @@ interface AbortSignal extends EventTarget {
|
||||
/** Returns true if this AbortSignal's AbortController has signaled to abort, and false otherwise. */
|
||||
readonly aborted: boolean;
|
||||
onabort: ((this: AbortSignal, ev: Event) => any) | null;
|
||||
readonly reason: any;
|
||||
throwIfAborted(): void;
|
||||
addEventListener<K extends keyof AbortSignalEventMap>(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof AbortSignalEventMap>(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -2389,7 +2458,7 @@ interface Blob {
|
||||
readonly type: string;
|
||||
arrayBuffer(): Promise<ArrayBuffer>;
|
||||
slice(start?: number, end?: number, contentType?: string): Blob;
|
||||
stream(): ReadableStream;
|
||||
stream(): ReadableStream<Uint8Array>;
|
||||
text(): Promise<string>;
|
||||
}
|
||||
|
||||
@@ -2764,6 +2833,7 @@ interface CSSStyleDeclaration {
|
||||
columns: string;
|
||||
contain: string;
|
||||
content: string;
|
||||
contentVisibility: string;
|
||||
counterIncrement: string;
|
||||
counterReset: string;
|
||||
counterSet: string;
|
||||
@@ -2799,7 +2869,6 @@ interface CSSStyleDeclaration {
|
||||
fontStyle: string;
|
||||
fontSynthesis: string;
|
||||
fontVariant: string;
|
||||
/** @deprecated */
|
||||
fontVariantAlternates: string;
|
||||
fontVariantCaps: string;
|
||||
fontVariantEastAsian: string;
|
||||
@@ -2873,6 +2942,14 @@ interface CSSStyleDeclaration {
|
||||
markerMid: string;
|
||||
markerStart: string;
|
||||
mask: string;
|
||||
maskClip: string;
|
||||
maskComposite: string;
|
||||
maskImage: string;
|
||||
maskMode: string;
|
||||
maskOrigin: string;
|
||||
maskPosition: string;
|
||||
maskRepeat: string;
|
||||
maskSize: string;
|
||||
maskType: string;
|
||||
maxBlockSize: string;
|
||||
maxHeight: string;
|
||||
@@ -2886,7 +2963,6 @@ interface CSSStyleDeclaration {
|
||||
objectFit: string;
|
||||
objectPosition: string;
|
||||
offset: string;
|
||||
offsetAnchor: string;
|
||||
offsetDistance: string;
|
||||
offsetPath: string;
|
||||
offsetRotate: string;
|
||||
@@ -2931,6 +3007,7 @@ interface CSSStyleDeclaration {
|
||||
placeSelf: string;
|
||||
pointerEvents: string;
|
||||
position: string;
|
||||
printColorAdjust: string;
|
||||
quotes: string;
|
||||
resize: string;
|
||||
right: string;
|
||||
@@ -3231,13 +3308,13 @@ declare var CSSTransition: {
|
||||
* Available only in secure contexts.
|
||||
*/
|
||||
interface Cache {
|
||||
add(request: RequestInfo): Promise<void>;
|
||||
add(request: RequestInfo | URL): Promise<void>;
|
||||
addAll(requests: RequestInfo[]): Promise<void>;
|
||||
delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;
|
||||
keys(request?: RequestInfo, options?: CacheQueryOptions): Promise<ReadonlyArray<Request>>;
|
||||
match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response | undefined>;
|
||||
matchAll(request?: RequestInfo, options?: CacheQueryOptions): Promise<ReadonlyArray<Response>>;
|
||||
put(request: RequestInfo, response: Response): Promise<void>;
|
||||
delete(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<boolean>;
|
||||
keys(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Request>>;
|
||||
match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>;
|
||||
matchAll(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Response>>;
|
||||
put(request: RequestInfo | URL, response: Response): Promise<void>;
|
||||
}
|
||||
|
||||
declare var Cache: {
|
||||
@@ -3253,7 +3330,7 @@ interface CacheStorage {
|
||||
delete(cacheName: string): Promise<boolean>;
|
||||
has(cacheName: string): Promise<boolean>;
|
||||
keys(): Promise<string[]>;
|
||||
match(request: RequestInfo, options?: MultiCacheQueryOptions): Promise<Response | undefined>;
|
||||
match(request: RequestInfo | URL, options?: MultiCacheQueryOptions): Promise<Response | undefined>;
|
||||
open(cacheName: string): Promise<Cache>;
|
||||
}
|
||||
|
||||
@@ -3518,6 +3595,7 @@ declare var ClipboardEvent: {
|
||||
new(type: string, eventInitDict?: ClipboardEventInit): ClipboardEvent;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface ClipboardItem {
|
||||
readonly types: ReadonlyArray<string>;
|
||||
getType(type: string): Promise<Blob>;
|
||||
@@ -3525,7 +3603,7 @@ interface ClipboardItem {
|
||||
|
||||
declare var ClipboardItem: {
|
||||
prototype: ClipboardItem;
|
||||
new(items: Record<string, ClipboardItemDataType | PromiseLike<ClipboardItemDataType>>, options?: ClipboardItemOptions): ClipboardItem;
|
||||
new(items: Record<string, string | Blob | PromiseLike<string | Blob>>, options?: ClipboardItemOptions): ClipboardItem;
|
||||
};
|
||||
|
||||
/** A CloseEvent is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket object's onclose attribute. */
|
||||
@@ -4195,6 +4273,7 @@ declare var DeviceOrientationEvent: {
|
||||
};
|
||||
|
||||
interface DocumentEventMap extends DocumentAndElementEventHandlersEventMap, GlobalEventHandlersEventMap {
|
||||
"DOMContentLoaded": Event;
|
||||
"fullscreenchange": Event;
|
||||
"fullscreenerror": Event;
|
||||
"pointerlockchange": Event;
|
||||
@@ -4412,6 +4491,8 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad
|
||||
createEvent(eventInterface: "DeviceOrientationEvent"): DeviceOrientationEvent;
|
||||
createEvent(eventInterface: "DragEvent"): DragEvent;
|
||||
createEvent(eventInterface: "ErrorEvent"): ErrorEvent;
|
||||
createEvent(eventInterface: "Event"): Event;
|
||||
createEvent(eventInterface: "Events"): Event;
|
||||
createEvent(eventInterface: "FocusEvent"): FocusEvent;
|
||||
createEvent(eventInterface: "FontFaceSetLoadEvent"): FontFaceSetLoadEvent;
|
||||
createEvent(eventInterface: "FormDataEvent"): FormDataEvent;
|
||||
@@ -4420,6 +4501,8 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad
|
||||
createEvent(eventInterface: "IDBVersionChangeEvent"): IDBVersionChangeEvent;
|
||||
createEvent(eventInterface: "InputEvent"): InputEvent;
|
||||
createEvent(eventInterface: "KeyboardEvent"): KeyboardEvent;
|
||||
createEvent(eventInterface: "MIDIConnectionEvent"): MIDIConnectionEvent;
|
||||
createEvent(eventInterface: "MIDIMessageEvent"): MIDIMessageEvent;
|
||||
createEvent(eventInterface: "MediaEncryptedEvent"): MediaEncryptedEvent;
|
||||
createEvent(eventInterface: "MediaKeyMessageEvent"): MediaKeyMessageEvent;
|
||||
createEvent(eventInterface: "MediaQueryListEvent"): MediaQueryListEvent;
|
||||
@@ -4440,6 +4523,7 @@ interface Document extends Node, DocumentAndElementEventHandlers, DocumentOrShad
|
||||
createEvent(eventInterface: "PromiseRejectionEvent"): PromiseRejectionEvent;
|
||||
createEvent(eventInterface: "RTCDTMFToneChangeEvent"): RTCDTMFToneChangeEvent;
|
||||
createEvent(eventInterface: "RTCDataChannelEvent"): RTCDataChannelEvent;
|
||||
createEvent(eventInterface: "RTCErrorEvent"): RTCErrorEvent;
|
||||
createEvent(eventInterface: "RTCPeerConnectionIceErrorEvent"): RTCPeerConnectionIceErrorEvent;
|
||||
createEvent(eventInterface: "RTCPeerConnectionIceEvent"): RTCPeerConnectionIceEvent;
|
||||
createEvent(eventInterface: "RTCTrackEvent"): RTCTrackEvent;
|
||||
@@ -4871,8 +4955,20 @@ interface ElementContentEditable {
|
||||
}
|
||||
|
||||
interface ElementInternals extends ARIAMixin {
|
||||
/** Returns the form owner of internals's target element. */
|
||||
readonly form: HTMLFormElement | null;
|
||||
/** Returns a NodeList of all the label elements that internals's target element is associated with. */
|
||||
readonly labels: NodeList;
|
||||
/** Returns the ShadowRoot for internals's target element, if the target element is a shadow host, or null otherwise. */
|
||||
readonly shadowRoot: ShadowRoot | null;
|
||||
/** Returns true if internals's target element will be validated when the form is submitted; false otherwise. */
|
||||
readonly willValidate: boolean;
|
||||
/**
|
||||
* Sets both the state and submission value of internals's target element to value.
|
||||
*
|
||||
* If value is null, the element won't participate in form submission.
|
||||
*/
|
||||
setFormValue(value: File | string | FormData | null, state?: File | string | FormData | null): void;
|
||||
}
|
||||
|
||||
declare var ElementInternals: {
|
||||
@@ -4946,6 +5042,15 @@ declare var Event: {
|
||||
readonly NONE: number;
|
||||
};
|
||||
|
||||
interface EventCounts {
|
||||
forEach(callbackfn: (value: number, key: string, parent: EventCounts) => void, thisArg?: any): void;
|
||||
}
|
||||
|
||||
declare var EventCounts: {
|
||||
prototype: EventCounts;
|
||||
new(): EventCounts;
|
||||
};
|
||||
|
||||
interface EventListener {
|
||||
(evt: Event): void;
|
||||
}
|
||||
@@ -6139,14 +6244,29 @@ declare var HTMLDetailsElement: {
|
||||
new(): HTMLDetailsElement;
|
||||
};
|
||||
|
||||
/** @deprecated this is not available in most browsers */
|
||||
interface HTMLDialogElement extends HTMLElement {
|
||||
open: boolean;
|
||||
returnValue: string;
|
||||
/**
|
||||
* Closes the dialog element.
|
||||
*
|
||||
* The argument, if provided, provides a return value.
|
||||
*/
|
||||
close(returnValue?: string): void;
|
||||
/** Displays the dialog element. */
|
||||
show(): void;
|
||||
showModal(): void;
|
||||
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDialogElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDialogElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var HTMLDialogElement: {
|
||||
prototype: HTMLDialogElement;
|
||||
new(): HTMLDialogElement;
|
||||
};
|
||||
|
||||
/** @deprecated */
|
||||
interface HTMLDirectoryElement extends HTMLElement {
|
||||
/** @deprecated */
|
||||
@@ -7594,6 +7714,7 @@ interface HTMLScriptElement extends HTMLElement {
|
||||
declare var HTMLScriptElement: {
|
||||
prototype: HTMLScriptElement;
|
||||
new(): HTMLScriptElement;
|
||||
supports(type: string): boolean;
|
||||
};
|
||||
|
||||
/** A <select> HTML Element. These elements also share all of the properties and methods of other HTML elements via the HTMLElement interface. */
|
||||
@@ -7725,6 +7846,8 @@ declare var HTMLSpanElement: {
|
||||
|
||||
/** A <style> element. It inherits properties and methods from its parent, HTMLElement, and from LinkStyle. */
|
||||
interface HTMLStyleElement extends HTMLElement, LinkStyle {
|
||||
/** Enables or disables the style sheet. */
|
||||
disabled: boolean;
|
||||
/** Sets or retrieves the media type. */
|
||||
media: string;
|
||||
/**
|
||||
@@ -8231,8 +8354,10 @@ interface HTMLVideoElement extends HTMLMediaElement {
|
||||
readonly videoWidth: number;
|
||||
/** Gets or sets the width of the video element. */
|
||||
width: number;
|
||||
cancelVideoFrameCallback(handle: number): void;
|
||||
getVideoPlaybackQuality(): VideoPlaybackQuality;
|
||||
requestPictureInPicture(): Promise<PictureInPictureWindow>;
|
||||
requestVideoFrameCallback(callback: VideoFrameRequestCallback): number;
|
||||
addEventListener<K extends keyof HTMLVideoElementEventMap>(type: K, listener: (this: HTMLVideoElement, ev: HTMLVideoElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof HTMLVideoElementEventMap>(type: K, listener: (this: HTMLVideoElement, ev: HTMLVideoElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -8739,6 +8864,7 @@ declare var ImageBitmapRenderingContext: {
|
||||
|
||||
/** The underlying pixel data of an area of a <canvas> element. It is created using the ImageData() constructor or creator methods on the CanvasRenderingContext2D object associated with a canvas: createImageData() and getImageData(). It can also be used to set a part of the canvas by using putImageData(). */
|
||||
interface ImageData {
|
||||
readonly colorSpace: PredefinedColorSpace;
|
||||
/** Returns the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255. */
|
||||
readonly data: Uint8ClampedArray;
|
||||
/** Returns the actual dimensions of the data in the ImageData object, in pixels. */
|
||||
@@ -8957,6 +9083,126 @@ declare var LockManager: {
|
||||
new(): LockManager;
|
||||
};
|
||||
|
||||
interface MIDIAccessEventMap {
|
||||
"statechange": Event;
|
||||
}
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIAccess extends EventTarget {
|
||||
readonly inputs: MIDIInputMap;
|
||||
onstatechange: ((this: MIDIAccess, ev: Event) => any) | null;
|
||||
readonly outputs: MIDIOutputMap;
|
||||
readonly sysexEnabled: boolean;
|
||||
addEventListener<K extends keyof MIDIAccessEventMap>(type: K, listener: (this: MIDIAccess, ev: MIDIAccessEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof MIDIAccessEventMap>(type: K, listener: (this: MIDIAccess, ev: MIDIAccessEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var MIDIAccess: {
|
||||
prototype: MIDIAccess;
|
||||
new(): MIDIAccess;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIConnectionEvent extends Event {
|
||||
readonly port: MIDIPort;
|
||||
}
|
||||
|
||||
declare var MIDIConnectionEvent: {
|
||||
prototype: MIDIConnectionEvent;
|
||||
new(type: string, eventInitDict?: MIDIConnectionEventInit): MIDIConnectionEvent;
|
||||
};
|
||||
|
||||
interface MIDIInputEventMap extends MIDIPortEventMap {
|
||||
"midimessage": Event;
|
||||
}
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIInput extends MIDIPort {
|
||||
onmidimessage: ((this: MIDIInput, ev: Event) => any) | null;
|
||||
addEventListener<K extends keyof MIDIInputEventMap>(type: K, listener: (this: MIDIInput, ev: MIDIInputEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof MIDIInputEventMap>(type: K, listener: (this: MIDIInput, ev: MIDIInputEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var MIDIInput: {
|
||||
prototype: MIDIInput;
|
||||
new(): MIDIInput;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIInputMap {
|
||||
forEach(callbackfn: (value: MIDIInput, key: string, parent: MIDIInputMap) => void, thisArg?: any): void;
|
||||
}
|
||||
|
||||
declare var MIDIInputMap: {
|
||||
prototype: MIDIInputMap;
|
||||
new(): MIDIInputMap;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIMessageEvent extends Event {
|
||||
readonly data: Uint8Array;
|
||||
}
|
||||
|
||||
declare var MIDIMessageEvent: {
|
||||
prototype: MIDIMessageEvent;
|
||||
new(type: string, eventInitDict?: MIDIMessageEventInit): MIDIMessageEvent;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIOutput extends MIDIPort {
|
||||
send(data: number[], timestamp?: DOMHighResTimeStamp): void;
|
||||
addEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIOutput, ev: MIDIPortEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIOutput, ev: MIDIPortEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var MIDIOutput: {
|
||||
prototype: MIDIOutput;
|
||||
new(): MIDIOutput;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIOutputMap {
|
||||
forEach(callbackfn: (value: MIDIOutput, key: string, parent: MIDIOutputMap) => void, thisArg?: any): void;
|
||||
}
|
||||
|
||||
declare var MIDIOutputMap: {
|
||||
prototype: MIDIOutputMap;
|
||||
new(): MIDIOutputMap;
|
||||
};
|
||||
|
||||
interface MIDIPortEventMap {
|
||||
"statechange": Event;
|
||||
}
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface MIDIPort extends EventTarget {
|
||||
readonly connection: MIDIPortConnectionState;
|
||||
readonly id: string;
|
||||
readonly manufacturer: string | null;
|
||||
readonly name: string | null;
|
||||
onstatechange: ((this: MIDIPort, ev: Event) => any) | null;
|
||||
readonly state: MIDIPortDeviceState;
|
||||
readonly type: MIDIPortType;
|
||||
readonly version: string | null;
|
||||
close(): Promise<MIDIPort>;
|
||||
open(): Promise<MIDIPort>;
|
||||
addEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIPort, ev: MIDIPortEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIPort, ev: MIDIPortEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var MIDIPort: {
|
||||
prototype: MIDIPort;
|
||||
new(): MIDIPort;
|
||||
};
|
||||
|
||||
interface MathMLElementEventMap extends ElementEventMap, DocumentAndElementEventHandlersEventMap, GlobalEventHandlersEventMap {
|
||||
}
|
||||
|
||||
@@ -9645,8 +9891,21 @@ declare var NamedNodeMap: {
|
||||
new(): NamedNodeMap;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface NavigationPreloadManager {
|
||||
disable(): Promise<void>;
|
||||
enable(): Promise<void>;
|
||||
getState(): Promise<NavigationPreloadState>;
|
||||
setHeaderValue(value: string): Promise<void>;
|
||||
}
|
||||
|
||||
declare var NavigationPreloadManager: {
|
||||
prototype: NavigationPreloadManager;
|
||||
new(): NavigationPreloadManager;
|
||||
};
|
||||
|
||||
/** The state and the identity of the user agent. It allows scripts to query it and to register themselves to carry on some activities. */
|
||||
interface Navigator extends NavigatorAutomationInformation, NavigatorConcurrentHardware, NavigatorContentUtils, NavigatorCookies, NavigatorID, NavigatorLanguage, NavigatorNetworkInformation, NavigatorOnLine, NavigatorPlugins, NavigatorStorage {
|
||||
interface Navigator extends NavigatorAutomationInformation, NavigatorConcurrentHardware, NavigatorContentUtils, NavigatorCookies, NavigatorID, NavigatorLanguage, NavigatorLocks, NavigatorNetworkInformation, NavigatorOnLine, NavigatorPlugins, NavigatorStorage {
|
||||
/** Available only in secure contexts. */
|
||||
readonly clipboard: Clipboard;
|
||||
/** Available only in secure contexts. */
|
||||
@@ -9665,6 +9924,8 @@ interface Navigator extends NavigatorAutomationInformation, NavigatorConcurrentH
|
||||
canShare(data?: ShareData): boolean;
|
||||
getGamepads(): (Gamepad | null)[];
|
||||
/** Available only in secure contexts. */
|
||||
requestMIDIAccess(options?: MIDIOptions): Promise<MIDIAccess>;
|
||||
/** Available only in secure contexts. */
|
||||
requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): Promise<MediaKeySystemAccess>;
|
||||
sendBeacon(url: string | URL, data?: BodyInit | null): boolean;
|
||||
/** Available only in secure contexts. */
|
||||
@@ -9718,6 +9979,11 @@ interface NavigatorLanguage {
|
||||
readonly languages: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface NavigatorLocks {
|
||||
readonly locks: LockManager;
|
||||
}
|
||||
|
||||
interface NavigatorNetworkInformation {
|
||||
readonly connection: NetworkInformation;
|
||||
}
|
||||
@@ -9729,6 +9995,7 @@ interface NavigatorOnLine {
|
||||
interface NavigatorPlugins {
|
||||
/** @deprecated */
|
||||
readonly mimeTypes: MimeTypeArray;
|
||||
readonly pdfViewerEnabled: boolean;
|
||||
/** @deprecated */
|
||||
readonly plugins: PluginArray;
|
||||
/** @deprecated */
|
||||
@@ -10236,6 +10503,7 @@ interface PerformanceEventMap {
|
||||
|
||||
/** Provides access to performance-related information for the current page. It's part of the High Resolution Time API, but is enhanced by the Performance Timeline API, the Navigation Timing API, the User Timing API, and the Resource Timing API. */
|
||||
interface Performance extends EventTarget {
|
||||
readonly eventCounts: EventCounts;
|
||||
/** @deprecated */
|
||||
readonly navigation: PerformanceNavigation;
|
||||
onresourcetimingbufferfull: ((this: Performance, ev: Event) => any) | null;
|
||||
@@ -10347,7 +10615,7 @@ interface PerformanceNavigationTiming extends PerformanceResourceTiming {
|
||||
readonly loadEventEnd: DOMHighResTimeStamp;
|
||||
readonly loadEventStart: DOMHighResTimeStamp;
|
||||
readonly redirectCount: number;
|
||||
readonly type: NavigationType;
|
||||
readonly type: NavigationTimingType;
|
||||
readonly unloadEventEnd: DOMHighResTimeStamp;
|
||||
readonly unloadEventStart: DOMHighResTimeStamp;
|
||||
toJSON(): any;
|
||||
@@ -10770,6 +11038,7 @@ declare var RTCDTMFToneChangeEvent: {
|
||||
interface RTCDataChannelEventMap {
|
||||
"bufferedamountlow": Event;
|
||||
"close": Event;
|
||||
"closing": Event;
|
||||
"error": Event;
|
||||
"message": MessageEvent;
|
||||
"open": Event;
|
||||
@@ -10786,6 +11055,7 @@ interface RTCDataChannel extends EventTarget {
|
||||
readonly negotiated: boolean;
|
||||
onbufferedamountlow: ((this: RTCDataChannel, ev: Event) => any) | null;
|
||||
onclose: ((this: RTCDataChannel, ev: Event) => any) | null;
|
||||
onclosing: ((this: RTCDataChannel, ev: Event) => any) | null;
|
||||
onerror: ((this: RTCDataChannel, ev: Event) => any) | null;
|
||||
onmessage: ((this: RTCDataChannel, ev: MessageEvent) => any) | null;
|
||||
onopen: ((this: RTCDataChannel, ev: Event) => any) | null;
|
||||
@@ -10818,12 +11088,16 @@ declare var RTCDataChannelEvent: {
|
||||
};
|
||||
|
||||
interface RTCDtlsTransportEventMap {
|
||||
"error": Event;
|
||||
"statechange": Event;
|
||||
}
|
||||
|
||||
interface RTCDtlsTransport extends EventTarget {
|
||||
readonly iceTransport: RTCIceTransport;
|
||||
onerror: ((this: RTCDtlsTransport, ev: Event) => any) | null;
|
||||
onstatechange: ((this: RTCDtlsTransport, ev: Event) => any) | null;
|
||||
readonly state: RTCDtlsTransportState;
|
||||
getRemoteCertificates(): ArrayBuffer[];
|
||||
addEventListener<K extends keyof RTCDtlsTransportEventMap>(type: K, listener: (this: RTCDtlsTransport, ev: RTCDtlsTransportEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof RTCDtlsTransportEventMap>(type: K, listener: (this: RTCDtlsTransport, ev: RTCDtlsTransportEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -10835,6 +11109,51 @@ declare var RTCDtlsTransport: {
|
||||
new(): RTCDtlsTransport;
|
||||
};
|
||||
|
||||
interface RTCEncodedAudioFrame {
|
||||
data: ArrayBuffer;
|
||||
readonly timestamp: number;
|
||||
getMetadata(): RTCEncodedAudioFrameMetadata;
|
||||
}
|
||||
|
||||
declare var RTCEncodedAudioFrame: {
|
||||
prototype: RTCEncodedAudioFrame;
|
||||
new(): RTCEncodedAudioFrame;
|
||||
};
|
||||
|
||||
interface RTCEncodedVideoFrame {
|
||||
data: ArrayBuffer;
|
||||
readonly timestamp: number;
|
||||
readonly type: RTCEncodedVideoFrameType;
|
||||
getMetadata(): RTCEncodedVideoFrameMetadata;
|
||||
}
|
||||
|
||||
declare var RTCEncodedVideoFrame: {
|
||||
prototype: RTCEncodedVideoFrame;
|
||||
new(): RTCEncodedVideoFrame;
|
||||
};
|
||||
|
||||
interface RTCError extends DOMException {
|
||||
readonly errorDetail: RTCErrorDetailType;
|
||||
readonly receivedAlert: number | null;
|
||||
readonly sctpCauseCode: number | null;
|
||||
readonly sdpLineNumber: number | null;
|
||||
readonly sentAlert: number | null;
|
||||
}
|
||||
|
||||
declare var RTCError: {
|
||||
prototype: RTCError;
|
||||
new(init: RTCErrorInit, message?: string): RTCError;
|
||||
};
|
||||
|
||||
interface RTCErrorEvent extends Event {
|
||||
readonly error: RTCError;
|
||||
}
|
||||
|
||||
declare var RTCErrorEvent: {
|
||||
prototype: RTCErrorEvent;
|
||||
new(type: string, eventInitDict: RTCErrorEventInit): RTCErrorEvent;
|
||||
};
|
||||
|
||||
/** The RTCIceCandidate interface—part of the WebRTC API—represents a candidate Internet Connectivity Establishment (ICE) configuration which may be used to establish an RTCPeerConnection. */
|
||||
interface RTCIceCandidate {
|
||||
readonly address: string | null;
|
||||
@@ -10859,10 +11178,21 @@ declare var RTCIceCandidate: {
|
||||
new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;
|
||||
};
|
||||
|
||||
interface RTCIceTransportEventMap {
|
||||
"gatheringstatechange": Event;
|
||||
"statechange": Event;
|
||||
}
|
||||
|
||||
/** Provides access to information about the ICE transport layer over which the data is being sent and received. */
|
||||
interface RTCIceTransport extends EventTarget {
|
||||
readonly gatheringState: RTCIceGathererState;
|
||||
ongatheringstatechange: ((this: RTCIceTransport, ev: Event) => any) | null;
|
||||
onstatechange: ((this: RTCIceTransport, ev: Event) => any) | null;
|
||||
readonly state: RTCIceTransportState;
|
||||
addEventListener<K extends keyof RTCIceTransportEventMap>(type: K, listener: (this: RTCIceTransport, ev: RTCIceTransportEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof RTCIceTransportEventMap>(type: K, listener: (this: RTCIceTransport, ev: RTCIceTransportEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var RTCIceTransport: {
|
||||
@@ -10903,6 +11233,7 @@ interface RTCPeerConnection extends EventTarget {
|
||||
readonly pendingLocalDescription: RTCSessionDescription | null;
|
||||
readonly pendingRemoteDescription: RTCSessionDescription | null;
|
||||
readonly remoteDescription: RTCSessionDescription | null;
|
||||
readonly sctp: RTCSctpTransport | null;
|
||||
readonly signalingState: RTCSignalingState;
|
||||
addIceCandidate(candidate?: RTCIceCandidateInit): Promise<void>;
|
||||
/** @deprecated */
|
||||
@@ -11015,6 +11346,27 @@ declare var RTCRtpTransceiver: {
|
||||
new(): RTCRtpTransceiver;
|
||||
};
|
||||
|
||||
interface RTCSctpTransportEventMap {
|
||||
"statechange": Event;
|
||||
}
|
||||
|
||||
interface RTCSctpTransport extends EventTarget {
|
||||
readonly maxChannels: number | null;
|
||||
readonly maxMessageSize: number;
|
||||
onstatechange: ((this: RTCSctpTransport, ev: Event) => any) | null;
|
||||
readonly state: RTCSctpTransportState;
|
||||
readonly transport: RTCDtlsTransport;
|
||||
addEventListener<K extends keyof RTCSctpTransportEventMap>(type: K, listener: (this: RTCSctpTransport, ev: RTCSctpTransportEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof RTCSctpTransportEventMap>(type: K, listener: (this: RTCSctpTransport, ev: RTCSctpTransportEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var RTCSctpTransport: {
|
||||
prototype: RTCSctpTransport;
|
||||
new(): RTCSctpTransport;
|
||||
};
|
||||
|
||||
/** One end of a connection—or potential connection—and how it's configured. Each RTCSessionDescription consists of a description type indicating which part of the offer/answer negotiation process it describes and of the SDP descriptor of the session. */
|
||||
interface RTCSessionDescription {
|
||||
readonly sdp: string;
|
||||
@@ -11203,7 +11555,7 @@ interface Request extends Body {
|
||||
|
||||
declare var Request: {
|
||||
prototype: Request;
|
||||
new(input: RequestInfo, init?: RequestInit): Request;
|
||||
new(input: RequestInfo | URL, init?: RequestInit): Request;
|
||||
};
|
||||
|
||||
interface ResizeObserver {
|
||||
@@ -13162,6 +13514,7 @@ interface ServiceWorkerRegistrationEventMap {
|
||||
interface ServiceWorkerRegistration extends EventTarget {
|
||||
readonly active: ServiceWorker | null;
|
||||
readonly installing: ServiceWorker | null;
|
||||
readonly navigationPreload: NavigationPreloadManager;
|
||||
onupdatefound: ((this: ServiceWorkerRegistration, ev: Event) => any) | null;
|
||||
readonly pushManager: PushManager;
|
||||
readonly scope: string;
|
||||
@@ -13555,10 +13908,10 @@ interface SubtleCrypto {
|
||||
encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>;
|
||||
exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>;
|
||||
exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair | CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
sign(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>;
|
||||
unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
@@ -14076,6 +14429,19 @@ declare var ValidityState: {
|
||||
new(): ValidityState;
|
||||
};
|
||||
|
||||
interface VideoColorSpace {
|
||||
readonly fullRange: boolean | null;
|
||||
readonly matrix: VideoMatrixCoefficients | null;
|
||||
readonly primaries: VideoColorPrimaries | null;
|
||||
readonly transfer: VideoTransferCharacteristics | null;
|
||||
toJSON(): VideoColorSpaceInit;
|
||||
}
|
||||
|
||||
declare var VideoColorSpace: {
|
||||
prototype: VideoColorSpace;
|
||||
new(init?: VideoColorSpaceInit): VideoColorSpace;
|
||||
};
|
||||
|
||||
/** Returned by the HTMLVideoElement.getVideoPlaybackQuality() method and contains metrics that can be used to determine the playback quality of a video. */
|
||||
interface VideoPlaybackQuality {
|
||||
/** @deprecated */
|
||||
@@ -14171,13 +14537,6 @@ interface WEBGL_compressed_texture_etc1 {
|
||||
readonly COMPRESSED_RGB_ETC1_WEBGL: GLenum;
|
||||
}
|
||||
|
||||
interface WEBGL_compressed_texture_pvrtc {
|
||||
readonly COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGB_PVRTC_2BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGB_PVRTC_4BPPV1_IMG: GLenum;
|
||||
}
|
||||
|
||||
/** The WEBGL_compressed_texture_s3tc extension is part of the WebGL API and exposes four S3TC compressed texture formats. */
|
||||
interface WEBGL_compressed_texture_s3tc {
|
||||
readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: GLenum;
|
||||
@@ -15680,7 +16039,6 @@ interface WebGLRenderingContextBase {
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_astc"): WEBGL_compressed_texture_astc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_etc"): WEBGL_compressed_texture_etc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_etc1"): WEBGL_compressed_texture_etc1 | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_pvrtc"): WEBGL_compressed_texture_pvrtc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_s3tc_srgb"): WEBGL_compressed_texture_s3tc_srgb | null;
|
||||
getExtension(extensionName: "WEBGL_debug_shaders"): WEBGL_debug_shaders | null;
|
||||
getExtension(extensionName: "WEBGL_draw_buffers"): WEBGL_draw_buffers | null;
|
||||
@@ -16228,6 +16586,7 @@ declare var WheelEvent: {
|
||||
};
|
||||
|
||||
interface WindowEventMap extends GlobalEventHandlersEventMap, WindowEventHandlersEventMap {
|
||||
"DOMContentLoaded": Event;
|
||||
"devicemotion": DeviceMotionEvent;
|
||||
"deviceorientation": DeviceOrientationEvent;
|
||||
"gamepadconnected": GamepadEvent;
|
||||
@@ -16427,11 +16786,12 @@ interface WindowOrWorkerGlobalScope {
|
||||
clearTimeout(id?: number): void;
|
||||
createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
|
||||
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
||||
queueMicrotask(callback: VoidFunction): void;
|
||||
reportError(e: any): void;
|
||||
setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
structuredClone(value: any, options?: StructuredSerializeOptions): any;
|
||||
}
|
||||
|
||||
interface WindowSessionStorage {
|
||||
@@ -17076,6 +17436,10 @@ interface UnderlyingSourceStartCallback<R> {
|
||||
(controller: ReadableStreamController<R>): any;
|
||||
}
|
||||
|
||||
interface VideoFrameRequestCallback {
|
||||
(now: DOMHighResTimeStamp, metadata: VideoFrameMetadata): void;
|
||||
}
|
||||
|
||||
interface VoidFunction {
|
||||
(): void;
|
||||
}
|
||||
@@ -17708,11 +18072,12 @@ declare function clearInterval(id?: number): void;
|
||||
declare function clearTimeout(id?: number): void;
|
||||
declare function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
declare function createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
declare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
|
||||
declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
||||
declare function queueMicrotask(callback: VoidFunction): void;
|
||||
declare function reportError(e: any): void;
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function structuredClone(value: any, options?: StructuredSerializeOptions): any;
|
||||
declare var sessionStorage: Storage;
|
||||
declare function addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
@@ -17727,8 +18092,7 @@ type BufferSource = ArrayBufferView | ArrayBuffer;
|
||||
type COSEAlgorithmIdentifier = number;
|
||||
type CSSNumberish = number;
|
||||
type CanvasImageSource = HTMLOrSVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap;
|
||||
type ClipboardItemData = Promise<ClipboardItemDataType>;
|
||||
type ClipboardItemDataType = string | Blob;
|
||||
type ClipboardItemData = Promise<string | Blob>;
|
||||
type ClipboardItems = ClipboardItem[];
|
||||
type ConstrainBoolean = boolean | ConstrainBooleanParameters;
|
||||
type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;
|
||||
@@ -17843,6 +18207,9 @@ type KeyType = "private" | "public" | "secret";
|
||||
type KeyUsage = "decrypt" | "deriveBits" | "deriveKey" | "encrypt" | "sign" | "unwrapKey" | "verify" | "wrapKey";
|
||||
type LineAlignSetting = "center" | "end" | "start";
|
||||
type LockMode = "exclusive" | "shared";
|
||||
type MIDIPortConnectionState = "closed" | "open" | "pending";
|
||||
type MIDIPortDeviceState = "connected" | "disconnected";
|
||||
type MIDIPortType = "input" | "output";
|
||||
type MediaDecodingType = "file" | "media-source" | "webrtc";
|
||||
type MediaDeviceKind = "audioinput" | "audiooutput" | "videoinput";
|
||||
type MediaEncodingType = "record" | "webrtc";
|
||||
@@ -17854,7 +18221,7 @@ type MediaKeysRequirement = "not-allowed" | "optional" | "required";
|
||||
type MediaSessionAction = "hangup" | "nexttrack" | "pause" | "play" | "previoustrack" | "seekbackward" | "seekforward" | "seekto" | "skipad" | "stop" | "togglecamera" | "togglemicrophone";
|
||||
type MediaSessionPlaybackState = "none" | "paused" | "playing";
|
||||
type MediaStreamTrackState = "ended" | "live";
|
||||
type NavigationType = "back_forward" | "navigate" | "prerender" | "reload";
|
||||
type NavigationTimingType = "back_forward" | "navigate" | "prerender" | "reload";
|
||||
type NotificationDirection = "auto" | "ltr" | "rtl";
|
||||
type NotificationPermission = "default" | "denied" | "granted";
|
||||
type OrientationLockType = "any" | "landscape" | "landscape-primary" | "landscape-secondary" | "natural" | "portrait" | "portrait-primary" | "portrait-secondary";
|
||||
@@ -17876,6 +18243,8 @@ type RTCBundlePolicy = "balanced" | "max-bundle" | "max-compat";
|
||||
type RTCDataChannelState = "closed" | "closing" | "connecting" | "open";
|
||||
type RTCDegradationPreference = "balanced" | "maintain-framerate" | "maintain-resolution";
|
||||
type RTCDtlsTransportState = "closed" | "connected" | "connecting" | "failed" | "new";
|
||||
type RTCEncodedVideoFrameType = "delta" | "empty" | "key";
|
||||
type RTCErrorDetailType = "data-channel-failure" | "dtls-failure" | "fingerprint-failure" | "hardware-encoder-error" | "hardware-encoder-not-available" | "sctp-failure" | "sdp-syntax-error";
|
||||
type RTCIceCandidateType = "host" | "prflx" | "relay" | "srflx";
|
||||
type RTCIceComponent = "rtcp" | "rtp";
|
||||
type RTCIceConnectionState = "checking" | "closed" | "completed" | "connected" | "disconnected" | "failed" | "new";
|
||||
@@ -17890,6 +18259,7 @@ type RTCPeerConnectionState = "closed" | "connected" | "connecting" | "disconnec
|
||||
type RTCPriorityType = "high" | "low" | "medium" | "very-low";
|
||||
type RTCRtcpMuxPolicy = "require";
|
||||
type RTCRtpTransceiverDirection = "inactive" | "recvonly" | "sendonly" | "sendrecv" | "stopped";
|
||||
type RTCSctpTransportState = "closed" | "connected" | "connecting";
|
||||
type RTCSdpType = "answer" | "offer" | "pranswer" | "rollback";
|
||||
type RTCSignalingState = "closed" | "have-local-offer" | "have-local-pranswer" | "have-remote-offer" | "have-remote-pranswer" | "stable";
|
||||
type RTCStatsIceCandidatePairState = "failed" | "frozen" | "in-progress" | "inprogress" | "succeeded" | "waiting";
|
||||
@@ -17923,7 +18293,10 @@ type TextTrackMode = "disabled" | "hidden" | "showing";
|
||||
type TouchType = "direct" | "stylus";
|
||||
type TransferFunction = "hlg" | "pq" | "srgb";
|
||||
type UserVerificationRequirement = "discouraged" | "preferred" | "required";
|
||||
type VideoColorPrimaries = "bt470bg" | "bt709" | "smpte170m";
|
||||
type VideoFacingModeEnum = "environment" | "left" | "right" | "user";
|
||||
type VideoMatrixCoefficients = "bt470bg" | "bt709" | "rgb" | "smpte170m";
|
||||
type VideoTransferCharacteristics = "bt709" | "iec61966-2-1" | "smpte170m";
|
||||
type WebGLPowerPreference = "default" | "high-performance" | "low-power";
|
||||
type WorkerType = "classic" | "module";
|
||||
type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "json" | "text";
|
||||
|
||||
Vendored
+16
-3
@@ -49,6 +49,9 @@ interface DataTransferItemList {
|
||||
[Symbol.iterator](): IterableIterator<DataTransferItem>;
|
||||
}
|
||||
|
||||
interface EventCounts extends ReadonlyMap<string, number> {
|
||||
}
|
||||
|
||||
interface FileList {
|
||||
[Symbol.iterator](): IterableIterator<File>;
|
||||
}
|
||||
@@ -110,6 +113,16 @@ interface IDBObjectStore {
|
||||
createIndex(name: string, keyPath: string | Iterable<string>, options?: IDBIndexParameters): IDBIndex;
|
||||
}
|
||||
|
||||
interface MIDIInputMap extends ReadonlyMap<string, MIDIInput> {
|
||||
}
|
||||
|
||||
interface MIDIOutput {
|
||||
send(data: Iterable<number>, timestamp?: DOMHighResTimeStamp): void;
|
||||
}
|
||||
|
||||
interface MIDIOutputMap extends ReadonlyMap<string, MIDIOutput> {
|
||||
}
|
||||
|
||||
interface MediaKeyStatusMap {
|
||||
[Symbol.iterator](): IterableIterator<[BufferSource, MediaKeyStatus]>;
|
||||
entries(): IterableIterator<[BufferSource, MediaKeyStatus]>;
|
||||
@@ -213,10 +226,10 @@ interface StyleSheetList {
|
||||
|
||||
interface SubtleCrypto {
|
||||
deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKeyPair | CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
}
|
||||
|
||||
Vendored
+15
-13
@@ -63,7 +63,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#locales_argument).
|
||||
*/
|
||||
type LocalesArgument = UnicodeBCP47LocaleIdentifier | UnicodeBCP47LocaleIdentifier[] | Locale | Locale[] | undefined;
|
||||
type LocalesArgument = UnicodeBCP47LocaleIdentifier | Locale | (UnicodeBCP47LocaleIdentifier | Locale)[] | undefined;
|
||||
|
||||
/**
|
||||
* An object with some or all of properties of `options` parameter
|
||||
@@ -295,30 +295,32 @@ declare namespace Intl {
|
||||
| "code"
|
||||
| "none";
|
||||
|
||||
type ResolvedDisplayNamesType =
|
||||
type DisplayNamesType =
|
||||
| "language"
|
||||
| "region"
|
||||
| "script"
|
||||
| "calendar"
|
||||
| "dateTimeField"
|
||||
| "currency";
|
||||
|
||||
type DisplayNamesType =
|
||||
| ResolvedDisplayNamesType
|
||||
| "calendar"
|
||||
| "datetimeField";
|
||||
type DisplayNamesLanguageDisplay =
|
||||
| "dialect"
|
||||
| "standard";
|
||||
|
||||
interface DisplayNamesOptions {
|
||||
localeMatcher: RelativeTimeFormatLocaleMatcher;
|
||||
style: RelativeTimeFormatStyle;
|
||||
localeMatcher?: RelativeTimeFormatLocaleMatcher;
|
||||
style?: RelativeTimeFormatStyle;
|
||||
type: DisplayNamesType;
|
||||
languageDisplay: "dialect" | "standard";
|
||||
fallback: DisplayNamesFallback;
|
||||
languageDisplay?: DisplayNamesLanguageDisplay;
|
||||
fallback?: DisplayNamesFallback;
|
||||
}
|
||||
|
||||
interface ResolvedDisplayNamesOptions {
|
||||
locale: UnicodeBCP47LocaleIdentifier;
|
||||
style: RelativeTimeFormatStyle;
|
||||
type: ResolvedDisplayNamesType;
|
||||
type: DisplayNamesType;
|
||||
fallback: DisplayNamesFallback;
|
||||
languageDisplay?: DisplayNamesLanguageDisplay;
|
||||
}
|
||||
|
||||
interface DisplayNames {
|
||||
@@ -365,7 +367,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/DisplayNames).
|
||||
*/
|
||||
new(locales?: BCP47LanguageTag | BCP47LanguageTag[], options?: Partial<DisplayNamesOptions>): DisplayNames;
|
||||
new(locales: LocalesArgument, options: DisplayNamesOptions): DisplayNames;
|
||||
|
||||
/**
|
||||
* Returns an array containing those of the provided locales that are supported in display names without having to fall back to the runtime's default locale.
|
||||
@@ -380,7 +382,7 @@ declare namespace Intl {
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/supportedLocalesOf).
|
||||
*/
|
||||
supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: {localeMatcher: RelativeTimeFormatLocaleMatcher}): BCP47LanguageTag[];
|
||||
supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: RelativeTimeFormatLocaleMatcher }): BCP47LanguageTag[];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Vendored
+102
@@ -21,4 +21,106 @@ declare namespace Intl {
|
||||
dayPeriod?: "narrow" | "short" | "long";
|
||||
fractionalSecondDigits?: 0 | 1 | 2 | 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* The locale matching algorithm to use.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
|
||||
*/
|
||||
type ListFormatLocaleMatcher = "lookup" | "best fit";
|
||||
|
||||
/**
|
||||
* The format of output message.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
|
||||
*/
|
||||
type ListFormatType = "conjunction" | "disjunction" | "unit";
|
||||
|
||||
/**
|
||||
* The length of the formatted message.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
|
||||
*/
|
||||
type ListFormatStyle = "long" | "short" | "narrow";
|
||||
|
||||
/**
|
||||
* An object with some or all properties of the `Intl.ListFormat` constructor `options` parameter.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters).
|
||||
*/
|
||||
interface ListFormatOptions {
|
||||
/** The locale matching algorithm to use. For information about this option, see [Intl page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_negotiation). */
|
||||
localeMatcher?: ListFormatLocaleMatcher | undefined;
|
||||
/** The format of output message. */
|
||||
type?: ListFormatType | undefined;
|
||||
/** The length of the internationalized message. */
|
||||
style?: ListFormatStyle | undefined;
|
||||
}
|
||||
|
||||
interface ListFormat {
|
||||
/**
|
||||
* Returns a string with a language-specific representation of the list.
|
||||
*
|
||||
* @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array).
|
||||
*
|
||||
* @throws `TypeError` if `list` includes something other than the possible values.
|
||||
*
|
||||
* @returns {string} A language-specific formatted string representing the elements of the list.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/format).
|
||||
*/
|
||||
format(list: Iterable<string>): string;
|
||||
|
||||
/**
|
||||
* Returns an Array of objects representing the different components that can be used to format a list of values in a locale-aware fashion.
|
||||
*
|
||||
* @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array), to be formatted according to a locale.
|
||||
*
|
||||
* @throws `TypeError` if `list` includes something other than the possible values.
|
||||
*
|
||||
* @returns {{ type: "element" | "literal", value: string; }[]} An Array of components which contains the formatted parts from the list.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/formatToParts).
|
||||
*/
|
||||
formatToParts(list: Iterable<string>): { type: "element" | "literal", value: string; }[];
|
||||
}
|
||||
|
||||
const ListFormat: {
|
||||
prototype: ListFormat;
|
||||
|
||||
/**
|
||||
* Creates [Intl.ListFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) objects that
|
||||
* enable language-sensitive list formatting.
|
||||
*
|
||||
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
|
||||
* For the general form and interpretation of the `locales` argument,
|
||||
* see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
|
||||
*
|
||||
* @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters)
|
||||
* with some or all options of `ListFormatOptions`.
|
||||
*
|
||||
* @returns [Intl.ListFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) object.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat).
|
||||
*/
|
||||
new(locales?: BCP47LanguageTag | BCP47LanguageTag[], options?: ListFormatOptions): ListFormat;
|
||||
|
||||
/**
|
||||
* Returns an array containing those of the provided locales that are
|
||||
* supported in list formatting without having to fall back to the runtime's default locale.
|
||||
*
|
||||
* @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings.
|
||||
* For the general form and interpretation of the `locales` argument,
|
||||
* see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
|
||||
*
|
||||
* @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf#parameters).
|
||||
* with some or all possible options.
|
||||
*
|
||||
* @returns An array of strings representing a subset of the given locale tags that are supported in list
|
||||
* formatting without having to fall back to the runtime's default locale.
|
||||
*
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf).
|
||||
*/
|
||||
supportedLocalesOf(locales: BCP47LanguageTag | BCP47LanguageTag[], options?: Pick<ListFormatOptions, "localeMatcher">): BCP47LanguageTag[];
|
||||
};
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -4404,7 +4404,7 @@ declare namespace Intl {
|
||||
hour?: "numeric" | "2-digit" | undefined;
|
||||
minute?: "numeric" | "2-digit" | undefined;
|
||||
second?: "numeric" | "2-digit" | undefined;
|
||||
timeZoneName?: "long" | "short" | undefined;
|
||||
timeZoneName?: "short" | "long" | "shortOffset" | "longOffset" | "shortGeneric" | "longGeneric" | undefined;
|
||||
formatMatcher?: "best fit" | "basic" | undefined;
|
||||
hour12?: boolean | undefined;
|
||||
timeZone?: string | undefined;
|
||||
|
||||
Vendored
+110
-25
@@ -359,6 +359,11 @@ interface MultiCacheQueryOptions extends CacheQueryOptions {
|
||||
cacheName?: string;
|
||||
}
|
||||
|
||||
interface NavigationPreloadState {
|
||||
enabled?: boolean;
|
||||
headerValue?: string;
|
||||
}
|
||||
|
||||
interface NotificationAction {
|
||||
action: string;
|
||||
icon?: string;
|
||||
@@ -455,6 +460,22 @@ interface QueuingStrategyInit {
|
||||
highWaterMark: number;
|
||||
}
|
||||
|
||||
interface RTCEncodedAudioFrameMetadata {
|
||||
contributingSources?: number[];
|
||||
synchronizationSource?: number;
|
||||
}
|
||||
|
||||
interface RTCEncodedVideoFrameMetadata {
|
||||
contributingSources?: number[];
|
||||
dependencies?: number[];
|
||||
frameId?: number;
|
||||
height?: number;
|
||||
spatialIndex?: number;
|
||||
synchronizationSource?: number;
|
||||
temporalIndex?: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
interface ReadableStreamDefaultReadDoneResult {
|
||||
done: true;
|
||||
value?: undefined;
|
||||
@@ -628,6 +649,13 @@ interface UnderlyingSource<R = any> {
|
||||
type?: undefined;
|
||||
}
|
||||
|
||||
interface VideoColorSpaceInit {
|
||||
fullRange?: boolean;
|
||||
matrix?: VideoMatrixCoefficients;
|
||||
primaries?: VideoColorPrimaries;
|
||||
transfer?: VideoTransferCharacteristics;
|
||||
}
|
||||
|
||||
interface VideoConfiguration {
|
||||
bitrate: number;
|
||||
colorGamut?: ColorGamut;
|
||||
@@ -675,7 +703,7 @@ interface AbortController {
|
||||
/** Returns the AbortSignal object associated with this object. */
|
||||
readonly signal: AbortSignal;
|
||||
/** Invoking this method will set this object's AbortSignal's aborted flag and signal to any observers that the associated activity is to be aborted. */
|
||||
abort(reason?: any): void;
|
||||
// abort(): AbortSignal; - To be re-added in the future
|
||||
}
|
||||
|
||||
declare var AbortController: {
|
||||
@@ -692,6 +720,8 @@ interface AbortSignal extends EventTarget {
|
||||
/** Returns true if this AbortSignal's AbortController has signaled to abort, and false otherwise. */
|
||||
readonly aborted: boolean;
|
||||
onabort: ((this: AbortSignal, ev: Event) => any) | null;
|
||||
readonly reason: any;
|
||||
throwIfAborted(): void;
|
||||
addEventListener<K extends keyof AbortSignalEventMap>(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof AbortSignalEventMap>(type: K, listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
@@ -701,7 +731,7 @@ interface AbortSignal extends EventTarget {
|
||||
declare var AbortSignal: {
|
||||
prototype: AbortSignal;
|
||||
new(): AbortSignal;
|
||||
// abort(): AbortSignal; - To be re-added in the future
|
||||
abort(reason?: any): AbortSignal;
|
||||
};
|
||||
|
||||
interface AbstractWorkerEventMap {
|
||||
@@ -727,7 +757,7 @@ interface Blob {
|
||||
readonly type: string;
|
||||
arrayBuffer(): Promise<ArrayBuffer>;
|
||||
slice(start?: number, end?: number, contentType?: string): Blob;
|
||||
stream(): ReadableStream;
|
||||
stream(): ReadableStream<Uint8Array>;
|
||||
text(): Promise<string>;
|
||||
}
|
||||
|
||||
@@ -787,13 +817,13 @@ declare var ByteLengthQueuingStrategy: {
|
||||
* Available only in secure contexts.
|
||||
*/
|
||||
interface Cache {
|
||||
add(request: RequestInfo): Promise<void>;
|
||||
add(request: RequestInfo | URL): Promise<void>;
|
||||
addAll(requests: RequestInfo[]): Promise<void>;
|
||||
delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;
|
||||
keys(request?: RequestInfo, options?: CacheQueryOptions): Promise<ReadonlyArray<Request>>;
|
||||
match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response | undefined>;
|
||||
matchAll(request?: RequestInfo, options?: CacheQueryOptions): Promise<ReadonlyArray<Response>>;
|
||||
put(request: RequestInfo, response: Response): Promise<void>;
|
||||
delete(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<boolean>;
|
||||
keys(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Request>>;
|
||||
match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>;
|
||||
matchAll(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<ReadonlyArray<Response>>;
|
||||
put(request: RequestInfo | URL, response: Response): Promise<void>;
|
||||
}
|
||||
|
||||
declare var Cache: {
|
||||
@@ -809,7 +839,7 @@ interface CacheStorage {
|
||||
delete(cacheName: string): Promise<boolean>;
|
||||
has(cacheName: string): Promise<boolean>;
|
||||
keys(): Promise<string[]>;
|
||||
match(request: RequestInfo, options?: MultiCacheQueryOptions): Promise<Response | undefined>;
|
||||
match(request: RequestInfo | URL, options?: MultiCacheQueryOptions): Promise<Response | undefined>;
|
||||
open(cacheName: string): Promise<Cache>;
|
||||
}
|
||||
|
||||
@@ -1442,6 +1472,7 @@ declare var ExtendableMessageEvent: {
|
||||
interface FetchEvent extends ExtendableEvent {
|
||||
readonly clientId: string;
|
||||
readonly handled: Promise<undefined>;
|
||||
readonly preloadResponse: Promise<any>;
|
||||
readonly request: Request;
|
||||
readonly resultingClientId: string;
|
||||
respondWith(r: Response | PromiseLike<Response>): void;
|
||||
@@ -2095,6 +2126,7 @@ declare var ImageBitmapRenderingContext: {
|
||||
|
||||
/** The underlying pixel data of an area of a <canvas> element. It is created using the ImageData() constructor or creator methods on the CanvasRenderingContext2D object associated with a canvas: createImageData() and getImageData(). It can also be used to set a part of the canvas by using putImageData(). */
|
||||
interface ImageData {
|
||||
readonly colorSpace: PredefinedColorSpace;
|
||||
/** Returns the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255. */
|
||||
readonly data: Uint8ClampedArray;
|
||||
/** Returns the actual dimensions of the data in the ImageData object, in pixels. */
|
||||
@@ -2211,6 +2243,19 @@ declare var MessagePort: {
|
||||
new(): MessagePort;
|
||||
};
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface NavigationPreloadManager {
|
||||
disable(): Promise<void>;
|
||||
enable(): Promise<void>;
|
||||
getState(): Promise<NavigationPreloadState>;
|
||||
setHeaderValue(value: string): Promise<void>;
|
||||
}
|
||||
|
||||
declare var NavigationPreloadManager: {
|
||||
prototype: NavigationPreloadManager;
|
||||
new(): NavigationPreloadManager;
|
||||
};
|
||||
|
||||
interface NavigatorConcurrentHardware {
|
||||
readonly hardwareConcurrency: number;
|
||||
}
|
||||
@@ -2234,6 +2279,11 @@ interface NavigatorLanguage {
|
||||
readonly languages: ReadonlyArray<string>;
|
||||
}
|
||||
|
||||
/** Available only in secure contexts. */
|
||||
interface NavigatorLocks {
|
||||
readonly locks: LockManager;
|
||||
}
|
||||
|
||||
interface NavigatorNetworkInformation {
|
||||
readonly connection: NetworkInformation;
|
||||
}
|
||||
@@ -2609,6 +2659,29 @@ declare var PushSubscriptionOptions: {
|
||||
new(): PushSubscriptionOptions;
|
||||
};
|
||||
|
||||
interface RTCEncodedAudioFrame {
|
||||
data: ArrayBuffer;
|
||||
readonly timestamp: number;
|
||||
getMetadata(): RTCEncodedAudioFrameMetadata;
|
||||
}
|
||||
|
||||
declare var RTCEncodedAudioFrame: {
|
||||
prototype: RTCEncodedAudioFrame;
|
||||
new(): RTCEncodedAudioFrame;
|
||||
};
|
||||
|
||||
interface RTCEncodedVideoFrame {
|
||||
data: ArrayBuffer;
|
||||
readonly timestamp: number;
|
||||
readonly type: RTCEncodedVideoFrameType;
|
||||
getMetadata(): RTCEncodedVideoFrameMetadata;
|
||||
}
|
||||
|
||||
declare var RTCEncodedVideoFrame: {
|
||||
prototype: RTCEncodedVideoFrame;
|
||||
new(): RTCEncodedVideoFrame;
|
||||
};
|
||||
|
||||
/** This Streams API interface represents a readable stream of byte data. The Fetch API offers a concrete instance of a ReadableStream through the body property of a Response object. */
|
||||
interface ReadableStream<R = any> {
|
||||
readonly locked: boolean;
|
||||
@@ -2684,7 +2757,7 @@ interface Request extends Body {
|
||||
|
||||
declare var Request: {
|
||||
prototype: Request;
|
||||
new(input: RequestInfo, init?: RequestInit): Request;
|
||||
new(input: RequestInfo | URL, init?: RequestInit): Request;
|
||||
};
|
||||
|
||||
/** This Fetch API interface represents the response to a request. */
|
||||
@@ -2829,6 +2902,7 @@ interface ServiceWorkerRegistrationEventMap {
|
||||
interface ServiceWorkerRegistration extends EventTarget {
|
||||
readonly active: ServiceWorker | null;
|
||||
readonly installing: ServiceWorker | null;
|
||||
readonly navigationPreload: NavigationPreloadManager;
|
||||
onupdatefound: ((this: ServiceWorkerRegistration, ev: Event) => any) | null;
|
||||
readonly pushManager: PushManager;
|
||||
readonly scope: string;
|
||||
@@ -2894,10 +2968,10 @@ interface SubtleCrypto {
|
||||
encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>;
|
||||
exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>;
|
||||
exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair | CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
sign(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>;
|
||||
unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
@@ -3075,6 +3149,19 @@ declare var URLSearchParams: {
|
||||
toString(): string;
|
||||
};
|
||||
|
||||
interface VideoColorSpace {
|
||||
readonly fullRange: boolean | null;
|
||||
readonly matrix: VideoMatrixCoefficients | null;
|
||||
readonly primaries: VideoColorPrimaries | null;
|
||||
readonly transfer: VideoTransferCharacteristics | null;
|
||||
toJSON(): VideoColorSpaceInit;
|
||||
}
|
||||
|
||||
declare var VideoColorSpace: {
|
||||
prototype: VideoColorSpace;
|
||||
new(init?: VideoColorSpaceInit): VideoColorSpace;
|
||||
};
|
||||
|
||||
interface WEBGL_color_buffer_float {
|
||||
readonly FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: GLenum;
|
||||
readonly RGBA32F_EXT: GLenum;
|
||||
@@ -3130,13 +3217,6 @@ interface WEBGL_compressed_texture_etc1 {
|
||||
readonly COMPRESSED_RGB_ETC1_WEBGL: GLenum;
|
||||
}
|
||||
|
||||
interface WEBGL_compressed_texture_pvrtc {
|
||||
readonly COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGB_PVRTC_2BPPV1_IMG: GLenum;
|
||||
readonly COMPRESSED_RGB_PVRTC_4BPPV1_IMG: GLenum;
|
||||
}
|
||||
|
||||
/** The WEBGL_compressed_texture_s3tc extension is part of the WebGL API and exposes four S3TC compressed texture formats. */
|
||||
interface WEBGL_compressed_texture_s3tc {
|
||||
readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: GLenum;
|
||||
@@ -4627,7 +4707,6 @@ interface WebGLRenderingContextBase {
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_astc"): WEBGL_compressed_texture_astc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_etc"): WEBGL_compressed_texture_etc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_etc1"): WEBGL_compressed_texture_etc1 | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_pvrtc"): WEBGL_compressed_texture_pvrtc | null;
|
||||
getExtension(extensionName: "WEBGL_compressed_texture_s3tc_srgb"): WEBGL_compressed_texture_s3tc_srgb | null;
|
||||
getExtension(extensionName: "WEBGL_debug_shaders"): WEBGL_debug_shaders | null;
|
||||
getExtension(extensionName: "WEBGL_draw_buffers"): WEBGL_draw_buffers | null;
|
||||
@@ -5183,11 +5262,12 @@ interface WindowOrWorkerGlobalScope {
|
||||
clearTimeout(id?: number): void;
|
||||
createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
|
||||
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
||||
queueMicrotask(callback: VoidFunction): void;
|
||||
reportError(e: any): void;
|
||||
setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
structuredClone(value: any, options?: StructuredSerializeOptions): any;
|
||||
}
|
||||
|
||||
interface WorkerEventMap extends AbstractWorkerEventMap {
|
||||
@@ -5271,7 +5351,7 @@ declare var WorkerLocation: {
|
||||
};
|
||||
|
||||
/** A subset of the Navigator interface allowed to be accessed from a Worker. Such an object is initialized for each worker and is available via the WorkerGlobalScope.navigator property obtained by calling window.self.navigator. */
|
||||
interface WorkerNavigator extends NavigatorConcurrentHardware, NavigatorID, NavigatorLanguage, NavigatorNetworkInformation, NavigatorOnLine, NavigatorStorage {
|
||||
interface WorkerNavigator extends NavigatorConcurrentHardware, NavigatorID, NavigatorLanguage, NavigatorLocks, NavigatorNetworkInformation, NavigatorOnLine, NavigatorStorage {
|
||||
readonly mediaCapabilities: MediaCapabilities;
|
||||
}
|
||||
|
||||
@@ -5722,11 +5802,12 @@ declare function clearInterval(id?: number): void;
|
||||
declare function clearTimeout(id?: number): void;
|
||||
declare function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
declare function createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;
|
||||
declare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
|
||||
declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
||||
declare function queueMicrotask(callback: VoidFunction): void;
|
||||
declare function reportError(e: any): void;
|
||||
declare function setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
|
||||
declare function structuredClone(value: any, options?: StructuredSerializeOptions): any;
|
||||
declare function cancelAnimationFrame(handle: number): void;
|
||||
declare function requestAnimationFrame(callback: FrameRequestCallback): number;
|
||||
declare function addEventListener<K extends keyof DedicatedWorkerGlobalScopeEventMap>(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
@@ -5807,6 +5888,7 @@ type PermissionState = "denied" | "granted" | "prompt";
|
||||
type PredefinedColorSpace = "display-p3" | "srgb";
|
||||
type PremultiplyAlpha = "default" | "none" | "premultiply";
|
||||
type PushEncryptionKeyName = "auth" | "p256dh";
|
||||
type RTCEncodedVideoFrameType = "delta" | "empty" | "key";
|
||||
type ReferrerPolicy = "" | "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" | "unsafe-url";
|
||||
type RequestCache = "default" | "force-cache" | "no-cache" | "no-store" | "only-if-cached" | "reload";
|
||||
type RequestCredentials = "include" | "omit" | "same-origin";
|
||||
@@ -5819,6 +5901,9 @@ type SecurityPolicyViolationEventDisposition = "enforce" | "report";
|
||||
type ServiceWorkerState = "activated" | "activating" | "installed" | "installing" | "parsed" | "redundant";
|
||||
type ServiceWorkerUpdateViaCache = "all" | "imports" | "none";
|
||||
type TransferFunction = "hlg" | "pq" | "srgb";
|
||||
type VideoColorPrimaries = "bt470bg" | "bt709" | "smpte170m";
|
||||
type VideoMatrixCoefficients = "bt470bg" | "bt709" | "rgb" | "smpte170m";
|
||||
type VideoTransferCharacteristics = "bt709" | "iec61966-2-1" | "smpte170m";
|
||||
type WebGLPowerPreference = "default" | "high-performance" | "low-power";
|
||||
type WorkerType = "classic" | "module";
|
||||
type XMLHttpRequestResponseType = "" | "arraybuffer" | "blob" | "document" | "json" | "text";
|
||||
|
||||
+3
-3
@@ -58,10 +58,10 @@ interface MessageEvent<T = any> {
|
||||
|
||||
interface SubtleCrypto {
|
||||
deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>;
|
||||
generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKeyPair | CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
|
||||
importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKey>;
|
||||
importKey(format: Exclude<KeyFormat, "jwk">, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: Iterable<KeyUsage>): Promise<CryptoKey>;
|
||||
}
|
||||
|
||||
@@ -8184,6 +8184,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[解析模块时要搜索的文件名后缀列表。]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8184,6 +8184,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[解析模組時要搜尋的檔案名尾碼清單。]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8193,6 +8193,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Seznam přípon názvů souborů, které se mají vyhledat při překladu modulu]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8181,6 +8181,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Liste der Dateinamensuffixe, die beim Auflösen eines Moduls gesucht werden sollen.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8196,6 +8196,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Lista de sufijos de nombre de archivo para buscar al resolver un módulo.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8196,6 +8196,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Liste des suffixes de nom de fichier à rechercher lors de la résolution d’un module.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8184,6 +8184,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Elenco dei suffissi dei nomi di file da cercare durante la risoluzione di un modulo.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8184,6 +8184,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[モジュールを解決するときに検索するファイル名サフィックスのリスト。]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8184,6 +8184,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[모듈을 확인할 때 검색할 파일 이름 접미사 목록입니다.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8174,6 +8174,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Lista sufiksów nazw plików do przeszukania podczas rozpoznawania modułu.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8177,6 +8177,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Lista de sufixos de nome de arquivo a serem pesquisadas ao resolver um módulo.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8183,6 +8183,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Список суффиксов имен файлов для поиска при разрешении модуля.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -8177,6 +8177,15 @@
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_file_name_suffixes_to_search_when_resolving_a_module_6931" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of file name suffixes to search when resolving a module.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Bir modül çözümlenirken aranacak dosya adı son eklerinin listesi.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
</Item>
|
||||
<Item ItemId=";List_of_folders_to_include_type_definitions_from_6161" ItemType="0" PsrId="306" Leaf="true">
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[List of folders to include type definitions from.]]></Val>
|
||||
|
||||
@@ -1159,9 +1159,12 @@ namespace ts.server.protocol {
|
||||
isWriteAccess: boolean;
|
||||
|
||||
/**
|
||||
* True if reference is a definition, false otherwise.
|
||||
* Present only if the search was triggered from a declaration.
|
||||
* True indicates that the references refers to the same symbol
|
||||
* (i.e. has the same meaning) as the declaration that began the
|
||||
* search.
|
||||
*/
|
||||
isDefinition: boolean;
|
||||
isDefinition?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -354,6 +354,7 @@ namespace ts.server {
|
||||
logger.info(`Finding references to ${location.fileName} position ${location.pos} in project ${project.getProjectName()}`);
|
||||
const projectOutputs = project.getLanguageService().findReferences(location.fileName, location.pos);
|
||||
if (projectOutputs) {
|
||||
const clearIsDefinition = projectOutputs[0].references[0].isDefinition === undefined;
|
||||
for (const referencedSymbol of projectOutputs) {
|
||||
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(referencedSymbol.definition));
|
||||
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ?
|
||||
@@ -374,6 +375,9 @@ namespace ts.server {
|
||||
for (const ref of referencedSymbol.references) {
|
||||
// If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
|
||||
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
|
||||
if (clearIsDefinition) {
|
||||
delete ref.isDefinition;
|
||||
}
|
||||
symbolToAddTo.references.push(ref);
|
||||
}
|
||||
}
|
||||
@@ -3269,7 +3273,7 @@ namespace ts.server {
|
||||
return text;
|
||||
}
|
||||
|
||||
function referenceEntryToReferencesResponseItem(projectService: ProjectService, { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferenceEntry): protocol.ReferencesResponseItem {
|
||||
function referenceEntryToReferencesResponseItem(projectService: ProjectService, { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferencedSymbolEntry): protocol.ReferencesResponseItem {
|
||||
const scriptInfo = Debug.checkDefined(projectService.getScriptInfo(fileName));
|
||||
const span = toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo);
|
||||
const lineSpan = scriptInfo.lineToTextSpan(span.start.line - 1);
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace ts.codefix {
|
||||
const param = signature.parameters[argIndex].valueDeclaration;
|
||||
if (!(param && isParameter(param) && isIdentifier(param.name))) return undefined;
|
||||
|
||||
const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getTypeAtLocation(param), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false));
|
||||
const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false));
|
||||
if (!length(properties)) return undefined;
|
||||
return { kind: InfoKind.ObjectLiteral, token: param.name, properties, parentDeclaration: parent };
|
||||
}
|
||||
|
||||
@@ -192,7 +192,12 @@ namespace ts.codefix {
|
||||
const program = context.program;
|
||||
const checker = program.getTypeChecker();
|
||||
const scriptTarget = getEmitScriptTarget(program.getCompilerOptions());
|
||||
const flags = NodeBuilderFlags.NoTruncation | NodeBuilderFlags.NoUndefinedOptionalParameterType | NodeBuilderFlags.SuppressAnyReturnType | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : 0);
|
||||
const flags =
|
||||
NodeBuilderFlags.NoTruncation
|
||||
| NodeBuilderFlags.NoUndefinedOptionalParameterType
|
||||
| NodeBuilderFlags.SuppressAnyReturnType
|
||||
| NodeBuilderFlags.AllowEmptyTuple
|
||||
| (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None);
|
||||
const signatureDeclaration = checker.signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)) as ArrowFunction | FunctionExpression | MethodDeclaration;
|
||||
if (!signatureDeclaration) {
|
||||
return undefined;
|
||||
|
||||
@@ -206,17 +206,27 @@ namespace ts.FindAllReferences {
|
||||
|
||||
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, { use: FindReferencesUse.References });
|
||||
const options = { use: FindReferencesUse.References };
|
||||
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options);
|
||||
const checker = program.getTypeChecker();
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
// Unless the starting node is a declaration (vs e.g. JSDoc), don't attempt to compute isDefinition
|
||||
const adjustedNode = Core.getAdjustedNode(node, options);
|
||||
const symbol = isDefinitionForReference(adjustedNode) ? checker.getSymbolAtLocation(adjustedNode) : undefined;
|
||||
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined<SymbolAndEntries, ReferencedSymbol>(referencedSymbols, ({ definition, references }) =>
|
||||
// Only include referenced symbols that have a valid definition.
|
||||
definition && {
|
||||
definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)),
|
||||
references: references.map(r => toReferenceEntry(r, symbol))
|
||||
references: references.map(r => toReferencedSymbolEntry(r, symbol))
|
||||
});
|
||||
}
|
||||
|
||||
function isDefinitionForReference(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.DefaultKeyword
|
||||
|| !!getDeclarationFromName(node)
|
||||
|| isLiteralComputedPropertyDeclarationName(node)
|
||||
|| (node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent));
|
||||
}
|
||||
|
||||
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined {
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
let referenceEntries: Entry[] | undefined;
|
||||
@@ -388,16 +398,24 @@ namespace ts.FindAllReferences {
|
||||
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
|
||||
}
|
||||
|
||||
export function toReferenceEntry(entry: Entry, symbol: Symbol | undefined): ReferenceEntry {
|
||||
function toReferencedSymbolEntry(entry: Entry, symbol: Symbol | undefined): ReferencedSymbolEntry {
|
||||
const referenceEntry = toReferenceEntry(entry);
|
||||
if (!symbol) return referenceEntry;
|
||||
return {
|
||||
...referenceEntry,
|
||||
isDefinition: entry.kind !== EntryKind.Span && isDeclarationOfSymbol(entry.node, symbol)
|
||||
};
|
||||
}
|
||||
|
||||
export function toReferenceEntry(entry: Entry): ReferenceEntry {
|
||||
const documentSpan = entryToDocumentSpan(entry);
|
||||
if (entry.kind === EntryKind.Span) {
|
||||
return { ...documentSpan, isWriteAccess: false, isDefinition: false };
|
||||
return { ...documentSpan, isWriteAccess: false };
|
||||
}
|
||||
const { kind, node } = entry;
|
||||
return {
|
||||
...documentSpan,
|
||||
isWriteAccess: isWriteAccessForReference(node),
|
||||
isDefinition: isDeclarationOfSymbol(node, symbol),
|
||||
isInString: kind === EntryKind.StringLiteral ? true : undefined,
|
||||
};
|
||||
}
|
||||
@@ -622,12 +640,7 @@ namespace ts.FindAllReferences {
|
||||
export namespace Core {
|
||||
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
|
||||
export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlySet<string> = new Set(sourceFiles.map(f => f.fileName))): readonly SymbolAndEntries[] | undefined {
|
||||
if (options.use === FindReferencesUse.References) {
|
||||
node = getAdjustedReferenceLocation(node);
|
||||
}
|
||||
else if (options.use === FindReferencesUse.Rename) {
|
||||
node = getAdjustedRenameLocation(node);
|
||||
}
|
||||
node = getAdjustedNode(node, options);
|
||||
if (isSourceFile(node)) {
|
||||
const resolvedRef = GoToDefinition.getReferenceAtPosition(node, position, program);
|
||||
if (!resolvedRef?.file) {
|
||||
@@ -695,6 +708,16 @@ namespace ts.FindAllReferences {
|
||||
return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget);
|
||||
}
|
||||
|
||||
export function getAdjustedNode(node: Node, options: Options) {
|
||||
if (options.use === FindReferencesUse.References) {
|
||||
node = getAdjustedReferenceLocation(node);
|
||||
}
|
||||
else if (options.use === FindReferencesUse.Rename) {
|
||||
node = getAdjustedRenameLocation(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function getReferencesForFileName(fileName: string, program: Program, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet<string> = new Set(sourceFiles.map(f => f.fileName))): readonly Entry[] {
|
||||
const moduleSymbol = program.getSourceFile(fileName)?.symbol;
|
||||
if (moduleSymbol) {
|
||||
@@ -1187,10 +1210,15 @@ namespace ts.FindAllReferences {
|
||||
cb: (ref: Identifier) => void,
|
||||
): void {
|
||||
const importTracker = createImportTracker(sourceFiles, new Set(sourceFiles.map(f => f.fileName)), checker, cancellationToken);
|
||||
const { importSearches, indirectUsers } = importTracker(exportSymbol, { exportKind: isDefaultExport ? ExportKind.Default : ExportKind.Named, exportingModuleSymbol }, /*isForRename*/ false);
|
||||
const { importSearches, indirectUsers, singleReferences } = importTracker(exportSymbol, { exportKind: isDefaultExport ? ExportKind.Default : ExportKind.Named, exportingModuleSymbol }, /*isForRename*/ false);
|
||||
for (const [importLocation] of importSearches) {
|
||||
cb(importLocation);
|
||||
}
|
||||
for (const singleReference of singleReferences) {
|
||||
if (isIdentifier(singleReference) && isImportTypeNode(singleReference.parent)) {
|
||||
cb(singleReference);
|
||||
}
|
||||
}
|
||||
for (const indirectUser of indirectUsers) {
|
||||
for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) {
|
||||
// Import specifiers should be handled by importSearches
|
||||
|
||||
@@ -56,9 +56,9 @@ namespace ts.formatting {
|
||||
// for block indentation, we should look for a line which contains something that's not
|
||||
// whitespace.
|
||||
const currentToken = getTokenAtPosition(sourceFile, position);
|
||||
// for object literal, we want to the indentation work like block
|
||||
// if { starts in any position (can be in the middle of line)
|
||||
// the following indentation should treat { as starting of that line (including leading whitespace)
|
||||
// For object literals, we want indentation to work just like with blocks.
|
||||
// If the `{` starts in any position (even in the middle of a line), then
|
||||
// the following indentation should treat `{` as the start of that line (including leading whitespace).
|
||||
// ```
|
||||
// const a: { x: undefined, y: undefined } = {} // leading 4 whitespaces and { starts in the middle of line
|
||||
// ->
|
||||
@@ -76,7 +76,8 @@ namespace ts.formatting {
|
||||
// y: undefined,
|
||||
// }
|
||||
// ```
|
||||
if (options.indentStyle === IndentStyle.Block || currentToken.kind === SyntaxKind.OpenBraceToken) {
|
||||
const isObjectLiteral = currentToken.kind === SyntaxKind.OpenBraceToken && currentToken.parent.kind === SyntaxKind.ObjectLiteralExpression;
|
||||
if (options.indentStyle === IndentStyle.Block || isObjectLiteral) {
|
||||
return getBlockIndent(sourceFile, position, options);
|
||||
}
|
||||
|
||||
@@ -91,7 +92,9 @@ namespace ts.formatting {
|
||||
const containerList = getListByPosition(position, precedingToken.parent, sourceFile);
|
||||
// use list position if the preceding token is before any list items
|
||||
if (containerList && !rangeContainsRange(containerList, precedingToken)) {
|
||||
return getActualIndentationForListStartLine(containerList, sourceFile, options) + options.indentSize!; // TODO: GH#18217
|
||||
const useTheSameBaseIndentation = [SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction].indexOf(currentToken.parent.kind) !== -1;
|
||||
const indentSize = useTheSameBaseIndentation ? 0 : options.indentSize!;
|
||||
return getActualIndentationForListStartLine(containerList, sourceFile, options) + indentSize; // TODO: GH#18217
|
||||
}
|
||||
|
||||
return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options);
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace ts.OrganizeImports {
|
||||
preferences: UserPreferences,
|
||||
skipDestructiveCodeActions?: boolean
|
||||
) {
|
||||
|
||||
const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext, preferences });
|
||||
|
||||
const coalesceAndOrganizeImports = (importGroup: readonly ImportDeclaration[]) => stableSort(
|
||||
@@ -23,8 +22,8 @@ namespace ts.OrganizeImports {
|
||||
(s1, s2) => compareImportsOrRequireStatements(s1, s2));
|
||||
|
||||
// All of the old ImportDeclarations in the file, in syntactic order.
|
||||
const topLevelImportDecls = sourceFile.statements.filter(isImportDeclaration);
|
||||
organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports);
|
||||
const topLevelImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, sourceFile.statements.filter(isImportDeclaration));
|
||||
topLevelImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, coalesceAndOrganizeImports));
|
||||
|
||||
// All of the old ExportDeclarations in the file, in syntactic order.
|
||||
const topLevelExportDecls = sourceFile.statements.filter(isExportDeclaration);
|
||||
@@ -33,8 +32,8 @@ namespace ts.OrganizeImports {
|
||||
for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) {
|
||||
if (!ambientModule.body) continue;
|
||||
|
||||
const ambientModuleImportDecls = ambientModule.body.statements.filter(isImportDeclaration);
|
||||
organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports);
|
||||
const ambientModuleImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(isImportDeclaration));
|
||||
ambientModuleImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, coalesceAndOrganizeImports));
|
||||
|
||||
const ambientModuleExportDecls = ambientModule.body.statements.filter(isExportDeclaration);
|
||||
organizeImportsWorker(ambientModuleExportDecls, coalesceExports);
|
||||
@@ -88,6 +87,48 @@ namespace ts.OrganizeImports {
|
||||
}
|
||||
}
|
||||
|
||||
function groupImportsByNewlineContiguous(sourceFile: SourceFile, importDecls: ImportDeclaration[]): ImportDeclaration[][] {
|
||||
const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant);
|
||||
const groupImports: ImportDeclaration[][] = [];
|
||||
let groupIndex = 0;
|
||||
for (const topLevelImportDecl of importDecls) {
|
||||
if (isNewGroup(sourceFile, topLevelImportDecl, scanner)) {
|
||||
groupIndex++;
|
||||
}
|
||||
|
||||
if (!groupImports[groupIndex]) {
|
||||
groupImports[groupIndex] = [];
|
||||
}
|
||||
|
||||
groupImports[groupIndex].push(topLevelImportDecl);
|
||||
}
|
||||
|
||||
return groupImports;
|
||||
}
|
||||
|
||||
// a new group is created if an import includes at least two new line
|
||||
// new line from multi-line comment doesn't count
|
||||
function isNewGroup(sourceFile: SourceFile, topLevelImportDecl: ImportDeclaration, scanner: Scanner) {
|
||||
const startPos = topLevelImportDecl.getFullStart();
|
||||
const endPos = topLevelImportDecl.getStart();
|
||||
scanner.setText(sourceFile.text, startPos, endPos - startPos);
|
||||
|
||||
let numberOfNewLines = 0;
|
||||
while (scanner.getTokenPos() < endPos) {
|
||||
const tokenKind = scanner.scan();
|
||||
|
||||
if (tokenKind === SyntaxKind.NewLineTrivia) {
|
||||
numberOfNewLines++;
|
||||
|
||||
if (numberOfNewLines >= 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function removeUnusedImports(oldImports: readonly ImportDeclaration[], sourceFile: SourceFile, program: Program, skipDestructiveCodeActions: boolean | undefined) {
|
||||
// As a precaution, consider unused import detection to be destructive (GH #43051)
|
||||
if (skipDestructiveCodeActions) {
|
||||
|
||||
@@ -212,6 +212,10 @@ namespace ts.refactor {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.ImportType:
|
||||
const importTypeNode = parent as ImportTypeNode;
|
||||
changes.replaceNode(importingSourceFile, parent, factory.createImportTypeNode(importTypeNode.argument, factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf));
|
||||
break;
|
||||
default:
|
||||
Debug.failBadSyntaxKind(parent);
|
||||
}
|
||||
|
||||
@@ -639,7 +639,8 @@ namespace ts.refactor.extractSymbol {
|
||||
}
|
||||
|
||||
function isScope(node: Node): node is Scope {
|
||||
return isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node);
|
||||
return isArrowFunction(node) ? isFunctionBody(node.body) :
|
||||
isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -229,6 +229,8 @@ namespace ts.refactor {
|
||||
function doTypedefChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: ExtractInfo) {
|
||||
const { firstStatement, selection, typeParameters } = info;
|
||||
|
||||
setEmitFlags(selection, EmitFlags.NoComments | EmitFlags.NoNestedComments);
|
||||
|
||||
const node = factory.createJSDocTypedefTag(
|
||||
factory.createIdentifier("typedef"),
|
||||
factory.createJSDocTypeExpression(selection),
|
||||
|
||||
@@ -1798,7 +1798,6 @@ namespace ts {
|
||||
fileName: entry.fileName,
|
||||
textSpan: highlightSpan.textSpan,
|
||||
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
|
||||
isDefinition: false,
|
||||
...highlightSpan.isInString && { isInString: true },
|
||||
...highlightSpan.contextSpan && { contextSpan: highlightSpan.contextSpan }
|
||||
}))
|
||||
@@ -1838,7 +1837,7 @@ namespace ts {
|
||||
|
||||
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, (entry, node, checker) => FindAllReferences.toReferenceEntry(entry, checker.getSymbolAtLocation(node)));
|
||||
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, FindAllReferences.toReferenceEntry);
|
||||
}
|
||||
|
||||
function getReferencesWorker<T>(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry<T>): T[] | undefined {
|
||||
@@ -1859,8 +1858,7 @@ namespace ts {
|
||||
|
||||
function getFileReferences(fileName: string): ReferenceEntry[] {
|
||||
synchronizeHostData();
|
||||
const moduleSymbol = program.getSourceFile(fileName)?.symbol;
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(r => FindAllReferences.toReferenceEntry(r, moduleSymbol));
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry);
|
||||
}
|
||||
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { fileName: string; highlights: { start: number; length: number, isDefinition: boolean }[] }[]
|
||||
* { fileName: string; highlights: { start: number; length: number }[] }[]
|
||||
*
|
||||
* @param fileToSearch A JSON encoded string[] containing the file names that should be
|
||||
* considered when searching.
|
||||
|
||||
@@ -307,10 +307,13 @@ namespace ts.SignatureHelp {
|
||||
// for optional function condition.
|
||||
const nonNullableContextualType = contextualType.getNonNullableType();
|
||||
|
||||
const signatures = nonNullableContextualType.getCallSignatures();
|
||||
if (signatures.length !== 1) return undefined;
|
||||
const symbol = nonNullableContextualType.symbol;
|
||||
if (symbol === undefined) return undefined;
|
||||
|
||||
const invocation: ContextualInvocation = { kind: InvocationKind.Contextual, signature: first(signatures), node: startingToken, symbol: chooseBetterSymbol(nonNullableContextualType.symbol) };
|
||||
const signature = lastOrUndefined(nonNullableContextualType.getCallSignatures());
|
||||
if (signature === undefined) return undefined;
|
||||
|
||||
const invocation: ContextualInvocation = { kind: InvocationKind.Contextual, signature, node: startingToken, symbol: chooseBetterSymbol(symbol) };
|
||||
return { isTypeParameterList: false, invocation, argumentsSpan, argumentIndex, argumentCount };
|
||||
}
|
||||
|
||||
|
||||
@@ -1119,8 +1119,17 @@ namespace ts.textChanges {
|
||||
return skipTrivia(s, 0) === s.length;
|
||||
}
|
||||
|
||||
// A transformation context that won't perform parenthesization, as some parenthesization rules
|
||||
// are more aggressive than is strictly necessary.
|
||||
const textChangesTransformationContext: TransformationContext = {
|
||||
...nullTransformationContext,
|
||||
factory: createNodeFactory(
|
||||
nullTransformationContext.factory.flags | NodeFactoryFlags.NoParenthesizerRules,
|
||||
nullTransformationContext.factory.baseFactory),
|
||||
};
|
||||
|
||||
export function assignPositionsToNode(node: Node): Node {
|
||||
const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||
const visited = visitEachChild(node, assignPositionsToNode, textChangesTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
|
||||
// create proxy node for non synthesized nodes
|
||||
const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node;
|
||||
setTextRangePosEnd(newNode, getPos(node), getEnd(node));
|
||||
|
||||
@@ -886,7 +886,6 @@ namespace ts {
|
||||
|
||||
export interface ReferenceEntry extends DocumentSpan {
|
||||
isWriteAccess: boolean;
|
||||
isDefinition: boolean;
|
||||
isInString?: true;
|
||||
}
|
||||
|
||||
@@ -1046,7 +1045,11 @@ namespace ts {
|
||||
|
||||
export interface ReferencedSymbol {
|
||||
definition: ReferencedSymbolDefinitionInfo;
|
||||
references: ReferenceEntry[];
|
||||
references: ReferencedSymbolEntry[];
|
||||
}
|
||||
|
||||
export interface ReferencedSymbolEntry extends ReferenceEntry {
|
||||
isDefinition?: boolean;
|
||||
}
|
||||
|
||||
export enum SymbolDisplayPartKind {
|
||||
|
||||
@@ -17,8 +17,13 @@ describe("unittests:: Public APIs", () => {
|
||||
const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false);
|
||||
fs.linkSync(`${vfs.builtFolder}/${fileName}`, `${vfs.srcFolder}/${fileName}`);
|
||||
const sys = new fakes.System(fs);
|
||||
const host = new fakes.CompilerHost(sys);
|
||||
const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], {});
|
||||
const options: ts.CompilerOptions = {
|
||||
...ts.getDefaultCompilerOptions(),
|
||||
strict: true,
|
||||
exactOptionalPropertyTypes: true,
|
||||
};
|
||||
const host = new fakes.CompilerHost(sys, options);
|
||||
const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], options);
|
||||
assert(!result.diagnostics || !result.diagnostics.length, Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -679,23 +679,6 @@ import "lib1";
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" });
|
||||
|
||||
testOrganizeImports("SortComments",
|
||||
/*skipDestructiveCodeActions*/ false,
|
||||
{
|
||||
path: "/test.ts",
|
||||
content: `
|
||||
// Header
|
||||
import "lib3";
|
||||
// Comment2
|
||||
import "lib2";
|
||||
// Comment1
|
||||
import "lib1";
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" },
|
||||
{ path: "/lib3.ts", content: "" });
|
||||
|
||||
testOrganizeImports("AmbientModule",
|
||||
/*skipDestructiveCodeActions*/ false,
|
||||
{
|
||||
|
||||
@@ -1,30 +1,6 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => {
|
||||
let outFileFs: vfs.FileSystem;
|
||||
const enum Project { lib, app }
|
||||
function relName(path: string) {
|
||||
return path.slice(1);
|
||||
}
|
||||
type Sources = [string, readonly string[]];
|
||||
const enum Source { config, ts }
|
||||
const sources: [Sources, Sources] = [
|
||||
[
|
||||
"/src/lib/tsconfig.json",
|
||||
[
|
||||
"/src/lib/file0.ts",
|
||||
"/src/lib/file1.ts",
|
||||
"/src/lib/file2.ts",
|
||||
"/src/lib/global.ts",
|
||||
]
|
||||
],
|
||||
[
|
||||
"/src/app/tsconfig.json",
|
||||
[
|
||||
"/src/app/file3.ts",
|
||||
"/src/app/file4.ts"
|
||||
]
|
||||
]
|
||||
];
|
||||
before(() => {
|
||||
outFileFs = loadProjectFromDisk("tests/projects/amdModulesWithOut");
|
||||
});
|
||||
@@ -43,20 +19,20 @@ namespace ts {
|
||||
modifyFs,
|
||||
modifyAgainFs
|
||||
}: VerifyOutFileScenarioInput) {
|
||||
verifyTscIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "amdModulesWithOut",
|
||||
subScenario,
|
||||
fs: () => outFileFs,
|
||||
commandLineArgs: ["--b", "/src/app", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
modifyFs,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => appendText(fs, relName(sources[Project.lib][Source.ts][1]), "console.log(x);")
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => appendText(fs, "/src/lib/file1.ts", "console.log(x);")
|
||||
},
|
||||
...(modifyAgainFs ? [{
|
||||
buildKind: BuildKind.IncrementalHeadersChange,
|
||||
subScenario: "incremental-headers-change-without-dts-changes",
|
||||
modifyFs: modifyAgainFs
|
||||
}] : emptyArray),
|
||||
]
|
||||
@@ -73,15 +49,15 @@ namespace ts {
|
||||
verifyOutFileScenario({
|
||||
subScenario: "multiple prologues in all projects",
|
||||
modifyFs: fs => {
|
||||
enableStrict(fs, sources[Project.lib][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.lib][Source.ts][0], `"myPrologue"`);
|
||||
addTestPrologue(fs, sources[Project.lib][Source.ts][2], `"myPrologueFile"`);
|
||||
addTestPrologue(fs, sources[Project.lib][Source.ts][3], `"myPrologue3"`);
|
||||
enableStrict(fs, sources[Project.app][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.app][Source.ts][0], `"myPrologue"`);
|
||||
addTestPrologue(fs, sources[Project.app][Source.ts][1], `"myPrologue2";`);
|
||||
enableStrict(fs, "/src/lib/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/lib/file0.ts", `"myPrologue"`);
|
||||
addTestPrologue(fs, "/src/lib/file2.ts", `"myPrologueFile"`);
|
||||
addTestPrologue(fs, "/src/lib/global.ts", `"myPrologue3"`);
|
||||
enableStrict(fs, "/src/app/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/app/file3.ts", `"myPrologue"`);
|
||||
addTestPrologue(fs, "/src/app/file4.ts", `"myPrologue2";`);
|
||||
},
|
||||
modifyAgainFs: fs => addTestPrologue(fs, relName(sources[Project.lib][Source.ts][1]), `"myPrologue5"`)
|
||||
modifyAgainFs: fs => addTestPrologue(fs, "/src/lib/file1.ts", `"myPrologue5"`)
|
||||
});
|
||||
});
|
||||
|
||||
@@ -127,10 +103,10 @@ namespace ts {
|
||||
describe("stripInternal", () => {
|
||||
function stripInternalScenario(fs: vfs.FileSystem) {
|
||||
const internal = "/*@internal*/";
|
||||
replaceText(fs, sources[Project.app][Source.config], `"composite": true,`, `"composite": true,
|
||||
replaceText(fs, "/src/app/tsconfig.json", `"composite": true,`, `"composite": true,
|
||||
"stripInternal": true,`);
|
||||
replaceText(fs, sources[Project.lib][Source.ts][0], "const", `${internal} const`);
|
||||
appendText(fs, sources[Project.lib][Source.ts][1], `
|
||||
replaceText(fs, "/src/lib/file0.ts", "const", `${internal} const`);
|
||||
appendText(fs, "/src/lib/file1.ts", `
|
||||
export class normalC {
|
||||
${internal} constructor() { }
|
||||
${internal} prop: string;
|
||||
@@ -162,16 +138,16 @@ ${internal} export enum internalEnum { a, b, c }`);
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal",
|
||||
modifyFs: stripInternalScenario,
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.lib][Source.ts][1], `export const`, `/*@internal*/ export const`),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/lib/file1.ts", `export const`, `/*@internal*/ export const`),
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the module resolution finds original source file", () => {
|
||||
function modifyFs(fs: vfs.FileSystem) {
|
||||
// Make lib to output to parent dir
|
||||
replaceText(fs, sources[Project.lib][Source.config], `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`);
|
||||
replaceText(fs, "/src/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`);
|
||||
// Change reference to file1 module to resolve to lib/file1
|
||||
replaceText(fs, sources[Project.app][Source.ts][0], "file1", "lib/file1");
|
||||
replaceText(fs, "/src/app/file3.ts", "file1", "lib/file1");
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts {
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in config file", () => {
|
||||
verifyTscIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "configFileErrors",
|
||||
subScenario: "reports syntax errors in config file",
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -27,21 +27,18 @@ namespace ts {
|
||||
}`
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => replaceText(fs, "/src/tsconfig.json", ",", `,
|
||||
"declaration": true,`),
|
||||
subScenario: "reports syntax errors after change to config file"
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"),
|
||||
subScenario: "reports syntax errors after change to ts file"
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => fs.writeFileSync(
|
||||
"/src/tsconfig.json",
|
||||
JSON.stringify({
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: when containerOnly project is referenced", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "containerOnlyReferenced",
|
||||
subScenario: "verify that subsequent builds after initial build doesnt build anything",
|
||||
fs: () => loadProjectFromDisk("tests/projects/containerOnlyReferenced"),
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts {
|
||||
});
|
||||
|
||||
function verifyEmitDeclarationOnly(disableMap?: true) {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
|
||||
fs: () => projFs,
|
||||
scenario: "emitDeclarationOnly",
|
||||
@@ -17,8 +17,8 @@ namespace ts {
|
||||
modifyFs: disableMap ?
|
||||
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
|
||||
undefined,
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
}],
|
||||
});
|
||||
@@ -26,7 +26,7 @@ namespace ts {
|
||||
verifyEmitDeclarationOnly();
|
||||
verifyEmitDeclarationOnly(/*disableMap*/ true);
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: `only dts output in non circular imports project with emitDeclarationOnly`,
|
||||
fs: () => projFs,
|
||||
scenario: "emitDeclarationOnly",
|
||||
@@ -35,17 +35,16 @@ namespace ts {
|
||||
fs.rimrafSync("/src/src/index.ts");
|
||||
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
|
||||
},
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { }
|
||||
export interface A {`),
|
||||
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -331,24 +331,25 @@ interface Symbol {
|
||||
(originalWriteFile || sys.writeFile).call(sys, `${buildInfoPath}.baseline.txt`, text);
|
||||
}
|
||||
|
||||
interface VerifyIncrementalCorrectness {
|
||||
scenario: TscCompile["scenario"];
|
||||
commandLineArgs: TscCompile["commandLineArgs"];
|
||||
modifyFs: TscCompile["modifyFs"];
|
||||
incrementalModifyFs: TscIncremental["modifyFs"];
|
||||
interface VerifyTscEditCorrectnessInput {
|
||||
scenario: TestTscCompile["scenario"];
|
||||
commandLineArgs: TestTscCompile["commandLineArgs"];
|
||||
modifyFs: TestTscCompile["modifyFs"];
|
||||
editFs: TestTscEdit["modifyFs"];
|
||||
tick: () => void;
|
||||
baseFs: vfs.FileSystem;
|
||||
newSys: TscCompileSystem;
|
||||
cleanBuildDiscrepancies: TscIncremental["cleanBuildDiscrepancies"];
|
||||
cleanBuildDiscrepancies: TestTscEdit["cleanBuildDiscrepancies"];
|
||||
}
|
||||
function verifyIncrementalCorrectness(input: () => VerifyIncrementalCorrectness, index: number, subScenario: TscCompile["subScenario"]) {
|
||||
it(`Verify emit output file text is same when built clean for incremental scenario at:: ${index} ${subScenario}`, () => {
|
||||
/** Verify that emit is same as clean build vs building after edit */
|
||||
function verifyTscEditCorrectness(input: () => VerifyTscEditCorrectnessInput, index: number, subScenario: TestTscCompile["subScenario"]) {
|
||||
it(`Verify emit output file text is same when built clean for incremental edit scenario at:: ${index} ${subScenario}`, () => {
|
||||
const {
|
||||
scenario, commandLineArgs, cleanBuildDiscrepancies,
|
||||
modifyFs, incrementalModifyFs,
|
||||
modifyFs, editFs,
|
||||
tick, baseFs, newSys
|
||||
} = input();
|
||||
const sys = tscCompile({
|
||||
const sys = testTscCompile({
|
||||
scenario,
|
||||
subScenario,
|
||||
fs: () => baseFs.makeReadonly(),
|
||||
@@ -356,7 +357,7 @@ interface Symbol {
|
||||
modifyFs: fs => {
|
||||
tick();
|
||||
if (modifyFs) modifyFs(fs);
|
||||
incrementalModifyFs(fs);
|
||||
editFs(fs);
|
||||
},
|
||||
disableUseFileVersionAsSignature: true,
|
||||
});
|
||||
@@ -498,138 +499,47 @@ interface Symbol {
|
||||
CleanFilePresent,
|
||||
}
|
||||
|
||||
export interface TscIncremental {
|
||||
buildKind: BuildKind;
|
||||
export interface TestTscEdit {
|
||||
modifyFs: (fs: vfs.FileSystem) => void;
|
||||
subScenario?: string;
|
||||
subScenario: string;
|
||||
commandLineArgs?: readonly string[];
|
||||
cleanBuildDiscrepancies?: () => ESMap<string, CleanBuildDescrepancy>;
|
||||
}
|
||||
|
||||
export interface VerifyTsBuildInput extends VerifyTsBuildInputWorker {
|
||||
export interface VerifyTscWithEditsInput extends VerifyTscWithEditsWorkerInput {
|
||||
baselineIncremental?: boolean;
|
||||
}
|
||||
export interface VerifyTscWithEditsWorkerInput extends TestTscCompile {
|
||||
edits: TestTscEdit[];
|
||||
}
|
||||
|
||||
export function verifyTscIncrementalEdits(input: VerifyTsBuildInput) {
|
||||
verifyTscIncrementalEditsWorker(input);
|
||||
/**
|
||||
* Verify non watch tsc invokcation after each edit
|
||||
*/
|
||||
export function verifyTscWithEdits(input: VerifyTscWithEditsInput) {
|
||||
verifyTscWithEditsWorker(input);
|
||||
if (input.baselineIncremental) {
|
||||
verifyTscIncrementalEditsWorker({
|
||||
verifyTscWithEditsWorker({
|
||||
...input,
|
||||
subScenario: `${input.subScenario} with incremental`,
|
||||
commandLineArgs: [...input.commandLineArgs, "--incremental"],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface VerifyTsBuildInputWorker extends TscCompile {
|
||||
incrementalScenarios: TscIncremental[];
|
||||
}
|
||||
function verifyTscIncrementalEditsWorker({
|
||||
function verifyTscWithEditsWorker({
|
||||
subScenario, fs, scenario, commandLineArgs,
|
||||
baselineSourceMap, modifyFs, baselineReadFileCalls, baselinePrograms,
|
||||
incrementalScenarios
|
||||
}: VerifyTsBuildInputWorker) {
|
||||
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => {
|
||||
let tick: () => void;
|
||||
let sys: TscCompileSystem;
|
||||
let baseFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
({ fs: baseFs, tick } = getFsWithTime(fs()));
|
||||
sys = tscCompile({
|
||||
scenario,
|
||||
subScenario,
|
||||
fs: () => baseFs.makeReadonly(),
|
||||
commandLineArgs,
|
||||
modifyFs: fs => {
|
||||
if (modifyFs) modifyFs(fs);
|
||||
tick();
|
||||
},
|
||||
baselineSourceMap,
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms
|
||||
});
|
||||
Debug.assert(!!incrementalScenarios.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`);
|
||||
});
|
||||
after(() => {
|
||||
baseFs = undefined!;
|
||||
sys = undefined!;
|
||||
tick = undefined!;
|
||||
});
|
||||
describe("initialBuild", () => {
|
||||
verifyTscBaseline(() => sys);
|
||||
});
|
||||
|
||||
incrementalScenarios.forEach(({
|
||||
buildKind,
|
||||
modifyFs: incrementalModifyFs,
|
||||
subScenario: incrementalSubScenario,
|
||||
commandLineArgs: incrementalCommandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
}, index) => {
|
||||
describe(incrementalSubScenario || buildKind, () => {
|
||||
let newSys: TscCompileSystem;
|
||||
before(() => {
|
||||
Debug.assert(buildKind !== BuildKind.Initial, "Incremental edit cannot be initial compilation");
|
||||
tick();
|
||||
newSys = tscCompile({
|
||||
scenario,
|
||||
subScenario: incrementalSubScenario || subScenario,
|
||||
buildKind,
|
||||
fs: () => sys.vfs,
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
modifyFs: fs => {
|
||||
tick();
|
||||
incrementalModifyFs(fs);
|
||||
tick();
|
||||
},
|
||||
baselineSourceMap,
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
newSys = undefined!;
|
||||
});
|
||||
verifyTscBaseline(() => newSys);
|
||||
verifyIncrementalCorrectness(() => ({
|
||||
scenario,
|
||||
baseFs,
|
||||
newSys,
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
incrementalModifyFs,
|
||||
modifyFs,
|
||||
tick
|
||||
}), index, incrementalSubScenario || subScenario);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function verifyTscSerializedIncrementalEdits(input: VerifyTsBuildInput) {
|
||||
verifyTscSerializedIncrementalEditsWorker(input);
|
||||
if (input.baselineIncremental) {
|
||||
verifyTscSerializedIncrementalEditsWorker({
|
||||
...input,
|
||||
subScenario: `${input.subScenario} with incremental`,
|
||||
commandLineArgs: [...input.commandLineArgs, "--incremental"],
|
||||
});
|
||||
}
|
||||
}
|
||||
function verifyTscSerializedIncrementalEditsWorker({
|
||||
subScenario, fs, scenario, commandLineArgs,
|
||||
baselineSourceMap, modifyFs, baselineReadFileCalls, baselinePrograms,
|
||||
incrementalScenarios
|
||||
}: VerifyTsBuildInputWorker) {
|
||||
edits
|
||||
}: VerifyTscWithEditsWorkerInput) {
|
||||
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario} serializedEdits`, () => {
|
||||
Debug.assert(!!incrementalScenarios.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`);
|
||||
let tick: () => void;
|
||||
let sys: TscCompileSystem;
|
||||
let baseFs: vfs.FileSystem;
|
||||
let incrementalSys: TscCompileSystem[];
|
||||
let editsSys: TscCompileSystem[];
|
||||
before(() => {
|
||||
Debug.assert(!!edits.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`);
|
||||
({ fs: baseFs, tick } = getFsWithTime(fs()));
|
||||
sys = tscCompile({
|
||||
sys = testTscCompile({
|
||||
scenario,
|
||||
subScenario,
|
||||
fs: () => baseFs.makeReadonly(),
|
||||
@@ -642,18 +552,17 @@ interface Symbol {
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms
|
||||
});
|
||||
incrementalScenarios.forEach((
|
||||
{ buildKind, modifyFs, subScenario: incrementalSubScenario, commandLineArgs: incrementalCommandLineArgs },
|
||||
edits.forEach((
|
||||
{ modifyFs, subScenario: editScenario, commandLineArgs: editCommandLineArgs },
|
||||
index
|
||||
) => {
|
||||
Debug.assert(buildKind !== BuildKind.Initial, "Incremental edit cannot be initial compilation");
|
||||
tick();
|
||||
(incrementalSys || (incrementalSys = [])).push(tscCompile({
|
||||
(editsSys || (editsSys = [])).push(testTscCompile({
|
||||
scenario,
|
||||
subScenario: incrementalSubScenario || subScenario,
|
||||
buildKind,
|
||||
fs: () => index === 0 ? sys.vfs : incrementalSys[index - 1].vfs,
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
subScenario: editScenario || subScenario,
|
||||
diffWithInitial: true,
|
||||
fs: () => index === 0 ? sys.vfs : editsSys[index - 1].vfs,
|
||||
commandLineArgs: editCommandLineArgs || commandLineArgs,
|
||||
modifyFs: fs => {
|
||||
tick();
|
||||
modifyFs(fs);
|
||||
@@ -669,39 +578,38 @@ interface Symbol {
|
||||
baseFs = undefined!;
|
||||
sys = undefined!;
|
||||
tick = undefined!;
|
||||
incrementalSys = undefined!;
|
||||
editsSys = undefined!;
|
||||
});
|
||||
describe("serializedBuild", () => {
|
||||
|
||||
describe("tsc invocation after edit", () => {
|
||||
verifyTscBaseline(() => ({
|
||||
baseLine: () => {
|
||||
const { file, text } = sys.baseLine();
|
||||
const texts: string[] = [text];
|
||||
incrementalSys.forEach((sys, index) => {
|
||||
const incrementalScenario = incrementalScenarios[index];
|
||||
editsSys.forEach((sys, index) => {
|
||||
const incrementalScenario = edits[index];
|
||||
texts.push("");
|
||||
texts.push(`Change:: ${incrementalScenario.subScenario || incrementalScenario.buildKind}`);
|
||||
texts.push(`Change:: ${incrementalScenario.subScenario}`);
|
||||
texts.push(sys.baseLine().text);
|
||||
});
|
||||
return { file, text: texts.join("\r\n") };
|
||||
}
|
||||
}));
|
||||
});
|
||||
describe("incremental correctness", () => {
|
||||
incrementalScenarios.forEach(({ commandLineArgs: incrementalCommandLineArgs, subScenario, buildKind, cleanBuildDiscrepancies }, index) => verifyIncrementalCorrectness(() => ({
|
||||
describe("tsc invocation after edit and clean build correctness", () => {
|
||||
edits.forEach(({ commandLineArgs: editCommandLineArgs, subScenario, cleanBuildDiscrepancies }, index) => verifyTscEditCorrectness(() => ({
|
||||
scenario,
|
||||
baseFs,
|
||||
newSys: incrementalSys[index],
|
||||
commandLineArgs: incrementalCommandLineArgs || commandLineArgs,
|
||||
newSys: editsSys[index],
|
||||
commandLineArgs: editCommandLineArgs || commandLineArgs,
|
||||
cleanBuildDiscrepancies,
|
||||
incrementalModifyFs: fs => {
|
||||
editFs: fs => {
|
||||
for (let i = 0; i <= index; i++) {
|
||||
incrementalScenarios[i].modifyFs(fs);
|
||||
edits[i].modifyFs(fs);
|
||||
}
|
||||
},
|
||||
modifyFs,
|
||||
tick
|
||||
}), index, subScenario || buildKind));
|
||||
}), index, subScenario));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,42 +8,42 @@ namespace ts {
|
||||
projFs = undefined!;
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
subScenario: "inferred type from transitive module",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParam,
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParamBack,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "inferred type from transitive module with isolatedModules",
|
||||
fs: () => projFs,
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
modifyFs: changeToIsolatedModules,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParam
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParamBack,
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
subScenario: "reports errors in files affected by change in signature with isolatedModules",
|
||||
fs: () => projFs,
|
||||
@@ -54,22 +54,21 @@ namespace ts {
|
||||
import { default as bar } from './bar';
|
||||
bar("hello");`);
|
||||
},
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParam
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParamBack,
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: changeBarParam
|
||||
},
|
||||
{
|
||||
subScenario: "Fix Error",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => replaceText(fs, "/src/lazyIndex.ts", `bar("hello")`, "bar()")
|
||||
},
|
||||
]
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace ts {
|
||||
commandLineArgs: ["-b", "/src"]
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `modifies outfile js projects and concatenates them correctly`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -176,8 +176,8 @@ namespace ts {
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src"],
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => replaceText(fs, "/src/sub-project/index.js", "null", "undefined")
|
||||
}]
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "interface is merged and contains late bound member",
|
||||
fs: () => loadProjectFromDisk("tests/projects/lateBoundSymbol"),
|
||||
scenario: "lateBoundSymbol",
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => replaceText(fs, "/src/src/main.ts", "const x = 10;", ""),
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => appendText(fs, "/src/src/main.ts", "const x = 10;"),
|
||||
},
|
||||
]
|
||||
|
||||
@@ -8,18 +8,17 @@ namespace ts {
|
||||
projFs = undefined!;
|
||||
});
|
||||
|
||||
function verifyNoEmitOnError(subScenario: string, fixModifyFs: TscIncremental["modifyFs"], modifyFs?: TscIncremental["modifyFs"]) {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
function verifyNoEmitOnError(subScenario: string, fixModifyFs: TestTscEdit["modifyFs"], modifyFs?: TestTscEdit["modifyFs"]) {
|
||||
verifyTscWithEdits({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario,
|
||||
fs: () => projFs,
|
||||
modifyFs,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "Fix error",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fixModifyFs,
|
||||
},
|
||||
noChangeRun,
|
||||
|
||||
@@ -1,78 +1,13 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: outFile::", () => {
|
||||
let outFileFs: vfs.FileSystem;
|
||||
const enum Ext { js, jsmap, dts, dtsmap, buildinfo }
|
||||
const enum Project { first, second, third }
|
||||
type OutputFile = [string, string, string, string, string];
|
||||
function relName(path: string) {
|
||||
return path.slice(1);
|
||||
}
|
||||
const outputFiles: [OutputFile, OutputFile, OutputFile] = [
|
||||
[
|
||||
"/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/first/bin/first-output.tsbuildinfo"
|
||||
],
|
||||
[
|
||||
"/src/2/second-output.js",
|
||||
"/src/2/second-output.js.map",
|
||||
"/src/2/second-output.d.ts",
|
||||
"/src/2/second-output.d.ts.map",
|
||||
"/src/2/second-output.tsbuildinfo"
|
||||
],
|
||||
[
|
||||
"/src/third/thirdjs/output/third-output.js",
|
||||
"/src/third/thirdjs/output/third-output.js.map",
|
||||
"/src/third/thirdjs/output/third-output.d.ts",
|
||||
"/src/third/thirdjs/output/third-output.d.ts.map",
|
||||
"/src/third/thirdjs/output/third-output.tsbuildinfo"
|
||||
]
|
||||
];
|
||||
const relOutputFiles = outputFiles.map(v => v.map(relName)) as [OutputFile, OutputFile, OutputFile];
|
||||
type Sources = [string, readonly string[]];
|
||||
const enum Source { config, ts }
|
||||
const enum Part { one, two, three }
|
||||
const sources: [Sources, Sources, Sources] = [
|
||||
[
|
||||
"/src/first/tsconfig.json",
|
||||
[
|
||||
"/src/first/first_PART1.ts",
|
||||
"/src/first/first_part2.ts",
|
||||
"/src/first/first_part3.ts"
|
||||
]
|
||||
],
|
||||
[
|
||||
"/src/second/tsconfig.json",
|
||||
[
|
||||
"/src/second/second_part1.ts",
|
||||
"/src/second/second_part2.ts"
|
||||
]
|
||||
],
|
||||
[
|
||||
"/src/third/tsconfig.json",
|
||||
[
|
||||
"/src/third/third_part1.ts"
|
||||
]
|
||||
]
|
||||
];
|
||||
const relSources = sources.map(([config, sources]) => [relName(config), sources.map(relName)]) as any as [Sources, Sources, Sources];
|
||||
let initialExpectedDiagnostics: readonly fakes.ExpectedDiagnostic[] = [
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[Project.first][Source.config], relSources[Project.second][Source.config], relSources[Project.third][Source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, relSources[Project.first][Source.config], relOutputFiles[Project.first][Ext.js]],
|
||||
[Diagnostics.Building_project_0, sources[Project.first][Source.config]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, relSources[Project.second][Source.config], relOutputFiles[Project.second][Ext.js]],
|
||||
[Diagnostics.Building_project_0, sources[Project.second][Source.config]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, relSources[Project.third][Source.config], relOutputFiles[Project.third][Ext.js]],
|
||||
[Diagnostics.Building_project_0, sources[Project.third][Source.config]]
|
||||
];
|
||||
let outFileWithBuildFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
outFileFs = loadProjectFromDisk("tests/projects/outfile-concat");
|
||||
});
|
||||
after(() => {
|
||||
outFileFs = undefined!;
|
||||
initialExpectedDiagnostics = undefined!;
|
||||
outFileWithBuildFs = undefined!;
|
||||
});
|
||||
|
||||
function createSolutionBuilder(host: fakes.SolutionBuilderHost, baseOptions?: BuildOptions) {
|
||||
@@ -98,26 +33,26 @@ namespace ts {
|
||||
baselineOnly,
|
||||
additionalCommandLineArgs,
|
||||
}: VerifyOutFileScenarioInput) {
|
||||
const incrementalScenarios: TscIncremental[] = [];
|
||||
const edits: TestTscEdit[] = [];
|
||||
if (!ignoreDtsChanged) {
|
||||
incrementalScenarios.push({
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => replaceText(fs, relSources[Project.first][Source.ts][Part.one], "Hello", "Hola"),
|
||||
edits.push({
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/first/first_PART1.ts", "Hello", "Hola"),
|
||||
});
|
||||
}
|
||||
if (!ignoreDtsUnchanged) {
|
||||
incrementalScenarios.push({
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => appendText(fs, relSources[Project.first][Source.ts][Part.one], "console.log(s);"),
|
||||
edits.push({
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
});
|
||||
}
|
||||
if (modifyAgainFs) {
|
||||
incrementalScenarios.push({
|
||||
buildKind: BuildKind.IncrementalHeadersChange,
|
||||
edits.push({
|
||||
subScenario: "incremental-headers-change-without-dts-changes",
|
||||
modifyFs: modifyAgainFs
|
||||
});
|
||||
}
|
||||
const input: VerifyTsBuildInput = {
|
||||
const input: VerifyTscWithEditsInput = {
|
||||
subScenario,
|
||||
fs: () => outFileFs,
|
||||
scenario: "outfile-concat",
|
||||
@@ -125,10 +60,10 @@ namespace ts {
|
||||
baselineSourceMap: true,
|
||||
modifyFs,
|
||||
baselineReadFileCalls: !baselineOnly,
|
||||
incrementalScenarios,
|
||||
edits,
|
||||
};
|
||||
return incrementalScenarios.length ?
|
||||
verifyTscIncrementalEdits(input) :
|
||||
return edits.length ?
|
||||
verifyTscWithEdits(input) :
|
||||
verifyTsc(input);
|
||||
}
|
||||
|
||||
@@ -146,7 +81,7 @@ namespace ts {
|
||||
// Verify baseline with build info + dts unChanged
|
||||
verifyOutFileScenario({
|
||||
subScenario: "when final project is not composite but uses project references",
|
||||
modifyFs: fs => replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, ""),
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -154,7 +89,7 @@ namespace ts {
|
||||
// Verify baseline with build info
|
||||
verifyOutFileScenario({
|
||||
subScenario: "when final project is not composite but incremental",
|
||||
modifyFs: fs => replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, `"incremental": true,`),
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"incremental": true,`),
|
||||
ignoreDtsChanged: true,
|
||||
ignoreDtsUnchanged: true,
|
||||
baselineOnly: true
|
||||
@@ -163,7 +98,7 @@ namespace ts {
|
||||
// Verify baseline with build info
|
||||
verifyOutFileScenario({
|
||||
subScenario: "when final project specifies tsBuildInfoFile",
|
||||
modifyFs: fs => replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, `"composite": true,
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true,
|
||||
"tsBuildInfoFile": "./thirdjs/output/third.tsbuildinfo",`),
|
||||
ignoreDtsChanged: true,
|
||||
ignoreDtsUnchanged: true,
|
||||
@@ -171,20 +106,21 @@ namespace ts {
|
||||
});
|
||||
|
||||
function getOutFileFsAfterBuild() {
|
||||
if (outFileWithBuildFs) return outFileWithBuildFs;
|
||||
const fs = outFileFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host);
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
return outFileWithBuildFs = fs;
|
||||
}
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "outFile",
|
||||
subScenario: "clean projects",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--clean"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
@@ -192,7 +128,7 @@ namespace ts {
|
||||
subScenario: "verify buildInfo absence results in new build",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => fs.unlinkSync(outputFiles[Project.first][Ext.buildinfo]),
|
||||
modifyFs: fs => fs.unlinkSync("/src/first/bin/first-output.tsbuildinfo"),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
@@ -200,100 +136,67 @@ namespace ts {
|
||||
subScenario: "tsbuildinfo is not generated when incremental is set to false",
|
||||
fs: () => outFileFs,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, ""),
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
});
|
||||
|
||||
it("rebuilds completely when version in tsbuildinfo doesnt match ts version", () => {
|
||||
const { fs, tick } = getFsWithTime(outFileFs);
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
let builder = createSolutionBuilder(host);
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
builder = createSolutionBuilder(host);
|
||||
changeCompilerVersion(host);
|
||||
tick();
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[Project.first][Source.config], relSources[Project.second][Source.config], relSources[Project.third][Source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relSources[Project.first][Source.config], fakes.version, version],
|
||||
[Diagnostics.Building_project_0, sources[Project.first][Source.config]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relSources[Project.second][Source.config], fakes.version, version],
|
||||
[Diagnostics.Building_project_0, sources[Project.second][Source.config]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, relSources[Project.third][Source.config], fakes.version, version],
|
||||
[Diagnostics.Building_project_0, sources[Project.third][Source.config]],
|
||||
);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "outFile",
|
||||
subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
fakes.patchHostForBuildInfoWrite(sys, "FakeTSCurrentVersion");
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
}
|
||||
});
|
||||
|
||||
it("rebuilds completely when command line incremental flag changes between non dts changes", () => {
|
||||
const { fs, tick } = getFsWithTime(outFileFs);
|
||||
verifyTscWithEdits({
|
||||
scenario: "outFile",
|
||||
subScenario: "rebuilds completely when command line incremental flag changes between non dts changes",
|
||||
fs: () => outFileFs,
|
||||
// Make non composite third project
|
||||
replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, "");
|
||||
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
// Build with command line incremental
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
let builder = createSolutionBuilder(host, { incremental: true });
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(...initialExpectedDiagnostics);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
|
||||
// Make non incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[Project.first][Source.ts][Part.one], "console.log(s);");
|
||||
builder = createSolutionBuilder(host, { verbose: true });
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(getExpectedDiagnosticForProjectsInBuild(relSources[Project.first][Source.config], relSources[Project.second][Source.config], relSources[Project.third][Source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[Project.first][Source.config], relOutputFiles[Project.first][Ext.js], relSources[Project.first][Source.ts][Part.one]],
|
||||
[Diagnostics.Building_project_0, sources[Project.first][Source.config]],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relSources[Project.second][Source.config], relSources[Project.second][Source.ts][Part.one], relOutputFiles[Project.second][Ext.js]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_of_its_dependency_1_has_changed, relSources[Project.third][Source.config], "src/first"],
|
||||
[Diagnostics.Building_project_0, sources[Project.third][Source.config]]
|
||||
);
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
|
||||
// Make incremental build with change in file that doesnt affect dts
|
||||
appendText(fs, relSources[Project.first][Source.ts][Part.one], "console.log(s);");
|
||||
builder = createSolutionBuilder(host, { verbose: true, incremental: true });
|
||||
builder.build();
|
||||
// Builds completely because tsbuildinfo is old.
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(relSources[Project.first][Source.config], relSources[Project.second][Source.config], relSources[Project.third][Source.config]),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[Project.first][Source.config], relOutputFiles[Project.first][Ext.js], relSources[Project.first][Source.ts][Part.one]],
|
||||
[Diagnostics.Building_project_0, sources[Project.first][Source.config]],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relSources[Project.second][Source.config], relSources[Project.second][Source.ts][Part.one], relOutputFiles[Project.second][Ext.js]],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_oldest_output_1_is_older_than_newest_input_2, relSources[Project.third][Source.config], relOutputFiles[Project.third][Ext.buildinfo], "src/first"],
|
||||
[Diagnostics.Building_project_0, sources[Project.third][Source.config]]
|
||||
);
|
||||
host.clearDiagnostics();
|
||||
commandLineArgs: ["--b", "/src/third", "--i", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
subScenario: "Make non incremental build with change in file that doesnt affect dts",
|
||||
modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
},
|
||||
{
|
||||
subScenario: "Make incremental build with change in file that doesnt affect dts",
|
||||
modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose", "--incremental"],
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
it("builds till project specified", () => {
|
||||
const fs = outFileFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, { verbose: false });
|
||||
const result = builder.build(sources[Project.second][Source.config]);
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
// First and Third is not built
|
||||
verifyOutputsAbsent(fs, [...outputFiles[Project.first], ...outputFiles[Project.third]]);
|
||||
// second is built
|
||||
verifyOutputsPresent(fs, outputFiles[Project.second]);
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "outFile",
|
||||
subScenario: "builds till project specified",
|
||||
fs: () => outFileFs,
|
||||
commandLineArgs: ["--build", "/src/second/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
|
||||
sys.exit(builder.build("/src/second/tsconfig.json"));
|
||||
}
|
||||
});
|
||||
|
||||
it("cleans till project specified", () => {
|
||||
const fs = outFileFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, { verbose: false });
|
||||
builder.build();
|
||||
const result = builder.clean(sources[Project.second][Source.config]);
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
// First and Third output for present
|
||||
verifyOutputsPresent(fs, [...outputFiles[Project.first], ...outputFiles[Project.third]]);
|
||||
// second is cleaned
|
||||
verifyOutputsAbsent(fs, outputFiles[Project.second]);
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "outFile",
|
||||
subScenario: "cleans till project specified",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--build", "--clean", "/src/second/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true });
|
||||
sys.exit(builder.clean("/src/second/tsconfig.json"));
|
||||
}
|
||||
});
|
||||
|
||||
describe("Prepend output with .tsbuildinfo", () => {
|
||||
@@ -303,17 +206,17 @@ namespace ts {
|
||||
verifyOutFileScenario({
|
||||
subScenario: "strict in all projects",
|
||||
modifyFs: fs => {
|
||||
enableStrict(fs, sources[Project.first][Source.config]);
|
||||
enableStrict(fs, sources[Project.second][Source.config]);
|
||||
enableStrict(fs, sources[Project.third][Source.config]);
|
||||
enableStrict(fs, "/src/first/tsconfig.json");
|
||||
enableStrict(fs, "/src/second/tsconfig.json");
|
||||
enableStrict(fs, "/src/third/tsconfig.json");
|
||||
},
|
||||
modifyAgainFs: fs => addTestPrologue(fs, relSources[Project.first][Source.ts][Part.one], `"myPrologue"`)
|
||||
modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`)
|
||||
});
|
||||
|
||||
// Verify ignore dtsChanged
|
||||
verifyOutFileScenario({
|
||||
subScenario: "strict in one dependency",
|
||||
modifyFs: fs => enableStrict(fs, sources[Project.second][Source.config]),
|
||||
modifyFs: fs => enableStrict(fs, "/src/second/tsconfig.json"),
|
||||
modifyAgainFs: fs => addTestPrologue(fs, "src/first/first_PART1.ts", `"myPrologue"`),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
@@ -323,28 +226,28 @@ namespace ts {
|
||||
verifyOutFileScenario({
|
||||
subScenario: "multiple prologues in all projects",
|
||||
modifyFs: fs => {
|
||||
enableStrict(fs, sources[Project.first][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.first][Source.ts][Part.one], `"myPrologue"`);
|
||||
enableStrict(fs, sources[Project.second][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.second][Source.ts][Part.one], `"myPrologue"`);
|
||||
addTestPrologue(fs, sources[Project.second][Source.ts][Part.two], `"myPrologue2";`);
|
||||
enableStrict(fs, sources[Project.third][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.third][Source.ts][Part.one], `"myPrologue";`);
|
||||
addTestPrologue(fs, sources[Project.third][Source.ts][Part.one], `"myPrologue3";`);
|
||||
enableStrict(fs, "/src/first/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`);
|
||||
enableStrict(fs, "/src/second/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`);
|
||||
addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`);
|
||||
enableStrict(fs, "/src/third/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue";`);
|
||||
addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue3";`);
|
||||
},
|
||||
modifyAgainFs: fs => addTestPrologue(fs, relSources[Project.first][Source.ts][Part.one], `"myPrologue5"`)
|
||||
modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`)
|
||||
});
|
||||
|
||||
// Verify ignore dtsChanged
|
||||
verifyOutFileScenario({
|
||||
subScenario: "multiple prologues in different projects",
|
||||
modifyFs: fs => {
|
||||
enableStrict(fs, sources[Project.first][Source.config]);
|
||||
addTestPrologue(fs, sources[Project.second][Source.ts][Part.one], `"myPrologue"`);
|
||||
addTestPrologue(fs, sources[Project.second][Source.ts][Part.two], `"myPrologue2";`);
|
||||
enableStrict(fs, sources[Project.third][Source.config]);
|
||||
enableStrict(fs, "/src/first/tsconfig.json");
|
||||
addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`);
|
||||
addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`);
|
||||
enableStrict(fs, "/src/third/tsconfig.json");
|
||||
},
|
||||
modifyAgainFs: fs => addTestPrologue(fs, sources[Project.first][Source.ts][Part.one], `"myPrologue5"`),
|
||||
modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -456,13 +359,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
function diableRemoveCommentsInAll(fs: vfs.FileSystem) {
|
||||
disableRemoveComments(fs, sources[Project.first][Source.config]);
|
||||
disableRemoveComments(fs, sources[Project.second][Source.config]);
|
||||
disableRemoveComments(fs, sources[Project.third][Source.config]);
|
||||
disableRemoveComments(fs, "/src/first/tsconfig.json");
|
||||
disableRemoveComments(fs, "/src/second/tsconfig.json");
|
||||
disableRemoveComments(fs, "/src/third/tsconfig.json");
|
||||
}
|
||||
|
||||
function stripInternalOfThird(fs: vfs.FileSystem) {
|
||||
replaceText(fs, sources[Project.third][Source.config], `"declaration": true,`, `"declaration": true,
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"declaration": true,`, `"declaration": true,
|
||||
"stripInternal": true,`);
|
||||
}
|
||||
|
||||
@@ -472,8 +375,8 @@ namespace ts {
|
||||
diableRemoveCommentsInAll(fs);
|
||||
}
|
||||
stripInternalOfThird(fs);
|
||||
replaceText(fs, sources[Project.first][Source.ts][Part.one], "interface", `${internal} interface`);
|
||||
appendText(fs, sources[Project.second][Source.ts][Part.one], `
|
||||
replaceText(fs, "/src/first/first_PART1.ts", "interface", `${internal} interface`);
|
||||
appendText(fs, "/src/second/second_part1.ts", `
|
||||
class normalC {
|
||||
${internal} constructor() { }
|
||||
${internal} prop: string;
|
||||
@@ -505,14 +408,14 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal",
|
||||
modifyFs: stripInternalScenario,
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/*@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
|
||||
});
|
||||
|
||||
// Verify ignore dtsChanged
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal with comments emit enabled",
|
||||
modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ true),
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/*@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -521,7 +424,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal jsdoc style comment",
|
||||
modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true),
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/**@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -536,9 +439,9 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
|
||||
describe("with three levels of project dependency", () => {
|
||||
function makeOneTwoThreeDependOrder(fs: vfs.FileSystem) {
|
||||
replaceText(fs, sources[Project.second][Source.config], "[", `[
|
||||
replaceText(fs, "/src/second/tsconfig.json", "[", `[
|
||||
{ "path": "../first", "prepend": true }`);
|
||||
replaceText(fs, sources[Project.third][Source.config], `{ "path": "../first", "prepend": true },`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true },`, "");
|
||||
}
|
||||
|
||||
function stripInternalWithDependentOrder(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) {
|
||||
@@ -550,14 +453,14 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal when one-two-three are prepended in order",
|
||||
modifyFs: stripInternalWithDependentOrder,
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/*@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
|
||||
});
|
||||
|
||||
// Verify ignore dtsChanged
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal with comments emit enabled when one-two-three are prepended in order",
|
||||
modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true),
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/*@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -566,7 +469,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
verifyOutFileScenario({
|
||||
subScenario: "stripInternal jsdoc style comment when one-two-three are prepended in order",
|
||||
modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true),
|
||||
modifyAgainFs: fs => replaceText(fs, sources[Project.first][Source.ts][Part.one], `/**@internal*/ interface`, "interface"),
|
||||
modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"),
|
||||
ignoreDtsChanged: true,
|
||||
baselineOnly: true
|
||||
});
|
||||
@@ -585,7 +488,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
subScenario: "stripInternal baseline when internal is inside another internal",
|
||||
modifyFs: fs => {
|
||||
stripInternalOfThird(fs);
|
||||
prependText(fs, sources[Project.first][Source.ts][Part.one], `namespace ts {
|
||||
prependText(fs, "/src/first/first_PART1.ts", `namespace ts {
|
||||
/* @internal */
|
||||
/**
|
||||
* Subset of properties from SourceFile that are used in multiple utility functions
|
||||
@@ -624,7 +527,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
subScenario: "stripInternal when few members of enum are internal",
|
||||
modifyFs: fs => {
|
||||
stripInternalOfThird(fs);
|
||||
prependText(fs, sources[Project.first][Source.ts][Part.one], `enum TokenFlags {
|
||||
prependText(fs, "/src/first/first_PART1.ts", `enum TokenFlags {
|
||||
None = 0,
|
||||
/* @internal */
|
||||
PrecedingLineBreak = 1 << 0,
|
||||
@@ -659,9 +562,9 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
ignoreDtsChanged: true,
|
||||
ignoreDtsUnchanged: true,
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(sources[Project.first][Source.ts][Part.one], "/* @internal */ const A = 1;");
|
||||
fs.writeFileSync(sources[Project.third][Source.ts][Part.one], "const B = 2;");
|
||||
fs.writeFileSync(sources[Project.first][Source.config], JSON.stringify({
|
||||
fs.writeFileSync("/src/first/first_PART1.ts", "/* @internal */ const A = 1;");
|
||||
fs.writeFileSync("/src/third/third_part1.ts", "const B = 2;");
|
||||
fs.writeFileSync("/src/first/tsconfig.json", JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
@@ -670,9 +573,9 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
sourceMap: true,
|
||||
outFile: "./bin/first-output.js"
|
||||
},
|
||||
files: [sources[Project.first][Source.ts][Part.one]]
|
||||
files: ["/src/first/first_PART1.ts"]
|
||||
}));
|
||||
fs.writeFileSync(sources[Project.third][Source.config], JSON.stringify({
|
||||
fs.writeFileSync("/src/third/tsconfig.json", JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
@@ -682,7 +585,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
outFile: "./thirdjs/output/third-output.js",
|
||||
},
|
||||
references: [{ path: "../first", prepend: true }],
|
||||
files: [sources[Project.third][Source.ts][Part.one]]
|
||||
files: ["/src/third/third_part1.ts"]
|
||||
}));
|
||||
}
|
||||
});
|
||||
@@ -690,7 +593,7 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
|
||||
describe("empty source files", () => {
|
||||
function makeThirdEmptySourceFile(fs: vfs.FileSystem) {
|
||||
fs.writeFileSync(sources[Project.third][Source.ts][Part.one], "", "utf8");
|
||||
fs.writeFileSync("/src/third/third_part1.ts", "", "utf8");
|
||||
}
|
||||
|
||||
// Verify ignore dtsChanged
|
||||
@@ -706,9 +609,9 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
subScenario: "declarationMap and sourceMap disabled",
|
||||
modifyFs: fs => {
|
||||
makeThirdEmptySourceFile(fs);
|
||||
replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, "");
|
||||
replaceText(fs, sources[Project.third][Source.config], `"sourceMap": true,`, "");
|
||||
replaceText(fs, sources[Project.third][Source.config], `"declarationMap": true,`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"sourceMap": true,`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"declarationMap": true,`, "");
|
||||
},
|
||||
ignoreDtsChanged: true,
|
||||
ignoreDtsUnchanged: true,
|
||||
@@ -724,18 +627,18 @@ ${internal} enum internalEnum { a, b, c }`);
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
// No prepend
|
||||
replaceText(fs, sources[Project.third][Source.config], `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`);
|
||||
replaceText(fs, sources[Project.third][Source.config], `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`);
|
||||
replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`);
|
||||
replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`);
|
||||
|
||||
// Non Modules
|
||||
replaceText(fs, sources[Project.first][Source.config], `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, sources[Project.second][Source.config], `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, sources[Project.third][Source.config], `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, "/src/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
|
||||
// Own file emit
|
||||
replaceText(fs, sources[Project.first][Source.config], `"outFile": "./bin/first-output.js",`, "");
|
||||
replaceText(fs, sources[Project.second][Source.config], `"outFile": "../2/second-output.js",`, "");
|
||||
replaceText(fs, sources[Project.third][Source.config], `"outFile": "./thirdjs/output/third-output.js",`, "");
|
||||
replaceText(fs, "/src/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, "");
|
||||
replaceText(fs, "/src/second/tsconfig.json", `"outFile": "../2/second-output.js",`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, "");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild - output file paths", () => {
|
||||
const noChangeProject: TscIncremental = {
|
||||
buildKind: BuildKind.NoChangeRun,
|
||||
const noChangeProject: TestTscEdit = {
|
||||
modifyFs: noop,
|
||||
subScenario: "Normal build without change, that does not block emit on error to show files that get emitted",
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json"],
|
||||
};
|
||||
const incrementalScenarios: TscIncremental[] = [
|
||||
const edits: TestTscEdit[] = [
|
||||
noChangeRun,
|
||||
noChangeProject,
|
||||
];
|
||||
|
||||
function verify(input: Pick<VerifyTsBuildInput, "subScenario" | "fs" | "incrementalScenarios">, expectedOuptutNames: readonly string[]) {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
function verify(input: Pick<VerifyTscWithEditsInput, "subScenario" | "fs" | "edits">, expectedOuptutNames: readonly string[]) {
|
||||
verifyTscWithEdits({
|
||||
scenario: "outputPaths",
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
...input
|
||||
@@ -42,7 +41,7 @@ namespace ts {
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
@@ -56,7 +55,7 @@ namespace ts {
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
...noChangeProject,
|
||||
@@ -79,7 +78,7 @@ namespace ts {
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
@@ -94,7 +93,7 @@ namespace ts {
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
@@ -110,7 +109,7 @@ namespace ts {
|
||||
}
|
||||
})
|
||||
}),
|
||||
incrementalScenarios,
|
||||
edits,
|
||||
}, ["/src/dist/index.js", "/src/dist/index.d.ts"]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export function f22() { } // trailing`,
|
||||
const baseFsPatch = inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true });
|
||||
const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true });
|
||||
return {
|
||||
file: `tsbuild/$publicAPI/${BuildKind.Initial}/${"build with custom transformers".split(" ").join("-")}.js`,
|
||||
file: `tsbuild/publicAPI/build-with-custom-transformers.js`,
|
||||
text: `Input::
|
||||
${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""}
|
||||
|
||||
|
||||
@@ -51,32 +51,32 @@ export default hello.hello`);
|
||||
commandLineArgs: ["--b", "/src/tsconfig_withIncludeAndFiles.json", "--v", "--explainFiles"],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "resolveJsonModule",
|
||||
subScenario: "sourcemap",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "src/tsconfig_withFiles.json", "--verbose", "--explainFiles"],
|
||||
modifyFs: fs => replaceText(fs, "src/tsconfig_withFiles.json", `"composite": true,`, `"composite": true, "sourceMap": true,`),
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "resolveJsonModule",
|
||||
subScenario: "without outDir",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "src/tsconfig_withFiles.json", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, "src/tsconfig_withFiles.json", `"outDir": "dist",`, ""),
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule option on project importJsonFromProjectReference", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "resolveJsonModule",
|
||||
subScenario: "importing json module from project reference",
|
||||
fs: () => loadProjectFromDisk("tests/projects/importJsonFromProjectReference"),
|
||||
commandLineArgs: ["--b", "src/tsconfig.json", "--verbose", "--explainFiles"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
const testsOutputs = ["/src/tests/index.js", "/src/tests/index.d.ts", "/src/tests/tsconfig.tsbuildinfo"];
|
||||
const logicOutputs = ["/src/logic/index.js", "/src/logic/index.js.map", "/src/logic/index.d.ts", "/src/logic/tsconfig.tsbuildinfo"];
|
||||
const coreOutputs = ["/src/core/index.js", "/src/core/index.d.ts", "/src/core/index.d.ts.map", "/src/core/tsconfig.tsbuildinfo"];
|
||||
const allExpectedOutputs = [...testsOutputs, ...logicOutputs, ...coreOutputs];
|
||||
|
||||
let projFsWithBuild: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromDisk("tests/projects/sample1");
|
||||
});
|
||||
|
||||
after(() => {
|
||||
projFs = undefined!; // Release the contents
|
||||
projFsWithBuild = undefined!;
|
||||
});
|
||||
|
||||
function getTsBuildProjectFile(project: string, file: string): tscWatch.File {
|
||||
return {
|
||||
path: TestFSWithWatch.getTsBuildProjectFilePath(project, file),
|
||||
content: projFs.readFileSync(`/src/${project}/${file}`, "utf8")!
|
||||
};
|
||||
}
|
||||
|
||||
function getSampleFsAfterBuild() {
|
||||
if (projFsWithBuild) return projFsWithBuild;
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
return projFsWithBuild = fs;
|
||||
}
|
||||
|
||||
describe("sanity check of clean build of 'sample1' project", () => {
|
||||
@@ -65,143 +70,123 @@ namespace ts {
|
||||
});
|
||||
|
||||
describe("clean builds", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "removes all files it built",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/tests", "--clean"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
it("cleans till project specified", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
builder.build();
|
||||
const result = builder.clean("/src/logic");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
verifyOutputsPresent(fs, testsOutputs);
|
||||
verifyOutputsAbsent(fs, [...logicOutputs, ...coreOutputs]);
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "cleans till project specified",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/logic", "--clean"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
|
||||
sys.exit(builder.clean("/src/logic"));
|
||||
}
|
||||
});
|
||||
|
||||
it("cleaning project in not build order doesnt throw error", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
builder.build();
|
||||
const result = builder.clean("/src/logic2");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
verifyOutputsPresent(fs, allExpectedOutputs);
|
||||
assert.equal(result, ExitStatus.InvalidProject_OutputsSkipped);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "cleaning project in not build order doesnt throw error",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/logic2", "--clean"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
|
||||
sys.exit(builder.clean("/src/logic2"));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("force builds", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "always builds under with force option",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/tests", "--force"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
});
|
||||
|
||||
describe("can detect when and what to rebuild", () => {
|
||||
function initializeWithBuild(opts?: BuildOptions) {
|
||||
const { fs, tick } = getFsWithTime(projFs);
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.build();
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { ...(opts || {}), verbose: true });
|
||||
return { fs, host, builder };
|
||||
}
|
||||
|
||||
verifyTscIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "can detect when and what to rebuild",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
// Update a file in the leaf node (tests), only it should rebuild the last one
|
||||
{
|
||||
subScenario: "Only builds the leaf node project",
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => fs.writeFileSync("/src/tests/index.ts", "const m = 10;"),
|
||||
},
|
||||
// Update a file in the parent (without affecting types), should get fast downstream builds
|
||||
{
|
||||
subScenario: "Detects type-only changes in upstream projects",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET"),
|
||||
},
|
||||
{
|
||||
subScenario: "indicates that it would skip builds during a dry build",
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/tests", "--dry"],
|
||||
},
|
||||
{
|
||||
subScenario: "rebuilds from start if force option is set",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: noop,
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose", "--force"],
|
||||
},
|
||||
{
|
||||
subScenario: "rebuilds when tsconfig changes",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es3"`),
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
it("rebuilds completely when version in tsbuildinfo doesnt match ts version", () => {
|
||||
const { host, builder } = initializeWithBuild();
|
||||
changeCompilerVersion(host);
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, "src/core/tsconfig.json", fakes.version, version],
|
||||
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, "src/logic/tsconfig.json", fakes.version, version],
|
||||
[Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_for_it_was_generated_with_version_1_that_differs_with_current_version_2, "src/tests/tsconfig.json", fakes.version, version],
|
||||
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"],
|
||||
);
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "indicates that it would skip builds during a dry build",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/tests", "--dry"],
|
||||
});
|
||||
|
||||
it("does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version", () => {
|
||||
const { fs, tick } = getFsWithTime(projFs);
|
||||
const host = fakes.SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, createAbstractBuilder);
|
||||
let builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/logic/tsconfig.json", "src/logic/index.js"],
|
||||
[Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/tests/tsconfig.json", "src/tests/index.js"],
|
||||
[Diagnostics.Building_project_0, "/src/tests/tsconfig.json"]
|
||||
);
|
||||
verifyOutputsPresent(fs, allExpectedOutputs);
|
||||
|
||||
host.clearDiagnostics();
|
||||
tick();
|
||||
builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
changeCompilerVersion(host);
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json", "src/tests/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/core/tsconfig.json", "src/core/anotherModule.ts", "src/core/anotherModule.js"],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/logic/tsconfig.json", "src/logic/index.ts", "src/logic/index.js"],
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, "src/tests/tsconfig.json", "src/tests/index.ts", "src/tests/index.js"]
|
||||
);
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds from start if force option is set",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose", "--force"],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
|
||||
fs: getSampleFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
fakes.patchHostForBuildInfoWrite(sys, "FakeTSCurrentVersion");
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
}
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version",
|
||||
fs: () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, createAbstractBuilder);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
},
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
fakes.patchHostForBuildInfoWrite(sys, "FakeTSCurrentVersion");
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
},
|
||||
});
|
||||
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds when extended config file changes",
|
||||
fs: () => projFs,
|
||||
@@ -210,86 +195,93 @@ namespace ts {
|
||||
fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: { target: "es3" } }));
|
||||
replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`);
|
||||
},
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: {} }))
|
||||
}]
|
||||
});
|
||||
|
||||
it("builds till project specified", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
const result = builder.build("/src/logic");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
verifyOutputsAbsent(fs, testsOutputs);
|
||||
verifyOutputsPresent(fs, [...logicOutputs, ...coreOutputs]);
|
||||
assert.equal(result, ExitStatus.Success);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "builds till project specified",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--build", "/src/logic/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/tests"], {});
|
||||
sys.exit(builder.build("/src/logic/tsconfig.json"));
|
||||
}
|
||||
});
|
||||
|
||||
it("building project in not build order doesnt throw error", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
const result = builder.build("/src/logic2");
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
verifyOutputsAbsent(fs, allExpectedOutputs);
|
||||
assert.equal(result, ExitStatus.InvalidProject_OutputsSkipped);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "building project in not build order doesnt throw error",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--build", "/src/logic2/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/tests"], {});
|
||||
sys.exit(builder.build("/src/logic2/tsconfig.json"));
|
||||
}
|
||||
});
|
||||
|
||||
it("building using getNextInvalidatedProject", () => {
|
||||
interface SolutionBuilderResult<T> {
|
||||
project: ResolvedConfigFileName;
|
||||
result: T;
|
||||
}
|
||||
const coreConfig = getTsBuildProjectFile("core", "tsconfig.json");
|
||||
const coreIndex = getTsBuildProjectFile("core", "index.ts");
|
||||
const coreDecl = getTsBuildProjectFile("core", "some_decl.d.ts");
|
||||
const coreAnotherModule = getTsBuildProjectFile("core", "anotherModule.ts");
|
||||
const logicConfig = getTsBuildProjectFile("logic", "tsconfig.json");
|
||||
const logicIndex = getTsBuildProjectFile("logic", "index.ts");
|
||||
const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json");
|
||||
const testsIndex = getTsBuildProjectFile("tests", "index.ts");
|
||||
const baseline: string[] = [];
|
||||
let oldSnap: ReturnType<TestFSWithWatch.TestServerHost["snap"]> | undefined;
|
||||
const system = TestFSWithWatch.changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
tscWatch.createWatchedSystem([
|
||||
coreConfig, coreIndex, coreDecl, coreAnotherModule,
|
||||
logicConfig, logicIndex,
|
||||
testsConfig, testsIndex,
|
||||
tscWatch.libFile
|
||||
])
|
||||
)
|
||||
);
|
||||
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], {});
|
||||
verifyBuildNextResult({
|
||||
project: "/src/core/tsconfig.json" as ResolvedConfigFileName,
|
||||
result: ExitStatus.Success
|
||||
}, coreOutputs, [...logicOutputs, ...testsOutputs]);
|
||||
const host = createSolutionBuilderHost(system);
|
||||
const builder = createSolutionBuilder(host, [testsConfig.path], {});
|
||||
baseline.push("Input::");
|
||||
baselineState();
|
||||
verifyBuildNextResult(); // core
|
||||
verifyBuildNextResult(); // logic
|
||||
verifyBuildNextResult();// tests
|
||||
verifyBuildNextResult(); // All Done
|
||||
Harness.Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n"));
|
||||
|
||||
verifyBuildNextResult({
|
||||
project: "/src/logic/tsconfig.json" as ResolvedConfigFileName,
|
||||
result: ExitStatus.Success
|
||||
}, [...coreOutputs, ...logicOutputs], testsOutputs);
|
||||
|
||||
verifyBuildNextResult({
|
||||
project: "/src/tests/tsconfig.json" as ResolvedConfigFileName,
|
||||
result: ExitStatus.Success
|
||||
}, allExpectedOutputs, emptyArray);
|
||||
|
||||
verifyBuildNextResult(/*expected*/ undefined, allExpectedOutputs, emptyArray);
|
||||
|
||||
function verifyBuildNextResult(
|
||||
expected: SolutionBuilderResult<ExitStatus> | undefined,
|
||||
presentOutputs: readonly string[],
|
||||
absentOutputs: readonly string[]
|
||||
) {
|
||||
function verifyBuildNextResult() {
|
||||
const project = builder.getNextInvalidatedProject();
|
||||
const result = project && project.done();
|
||||
assert.deepEqual(project && { project: project.project, result }, expected);
|
||||
verifyOutputsPresent(fs, presentOutputs);
|
||||
verifyOutputsAbsent(fs, absentOutputs);
|
||||
baseline.push(`Project Result:: ${JSON.stringify({ project: project?.project, result })}`);
|
||||
baselineState();
|
||||
}
|
||||
|
||||
function baselineState() {
|
||||
system.serializeOutput(baseline);
|
||||
system.diff(baseline, oldSnap);
|
||||
system.writtenFiles.clear();
|
||||
oldSnap = system.snap();
|
||||
}
|
||||
});
|
||||
|
||||
it("building using buildReferencedProject", () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true });
|
||||
builder.buildReferences("/src/tests");
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild("src/core/tsconfig.json", "src/logic/tsconfig.json"),
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/core/tsconfig.json", "src/core/anotherModule.js"],
|
||||
[Diagnostics.Building_project_0, "/src/core/tsconfig.json"],
|
||||
[Diagnostics.Project_0_is_out_of_date_because_output_file_1_does_not_exist, "src/logic/tsconfig.json", "src/logic/index.js"],
|
||||
[Diagnostics.Building_project_0, "/src/logic/tsconfig.json"],
|
||||
);
|
||||
verifyOutputsPresent(fs, [...coreOutputs, ...logicOutputs]);
|
||||
verifyOutputsAbsent(fs, testsOutputs);
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
scenario: "sample1",
|
||||
subScenario: "building using buildReferencedProject",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--build", "/src/logic2/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true });
|
||||
sys.exit(builder.buildReferences("/src/tests"));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -305,109 +297,115 @@ namespace ts {
|
||||
|
||||
describe("project invalidation", () => {
|
||||
it("invalidates projects correctly", () => {
|
||||
const { fs, time, tick } = getFsWithTime(projFs);
|
||||
const host = fakes.SolutionBuilderHost.create(fs);
|
||||
const builder = createSolutionBuilder(host, ["/src/tests"], { dry: false, force: false, verbose: false });
|
||||
const coreConfig = getTsBuildProjectFile("core", "tsconfig.json");
|
||||
const coreIndex = getTsBuildProjectFile("core", "index.ts");
|
||||
const coreDecl = getTsBuildProjectFile("core", "some_decl.d.ts");
|
||||
const coreAnotherModule = getTsBuildProjectFile("core", "anotherModule.ts");
|
||||
const logicConfig = getTsBuildProjectFile("logic", "tsconfig.json");
|
||||
const logicIndex = getTsBuildProjectFile("logic", "index.ts");
|
||||
const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json");
|
||||
const testsIndex = getTsBuildProjectFile("tests", "index.ts");
|
||||
const baseline: string[] = [];
|
||||
let oldSnap: ReturnType<TestFSWithWatch.TestServerHost["snap"]> | undefined;
|
||||
const system = TestFSWithWatch.changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
tscWatch.createWatchedSystem([
|
||||
coreConfig, coreIndex, coreDecl, coreAnotherModule,
|
||||
logicConfig, logicIndex,
|
||||
testsConfig, testsIndex,
|
||||
tscWatch.libFile
|
||||
])
|
||||
)
|
||||
);
|
||||
|
||||
const host = createSolutionBuilderHost(system);
|
||||
const builder = createSolutionBuilder(host, [testsConfig.path], { dry: false, force: false, verbose: false });
|
||||
builder.build();
|
||||
host.assertDiagnosticMessages(/*empty*/);
|
||||
baselineState("Build of project");
|
||||
|
||||
// Update a timestamp in the middle project
|
||||
tick();
|
||||
appendText(fs, "/src/logic/index.ts", "function foo() {}");
|
||||
const originalWriteFile = fs.writeFileSync;
|
||||
const writtenFiles = new Map<string, true>();
|
||||
fs.writeFileSync = (path, data, encoding) => {
|
||||
writtenFiles.set(path, true);
|
||||
originalWriteFile.call(fs, path, data, encoding);
|
||||
};
|
||||
system.appendFile(logicIndex.path, "function foo() {}");
|
||||
|
||||
// Because we haven't reset the build context, the builder should assume there's nothing to do right now
|
||||
const status = builder.getUpToDateStatusOfProject("/src/logic");
|
||||
assert.equal(status.type, UpToDateStatusType.UpToDate, "Project should be assumed to be up-to-date");
|
||||
verifyInvalidation(/*expectedToWriteTests*/ false);
|
||||
const status = builder.getUpToDateStatusOfProject(logicConfig.path);
|
||||
baseline.push(`Project should still be upto date: ${UpToDateStatusType[status.type]}`);
|
||||
verifyInvalidation("non Dts change to logic");
|
||||
|
||||
// Rebuild this project
|
||||
fs.writeFileSync("/src/logic/index.ts", `${fs.readFileSync("/src/logic/index.ts")}
|
||||
export class cNew {}`);
|
||||
verifyInvalidation(/*expectedToWriteTests*/ true);
|
||||
system.appendFile(logicIndex.path, `export class cNew {}`);
|
||||
verifyInvalidation("Dts change to Logic");
|
||||
Harness.Baseline.runBaseline(`tsbuild/sample1/invalidates-projects-correctly.js`, baseline.join("\r\n"));
|
||||
|
||||
function verifyInvalidation(expectedToWriteTests: boolean) {
|
||||
function verifyInvalidation(heading: string) {
|
||||
// Rebuild this project
|
||||
tick();
|
||||
builder.invalidateProject("/src/logic/tsconfig.json" as ResolvedConfigFilePath);
|
||||
builder.invalidateProject(logicConfig.path as ResolvedConfigFilePath);
|
||||
builder.buildNextInvalidatedProject();
|
||||
// The file should be updated
|
||||
assert.isTrue(writtenFiles.has("/src/logic/index.js"), "JS file should have been rebuilt");
|
||||
assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt");
|
||||
assert.isFalse(writtenFiles.has("/src/tests/index.js"), "Downstream JS file should *not* have been rebuilt");
|
||||
assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should *not* have been rebuilt");
|
||||
writtenFiles.clear();
|
||||
baselineState(`${heading}:: After rebuilding logicConfig`);
|
||||
|
||||
// Build downstream projects should update 'tests', but not 'core'
|
||||
tick();
|
||||
builder.buildNextInvalidatedProject();
|
||||
if (expectedToWriteTests) {
|
||||
assert.isTrue(writtenFiles.has("/src/tests/index.js"), "Downstream JS file should have been rebuilt");
|
||||
}
|
||||
else {
|
||||
assert.equal(writtenFiles.size, 0, "Should not write any new files");
|
||||
}
|
||||
assert.equal(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have new timestamp");
|
||||
assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt");
|
||||
baselineState(`${heading}:: After building next project`);
|
||||
}
|
||||
|
||||
function baselineState(heading: string) {
|
||||
baseline.push(heading);
|
||||
system.serializeOutput(baseline);
|
||||
system.diff(baseline, oldSnap);
|
||||
system.writtenFiles.clear();
|
||||
oldSnap = system.snap();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const coreChanges: TscIncremental[] = [
|
||||
const coreChanges: TestTscEdit[] = [
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => appendText(fs, "/src/core/index.ts", `
|
||||
export class someClass { }`),
|
||||
},
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => appendText(fs, "/src/core/index.ts", `
|
||||
class someClass2 { }`),
|
||||
}
|
||||
];
|
||||
|
||||
describe("lists files", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "listFiles",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/tests", "--listFiles"],
|
||||
incrementalScenarios: coreChanges
|
||||
edits: coreChanges
|
||||
});
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "listEmittedFiles",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/tests", "--listEmittedFiles"],
|
||||
incrementalScenarios: coreChanges
|
||||
edits: coreChanges
|
||||
});
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "sample1",
|
||||
subScenario: "explainFiles",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/tests", "--explainFiles", "--v"],
|
||||
incrementalScenarios: coreChanges
|
||||
edits: coreChanges
|
||||
});
|
||||
});
|
||||
|
||||
describe("emit output", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "sample",
|
||||
fs: () => projFs,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "/src/tests", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
baselineReadFileCalls: true,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
...coreChanges,
|
||||
{
|
||||
subScenario: "when logic config changes declaration dir",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => replaceText(fs, "/src/logic/tsconfig.json", `"declaration": true,`, `"declaration": true,
|
||||
"declarationDir": "decls",`),
|
||||
},
|
||||
@@ -426,7 +424,7 @@ class someClass2 { }`),
|
||||
baselineReadFileCalls: true
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "when declaration option changes",
|
||||
fs: () => projFs,
|
||||
scenario: "sample1",
|
||||
@@ -437,13 +435,13 @@ class someClass2 { }`),
|
||||
"skipDefaultLibCheck": true
|
||||
}
|
||||
}`),
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "when target option changes",
|
||||
fs: () => projFs,
|
||||
scenario: "sample1",
|
||||
@@ -463,13 +461,13 @@ class someClass2 { }`),
|
||||
}
|
||||
}`);
|
||||
},
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", "esnext", "es5"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "when module option changes",
|
||||
fs: () => projFs,
|
||||
scenario: "sample1",
|
||||
@@ -480,13 +478,13 @@ class someClass2 { }`),
|
||||
"module": "commonjs"
|
||||
}
|
||||
}`),
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"module": "commonjs"`, `"module": "amd"`),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
subScenario: "when esModuleInterop option changes",
|
||||
fs: () => projFs,
|
||||
scenario: "sample1",
|
||||
@@ -505,8 +503,8 @@ class someClass2 { }`),
|
||||
"esModuleInterop": false
|
||||
}
|
||||
}`),
|
||||
incrementalScenarios: [{
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
edits: [{
|
||||
subScenario: "incremental-declaration-changes",
|
||||
modifyFs: fs => replaceText(fs, "/src/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`),
|
||||
}],
|
||||
});
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
namespace ts.tscWatch {
|
||||
import projectsLocation = TestFSWithWatch.tsbuildProjectsLocation;
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
type TsBuildWatchSystem = TestFSWithWatch.TestServerHostTrackingWrittenFiles;
|
||||
|
||||
function createTsBuildWatchSystem(fileOrFolderList: readonly TestFSWithWatch.FileOrFolderOrSymLink[], params?: TestFSWithWatch.TestServerHostCreationParameters) {
|
||||
return TestFSWithWatch.changeToHostTrackingWrittenFiles(
|
||||
createWatchedSystem(fileOrFolderList, params)
|
||||
);
|
||||
}
|
||||
|
||||
type OutputFileStamp = [string, Date | undefined, boolean];
|
||||
function transformOutputToOutputFileStamp(f: string, host: TsBuildWatchSystem): OutputFileStamp {
|
||||
return [f, host.getModifiedTime(f), host.writtenFiles.has(host.toFullPath(f))] as OutputFileStamp;
|
||||
}
|
||||
|
||||
const scenario = "programUpdates";
|
||||
const project = "sample1";
|
||||
const enum SubProject {
|
||||
core = "core",
|
||||
logic = "logic",
|
||||
@@ -24,17 +9,13 @@ namespace ts.tscWatch {
|
||||
}
|
||||
type ReadonlyFile = Readonly<File>;
|
||||
/** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */
|
||||
type SubProjectFiles = [ReadonlyFile, ReadonlyFile] | [ReadonlyFile, ReadonlyFile, ReadonlyFile, ReadonlyFile];
|
||||
function projectPath(subProject: SubProject) {
|
||||
return TestFSWithWatch.getTsBuildProjectFilePath(project, subProject);
|
||||
}
|
||||
|
||||
type SubProjectFiles = [tsconfig: ReadonlyFile, index: ReadonlyFile] | [tsconfig: ReadonlyFile, index: ReadonlyFile, anotherModule: ReadonlyFile, someDecl: ReadonlyFile];
|
||||
function projectFilePath(subProject: SubProject, baseFileName: string) {
|
||||
return `${projectPath(subProject)}/${baseFileName.toLowerCase()}`;
|
||||
return `${TestFSWithWatch.getTsBuildProjectFilePath("sample1", subProject)}/${baseFileName.toLowerCase()}`;
|
||||
}
|
||||
|
||||
function projectFile(subProject: SubProject, baseFileName: string): File {
|
||||
return TestFSWithWatch.getTsBuildProjectFile(project, `${subProject}/${baseFileName}`);
|
||||
return TestFSWithWatch.getTsBuildProjectFile("sample1", `${subProject}/${baseFileName}`);
|
||||
}
|
||||
|
||||
function subProjectFiles(subProject: SubProject, anotherModuleAndSomeDecl?: true): SubProjectFiles {
|
||||
@@ -48,29 +29,6 @@ namespace ts.tscWatch {
|
||||
return [tsconfig, index, anotherModule, someDecl];
|
||||
}
|
||||
|
||||
function getOutputFileNames(subProject: SubProject, baseFileNameWithoutExtension: string) {
|
||||
const file = projectFilePath(subProject, baseFileNameWithoutExtension);
|
||||
return [`${file}.js`, `${file}.d.ts`];
|
||||
}
|
||||
|
||||
function getOutputStamps(host: TsBuildWatchSystem, subProject: SubProject, baseFileNameWithoutExtension: string): OutputFileStamp[] {
|
||||
return getOutputFileNames(subProject, baseFileNameWithoutExtension).map(f => transformOutputToOutputFileStamp(f, host));
|
||||
}
|
||||
|
||||
function getOutputFileStamps(host: TsBuildWatchSystem, additionalFiles?: readonly [SubProject, string][]): OutputFileStamp[] {
|
||||
const result = [
|
||||
...getOutputStamps(host, SubProject.core, "anotherModule"),
|
||||
...getOutputStamps(host, SubProject.core, "index"),
|
||||
...getOutputStamps(host, SubProject.logic, "index"),
|
||||
...getOutputStamps(host, SubProject.tests, "index"),
|
||||
];
|
||||
if (additionalFiles) {
|
||||
additionalFiles.forEach(([subProject, baseFileNameWithoutExtension]) => result.push(...getOutputStamps(host, subProject, baseFileNameWithoutExtension)));
|
||||
}
|
||||
host.writtenFiles.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
function changeFile(fileName: string | (() => string), content: string | (() => string), caption: string): TscWatchCompileChange {
|
||||
return {
|
||||
caption,
|
||||
@@ -88,8 +46,6 @@ namespace ts.tscWatch {
|
||||
let tests: SubProjectFiles;
|
||||
let ui: SubProjectFiles;
|
||||
let allFiles: readonly File[];
|
||||
let testProjectExpectedWatchedFiles: string[];
|
||||
let testProjectExpectedWatchedDirectoriesRecursive: string[];
|
||||
|
||||
before(() => {
|
||||
core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true);
|
||||
@@ -97,8 +53,6 @@ namespace ts.tscWatch {
|
||||
tests = subProjectFiles(SubProject.tests);
|
||||
ui = subProjectFiles(SubProject.ui);
|
||||
allFiles = [libFile, ...core, ...logic, ...tests, ...ui];
|
||||
testProjectExpectedWatchedFiles = [core[0], core[1], core[2]!, ...logic, ...tests].map(f => f.path.toLowerCase());
|
||||
testProjectExpectedWatchedDirectoriesRecursive = [projectPath(SubProject.core), projectPath(SubProject.logic)];
|
||||
});
|
||||
|
||||
after(() => {
|
||||
@@ -107,38 +61,32 @@ namespace ts.tscWatch {
|
||||
tests = undefined!;
|
||||
ui = undefined!;
|
||||
allFiles = undefined!;
|
||||
testProjectExpectedWatchedFiles = undefined!;
|
||||
testProjectExpectedWatchedDirectoriesRecursive = undefined!;
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "creates solution in watch mode",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`],
|
||||
sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }),
|
||||
changes: emptyArray
|
||||
});
|
||||
|
||||
it("verify building references watches only those projects", () => {
|
||||
const system = createTsBuildWatchSystem(allFiles, { currentDirectory: projectsLocation });
|
||||
const host = createSolutionBuilderWithWatchHost(system);
|
||||
const solutionBuilder = createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`], { watch: true });
|
||||
solutionBuilder.buildReferences(`${project}/${SubProject.tests}`);
|
||||
|
||||
checkWatchedFiles(system, testProjectExpectedWatchedFiles.slice(0, testProjectExpectedWatchedFiles.length - tests.length));
|
||||
checkWatchedDirectories(system, emptyArray, /*recursive*/ false);
|
||||
checkWatchedDirectories(system, testProjectExpectedWatchedDirectoriesRecursive, /*recursive*/ true);
|
||||
|
||||
checkOutputErrorsInitial(system, emptyArray);
|
||||
const testOutput = getOutputStamps(system, SubProject.tests, "index");
|
||||
const outputFileStamps = getOutputFileStamps(system);
|
||||
for (const stamp of outputFileStamps.slice(0, outputFileStamps.length - testOutput.length)) {
|
||||
assert.isDefined(stamp[1], `${stamp[0]} expected to be present`);
|
||||
}
|
||||
for (const stamp of testOutput) {
|
||||
assert.isUndefined(stamp[1], `${stamp[0]} expected to be missing`);
|
||||
}
|
||||
return system;
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(allFiles, { currentDirectory: projectsLocation }));
|
||||
const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
const solutionBuilder = createSolutionBuilderWithWatch(host, [`sample1/${SubProject.tests}`], { watch: true });
|
||||
solutionBuilder.buildReferences(`sample1/${SubProject.tests}`);
|
||||
runWatchBaseline({
|
||||
scenario: "programUpdates",
|
||||
subScenario: "verify building references watches only those projects",
|
||||
commandLineArgs: ["--b", "--w"],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: emptyArray,
|
||||
watchOrSolution: solutionBuilder
|
||||
});
|
||||
});
|
||||
|
||||
const buildTests: TscWatchCompileChange = {
|
||||
@@ -163,9 +111,9 @@ namespace ts.tscWatch {
|
||||
};
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/change builds changes and reports found errors message`,
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`],
|
||||
sys: () => createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: projectsLocation }
|
||||
@@ -198,9 +146,9 @@ export class someClass2 { }`);
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/non local change does not start build of referencing projects`,
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`],
|
||||
sys: () => createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: projectsLocation }
|
||||
@@ -217,9 +165,9 @@ function foo() { }`, "Make local change to core"),
|
||||
return changeFile(newFile.path, newFileContent, "Change to new File and build core");
|
||||
}
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/builds when new file is added, and its subsequent updates`,
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`],
|
||||
sys: () => createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: projectsLocation }
|
||||
@@ -262,9 +210,9 @@ export class someClass2 { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "watches config files that are not present",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`],
|
||||
sys: () => createWatchedSystem(
|
||||
[libFile, ...core, logic[1], ...tests],
|
||||
{ currentDirectory: projectsLocation }
|
||||
@@ -297,9 +245,9 @@ export class someClass2 { }`),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout,
|
||||
};
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "when referenced using prepend builds referencing project even for non local change",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.logic}`],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.logic}`],
|
||||
sys: () => {
|
||||
const coreTsConfig: File = {
|
||||
path: core[0].path,
|
||||
@@ -332,7 +280,7 @@ function myFunc() { return 100; }`, "Make local change and build core"),
|
||||
});
|
||||
|
||||
describe("when referenced project change introduces error in the down stream project and then fixes it", () => {
|
||||
const subProjectLibrary = `${projectsLocation}/${project}/Library`;
|
||||
const subProjectLibrary = `${projectsLocation}/sample1/Library`;
|
||||
const libraryTs: File = {
|
||||
path: `${subProjectLibrary}/library.ts`,
|
||||
content: `
|
||||
@@ -349,7 +297,7 @@ export function createSomeObject(): SomeObject
|
||||
}`
|
||||
};
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "when referenced project change introduces error in the down stream project and then fixes it",
|
||||
commandLineArgs: ["-b", "-w", "App"],
|
||||
sys: () => {
|
||||
@@ -357,7 +305,7 @@ export function createSomeObject(): SomeObject
|
||||
path: `${subProjectLibrary}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: { composite: true } })
|
||||
};
|
||||
const subProjectApp = `${projectsLocation}/${project}/App`;
|
||||
const subProjectApp = `${projectsLocation}/sample1/App`;
|
||||
const appTs: File = {
|
||||
path: `${subProjectApp}/app.ts`,
|
||||
content: `import { createSomeObject } from "../Library/library";
|
||||
@@ -369,7 +317,7 @@ createSomeObject().message;`
|
||||
};
|
||||
|
||||
const files = [libFile, libraryTs, libraryTsconfig, appTs, appTsconfig];
|
||||
return createWatchedSystem(files, { currentDirectory: `${projectsLocation}/${project}` });
|
||||
return createWatchedSystem(files, { currentDirectory: `${projectsLocation}/sample1` });
|
||||
},
|
||||
changes: [
|
||||
{
|
||||
@@ -398,9 +346,9 @@ createSomeObject().message;`
|
||||
describe("reports errors in all projects on incremental compile", () => {
|
||||
function verifyIncrementalErrors(subScenario: string, buildOptions: readonly string[]) {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: `reportErrors/${subScenario}`,
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`, ...buildOptions],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`, ...buildOptions],
|
||||
sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }),
|
||||
changes: [
|
||||
{
|
||||
@@ -466,7 +414,7 @@ let x: string = 10;`),
|
||||
};
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "reportErrors/declarationEmitErrors/when fixing error files all files are emitted",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () => createWatchedSystem(
|
||||
@@ -479,7 +427,7 @@ let x: string = 10;`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "reportErrors/declarationEmitErrors/when file with no error changes",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () => createWatchedSystem(
|
||||
@@ -499,7 +447,7 @@ let x: string = 10;`),
|
||||
};
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "reportErrors/declarationEmitErrors/introduceError/when fixing errors only changed file is emitted",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () => createWatchedSystem(
|
||||
@@ -513,7 +461,7 @@ let x: string = 10;`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "reportErrors/declarationEmitErrors/introduceError/when file with no error changes",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () => createWatchedSystem(
|
||||
@@ -530,9 +478,9 @@ let x: string = 10;`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "incremental updates in verbose mode",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.tests}`, "-verbose"],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`, "-verbose"],
|
||||
sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }),
|
||||
changes: [
|
||||
{
|
||||
@@ -557,7 +505,7 @@ export function someFn() { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "works when noUnusedParameters changes to false",
|
||||
commandLineArgs: ["-b", "-w"],
|
||||
sys: () => {
|
||||
@@ -589,15 +537,15 @@ export function someFn() { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "should not trigger recompilation because of program emit",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.core}`, "-verbose"],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.core}`, "-verbose"],
|
||||
sys: () => createWatchedSystem([libFile, ...core], { currentDirectory: projectsLocation }),
|
||||
changes: [
|
||||
noopChange,
|
||||
{
|
||||
caption: "Add new file",
|
||||
change: sys => sys.writeFile(`${project}/${SubProject.core}/file3.ts`, `export const y = 10;`),
|
||||
change: sys => sys.writeFile(`sample1/${SubProject.core}/file3.ts`, `export const y = 10;`),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun
|
||||
},
|
||||
noopChange,
|
||||
@@ -605,9 +553,9 @@ export function someFn() { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "should not trigger recompilation because of program emit with outDir specified",
|
||||
commandLineArgs: ["-b", "-w", `${project}/${SubProject.core}`, "-verbose"],
|
||||
commandLineArgs: ["-b", "-w", `sample1/${SubProject.core}`, "-verbose"],
|
||||
sys: () => {
|
||||
const [coreConfig, ...rest] = core;
|
||||
const newCoreConfig: File = { path: coreConfig.path, content: JSON.stringify({ compilerOptions: { composite: true, outDir: "outDir" } }) };
|
||||
@@ -617,7 +565,7 @@ export function someFn() { }`),
|
||||
noopChange,
|
||||
{
|
||||
caption: "Add new file",
|
||||
change: sys => sys.writeFile(`${project}/${SubProject.core}/file3.ts`, `export const y = 10;`),
|
||||
change: sys => sys.writeFile(`sample1/${SubProject.core}/file3.ts`, `export const y = 10;`),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun
|
||||
},
|
||||
noopChange
|
||||
@@ -625,7 +573,7 @@ export function someFn() { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "works with extended source files",
|
||||
commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json"],
|
||||
sys: () => {
|
||||
@@ -711,7 +659,7 @@ export function someFn() { }`),
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "works correctly when project with extended config is removed",
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () => {
|
||||
|
||||
@@ -40,17 +40,8 @@ export enum e2 { }
|
||||
export function f22() { } // trailing`
|
||||
};
|
||||
const commandLineArgs = ["--b", "--w"];
|
||||
const { sys, baseline, oldSnap } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: projectRoot }));
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
const buildHost = createSolutionBuilderWithWatchHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
createWatchStatusReporter(sys, /*pretty*/ true)
|
||||
);
|
||||
buildHost.afterProgramEmitAndDiagnostics = cb;
|
||||
buildHost.afterEmitBundle = cb;
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: projectRoot }));
|
||||
const buildHost = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
buildHost.getCustomTransformers = getCustomTransformers;
|
||||
const builder = createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true });
|
||||
builder.build();
|
||||
|
||||
@@ -23,52 +23,56 @@ namespace ts.tscWatch {
|
||||
|
||||
const allPkgFiles = pkgs(pkgFiles);
|
||||
const system = createWatchedSystem([libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project, environmentVariables });
|
||||
writePkgReferences();
|
||||
const host = createSolutionBuilderWithWatchHost(system);
|
||||
writePkgReferences(system);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(system);
|
||||
const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
const solutionBuilder = createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true });
|
||||
solutionBuilder.build();
|
||||
checkOutputErrorsInitial(system, emptyArray, /*disableConsoleClears*/ undefined, [
|
||||
`Projects in this build: \r\n${
|
||||
concatenate(
|
||||
pkgs(index => ` * pkg${index}/tsconfig.json`),
|
||||
[" * tsconfig.json"]
|
||||
).join("\r\n")}\n\n`,
|
||||
...flatArray(pkgs(index => [
|
||||
`Project 'pkg${index}/tsconfig.json' is out of date because output file 'pkg${index}/index.js' does not exist\n\n`,
|
||||
`Building project '${project}/pkg${index}/tsconfig.json'...\n\n`
|
||||
]))
|
||||
]);
|
||||
|
||||
const watchFilesDetailed = arrayToMap(flatArray(allPkgFiles), f => f.path, () => 1);
|
||||
watchFilesDetailed.set(configPath, 1);
|
||||
watchFilesDetailed.set(typing.path, singleWatchPerFile ? 1 : maxPkgs);
|
||||
checkWatchedFilesDetailed(system, watchFilesDetailed);
|
||||
system.writeFile(typing.path, `${typing.content}export const typing1 = 10;`);
|
||||
verifyInvoke();
|
||||
|
||||
// Make change
|
||||
maxPkgs--;
|
||||
writePkgReferences();
|
||||
system.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(system, emptyArray);
|
||||
const lastFiles = last(allPkgFiles);
|
||||
lastFiles.forEach(f => watchFilesDetailed.delete(f.path));
|
||||
watchFilesDetailed.set(typing.path, singleWatchPerFile ? 1 : maxPkgs);
|
||||
checkWatchedFilesDetailed(system, watchFilesDetailed);
|
||||
system.writeFile(typing.path, typing.content);
|
||||
verifyInvoke();
|
||||
|
||||
// Make change to remove all the watches
|
||||
maxPkgs = 0;
|
||||
writePkgReferences();
|
||||
system.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(system, [
|
||||
`tsconfig.json(1,10): error TS18002: The 'files' list in config file '${configPath}' is empty.\n`
|
||||
]);
|
||||
checkWatchedFilesDetailed(system, [configPath], 1);
|
||||
|
||||
system.writeFile(typing.path, `${typing.content}export const typing1 = 10;`);
|
||||
system.checkTimeoutQueueLength(0);
|
||||
runWatchBaseline({
|
||||
scenario: "watchEnvironment",
|
||||
subScenario: `same file in multiple projects${singleWatchPerFile ? " with single watcher per file" : ""}`,
|
||||
commandLineArgs: ["--b", "--w"],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [
|
||||
{
|
||||
caption: "modify typing file",
|
||||
change: sys => sys.writeFile(typing.path, `${typing.content}export const typing1 = 10;`),
|
||||
timeouts: sys => pkgs(() => sys.checkTimeoutQueueLengthAndRun(1))
|
||||
},
|
||||
{
|
||||
// Make change
|
||||
caption: "change pkg references",
|
||||
change: sys => {
|
||||
maxPkgs--;
|
||||
writePkgReferences(sys);
|
||||
},
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
},
|
||||
{
|
||||
caption: "modify typing file",
|
||||
change: sys => sys.writeFile(typing.path, typing.content),
|
||||
timeouts: sys => pkgs(() => sys.checkTimeoutQueueLengthAndRun(1))
|
||||
},
|
||||
{
|
||||
// Make change to remove all watches
|
||||
caption: "change pkg references to remove all watches",
|
||||
change: sys => {
|
||||
maxPkgs = 0;
|
||||
writePkgReferences(sys);
|
||||
},
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
},
|
||||
{
|
||||
caption: "modify typing file",
|
||||
change: sys => sys.writeFile(typing.path, `${typing.content}export const typing1 = 10;`),
|
||||
timeouts: sys => pkgs(() => sys.checkTimeoutQueueLengthAndRun(1))
|
||||
},
|
||||
],
|
||||
watchOrSolution: solutionBuilder
|
||||
});
|
||||
|
||||
function flatArray<T>(arr: T[][]): readonly T[] {
|
||||
return flatMap(arr, identity);
|
||||
@@ -101,23 +105,13 @@ namespace ts.tscWatch {
|
||||
}
|
||||
];
|
||||
}
|
||||
function writePkgReferences() {
|
||||
function writePkgReferences(system: TestFSWithWatch.TestServerHost) {
|
||||
system.writeFile(configPath, JSON.stringify({
|
||||
files: [],
|
||||
include: [],
|
||||
references: pkgs(createPkgReference)
|
||||
}));
|
||||
}
|
||||
function verifyInvoke() {
|
||||
pkgs(() => system.checkTimeoutQueueLengthAndRun(1));
|
||||
checkOutputErrorsIncremental(system, emptyArray, /*disableConsoleClears*/ undefined, /*logsBeforeWatchDiagnostics*/ undefined, [
|
||||
...flatArray(pkgs(index => [
|
||||
`Project 'pkg${index}/tsconfig.json' is out of date because oldest output 'pkg${index}/index.js' is older than newest input 'typings/xterm.d.ts'\n\n`,
|
||||
`Building project '${project}/pkg${index}/tsconfig.json'...\n\n`,
|
||||
`Updating unchanged output timestamps of project '${project}/pkg${index}/tsconfig.json'...\n\n`
|
||||
]))
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,44 +5,27 @@ namespace ts {
|
||||
disableUseFileVersionAsSignature?: boolean;
|
||||
};
|
||||
|
||||
export enum BuildKind {
|
||||
Initial = "initial-build",
|
||||
IncrementalDtsChange = "incremental-declaration-changes",
|
||||
IncrementalDtsUnchanged = "incremental-declaration-doesnt-change",
|
||||
IncrementalHeadersChange = "incremental-headers-change-without-dts-changes",
|
||||
NoChangeRun = "no-change-run"
|
||||
}
|
||||
|
||||
export const noChangeRun: TscIncremental = {
|
||||
buildKind: BuildKind.NoChangeRun,
|
||||
export const noChangeRun: TestTscEdit = {
|
||||
subScenario: "no-change-run",
|
||||
modifyFs: noop
|
||||
};
|
||||
export const noChangeOnlyRuns = [noChangeRun];
|
||||
|
||||
export interface TscCompile {
|
||||
scenario: string;
|
||||
subScenario: string;
|
||||
buildKind?: BuildKind; // Should be defined for tsc --b
|
||||
fs: () => vfs.FileSystem;
|
||||
commandLineArgs: readonly string[];
|
||||
|
||||
modifyFs?: (fs: vfs.FileSystem) => void;
|
||||
export interface TestTscCompile extends TestTscCompileLikeBase {
|
||||
baselineSourceMap?: boolean;
|
||||
baselineReadFileCalls?: boolean;
|
||||
baselinePrograms?: boolean;
|
||||
baselineDependencies?: boolean;
|
||||
disableUseFileVersionAsSignature?: boolean;
|
||||
environmentVariables?: Record<string, string>;
|
||||
}
|
||||
|
||||
export type CommandLineProgram = [Program, EmitAndSemanticDiagnosticsBuilderProgram?];
|
||||
export type CommandLineProgram = [Program, BuilderProgram?];
|
||||
export interface CommandLineCallbacks {
|
||||
cb: ExecuteCommandLineCallbacks;
|
||||
getPrograms: () => readonly CommandLineProgram[];
|
||||
}
|
||||
|
||||
function isAnyProgram(program: Program | EmitAndSemanticDiagnosticsBuilderProgram | ParsedCommandLine): program is Program | EmitAndSemanticDiagnosticsBuilderProgram {
|
||||
return !!(program as Program | EmitAndSemanticDiagnosticsBuilderProgram).getCompilerOptions;
|
||||
function isAnyProgram(program: Program | BuilderProgram | ParsedCommandLine): program is Program | BuilderProgram {
|
||||
return !!(program as Program | BuilderProgram).getCompilerOptions;
|
||||
}
|
||||
export function commandLineCallbacks(
|
||||
sys: System & { writtenFiles: ReadonlyCollection<Path>; },
|
||||
@@ -71,15 +54,28 @@ namespace ts {
|
||||
}
|
||||
};
|
||||
}
|
||||
export interface TestTscCompileLikeBase extends VerifyTscCompileLike {
|
||||
diffWithInitial?: boolean;
|
||||
modifyFs?: (fs: vfs.FileSystem) => void;
|
||||
disableUseFileVersionAsSignature?: boolean;
|
||||
environmentVariables?: Record<string, string>;
|
||||
}
|
||||
|
||||
export function tscCompile(input: TscCompile) {
|
||||
export interface TestTscCompileLike extends TestTscCompileLikeBase {
|
||||
compile: (sys: TscCompileSystem) => void;
|
||||
additionalBaseline?: (sys: TscCompileSystem) => void;
|
||||
}
|
||||
/**
|
||||
* Initialize FS, run compile function and save baseline
|
||||
*/
|
||||
export function testTscCompileLike(input: TestTscCompileLike) {
|
||||
const initialFs = input.fs();
|
||||
const inputFs = initialFs.shadow();
|
||||
const {
|
||||
scenario, subScenario, buildKind,
|
||||
scenario, subScenario, diffWithInitial,
|
||||
commandLineArgs, modifyFs,
|
||||
baselineSourceMap, baselineReadFileCalls, baselinePrograms, baselineDependencies,
|
||||
environmentVariables
|
||||
environmentVariables,
|
||||
compile: worker, additionalBaseline,
|
||||
} = input;
|
||||
if (modifyFs) modifyFs(inputFs);
|
||||
inputFs.makeReadonly();
|
||||
@@ -88,53 +84,19 @@ namespace ts {
|
||||
// Create system
|
||||
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc", env: environmentVariables }) as TscCompileSystem;
|
||||
if (input.disableUseFileVersionAsSignature) sys.disableUseFileVersionAsSignature = true;
|
||||
fakes.patchHostForBuildInfoReadWrite(sys);
|
||||
const writtenFiles = sys.writtenFiles = new Set();
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName, content, writeByteOrderMark) => {
|
||||
const path = toPathWithSystem(sys, fileName);
|
||||
assert.isFalse(writtenFiles.has(path));
|
||||
writtenFiles.add(path);
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
const actualReadFileMap: MapLike<number> = {};
|
||||
const originalReadFile = sys.readFile;
|
||||
sys.readFile = path => {
|
||||
// Dont record libs
|
||||
if (path.startsWith("/src/")) {
|
||||
actualReadFileMap[path] = (getProperty(actualReadFileMap, path) || 0) + 1;
|
||||
}
|
||||
return originalReadFile.call(sys, path);
|
||||
};
|
||||
|
||||
sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`);
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys, originalReadFile, originalWriteFile);
|
||||
executeCommandLine(
|
||||
sys,
|
||||
cb,
|
||||
commandLineArgs,
|
||||
);
|
||||
worker(sys);
|
||||
sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`);
|
||||
if (baselinePrograms) {
|
||||
const baseline: string[] = [];
|
||||
tscWatch.baselinePrograms(baseline, getPrograms, emptyArray, baselineDependencies);
|
||||
sys.write(baseline.join("\n"));
|
||||
}
|
||||
if (baselineReadFileCalls) {
|
||||
sys.write(`readFiles:: ${JSON.stringify(actualReadFileMap, /*replacer*/ undefined, " ")} `);
|
||||
}
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
|
||||
additionalBaseline?.(sys);
|
||||
fs.makeReadonly();
|
||||
|
||||
sys.baseLine = () => {
|
||||
const baseFsPatch = !buildKind || buildKind === BuildKind.Initial ?
|
||||
inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true }) :
|
||||
inputFs.diff(initialFs, { includeChangedFileWithSameContent: true });
|
||||
const baseFsPatch = diffWithInitial ?
|
||||
inputFs.diff(initialFs, { includeChangedFileWithSameContent: true }) :
|
||||
inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true });
|
||||
const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true });
|
||||
return {
|
||||
file: `${isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${buildKind || BuildKind.Initial}/${subScenario.split(" ").join("-")}.js`,
|
||||
file: `${isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}.js`,
|
||||
text: `Input::
|
||||
${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""}
|
||||
|
||||
@@ -147,30 +109,97 @@ ${patch ? vfs.formatPatch(patch) : ""}`
|
||||
return sys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Fs, execute command line and save baseline
|
||||
*/
|
||||
export function testTscCompile(input: TestTscCompile) {
|
||||
let actualReadFileMap: MapLike<number> | undefined;
|
||||
let getPrograms: CommandLineCallbacks["getPrograms"] | undefined;
|
||||
return testTscCompileLike({
|
||||
...input,
|
||||
compile: commandLineCompile,
|
||||
additionalBaseline
|
||||
});
|
||||
|
||||
function commandLineCompile(sys: TscCompileSystem) {
|
||||
fakes.patchHostForBuildInfoReadWrite(sys);
|
||||
const writtenFiles = sys.writtenFiles = new Set();
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName, content, writeByteOrderMark) => {
|
||||
const path = toPathWithSystem(sys, fileName);
|
||||
assert.isFalse(writtenFiles.has(path));
|
||||
writtenFiles.add(path);
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
actualReadFileMap = {};
|
||||
const originalReadFile = sys.readFile;
|
||||
sys.readFile = path => {
|
||||
// Dont record libs
|
||||
if (path.startsWith("/src/")) {
|
||||
actualReadFileMap![path] = (getProperty(actualReadFileMap!, path) || 0) + 1;
|
||||
}
|
||||
return originalReadFile.call(sys, path);
|
||||
};
|
||||
|
||||
const result = commandLineCallbacks(sys, originalReadFile, originalWriteFile);
|
||||
executeCommandLine(
|
||||
sys,
|
||||
result.cb,
|
||||
input.commandLineArgs,
|
||||
);
|
||||
sys.readFile = originalReadFile;
|
||||
getPrograms = result.getPrograms;
|
||||
}
|
||||
|
||||
function additionalBaseline(sys: TscCompileSystem) {
|
||||
const { baselineSourceMap, baselineReadFileCalls, baselinePrograms, baselineDependencies } = input;
|
||||
if (baselinePrograms) {
|
||||
const baseline: string[] = [];
|
||||
tscWatch.baselinePrograms(baseline, getPrograms!, emptyArray, baselineDependencies);
|
||||
sys.write(baseline.join("\n"));
|
||||
}
|
||||
if (baselineReadFileCalls) {
|
||||
sys.write(`readFiles:: ${JSON.stringify(actualReadFileMap, /*replacer*/ undefined, " ")} `);
|
||||
}
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
actualReadFileMap = undefined;
|
||||
getPrograms = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }) {
|
||||
it(`Generates files matching the baseline`, () => {
|
||||
const { file, text } = sys().baseLine();
|
||||
Harness.Baseline.runBaseline(file, text);
|
||||
});
|
||||
}
|
||||
export interface VerifyTscCompileLike {
|
||||
scenario: string;
|
||||
subScenario: string;
|
||||
commandLineArgs: readonly string[];
|
||||
fs: () => vfs.FileSystem;
|
||||
}
|
||||
|
||||
export function verifyTsc(input: TscCompile) {
|
||||
/**
|
||||
* Verify by baselining after initializing FS and custom compile
|
||||
*/
|
||||
export function verifyTscCompileLike<T extends VerifyTscCompileLike>(verifier: (input: T) => { baseLine: TscCompileSystem["baseLine"]; }, input: T) {
|
||||
describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => {
|
||||
describe(input.scenario, () => {
|
||||
describe(input.subScenario, () => {
|
||||
let sys: TscCompileSystem;
|
||||
before(() => {
|
||||
sys = tscCompile({
|
||||
...input,
|
||||
fs: () => getFsWithTime(input.fs()).fs.makeReadonly()
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
sys = undefined!;
|
||||
});
|
||||
verifyTscBaseline(() => sys);
|
||||
verifyTscBaseline(() => verifier({
|
||||
...input,
|
||||
fs: () => getFsWithTime(input.fs()).fs.makeReadonly()
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify by baselining after initializing FS and command line compile
|
||||
*/
|
||||
export function verifyTsc(input: TestTscCompile) {
|
||||
verifyTscCompileLike(testTscCompile, input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsc:: incremental::", () => {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing filename for buildinfo on commandline",
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -17,10 +17,10 @@ namespace ts {
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing rootDir from commandline",
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -34,10 +34,10 @@ namespace ts {
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "with only dts files",
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -46,16 +46,16 @@ namespace ts {
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
}),
|
||||
commandLineArgs: ["--incremental", "--p", "src/project"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fs => appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;")
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing rootDir is in the tsconfig",
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -70,7 +70,7 @@ namespace ts {
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
incrementalScenarios: noChangeOnlyRuns
|
||||
edits: noChangeOnlyRuns
|
||||
});
|
||||
|
||||
describe("with noEmitOnError", () => {
|
||||
@@ -82,17 +82,17 @@ namespace ts {
|
||||
projFs = undefined!;
|
||||
});
|
||||
|
||||
function verifyNoEmitOnError(subScenario: string, fixModifyFs: TscIncremental["modifyFs"], modifyFs?: TscIncremental["modifyFs"]) {
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
function verifyNoEmitOnError(subScenario: string, fixModifyFs: TestTscEdit["modifyFs"], modifyFs?: TestTscEdit["modifyFs"]) {
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario,
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--incremental", "-p", "src"],
|
||||
modifyFs,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
subScenario: "incremental-declaration-doesnt-change",
|
||||
modifyFs: fixModifyFs
|
||||
},
|
||||
noChangeRun,
|
||||
@@ -123,15 +123,15 @@ const a: string = 10;`, "utf-8"),
|
||||
verifyNoEmitChanges({ composite: true });
|
||||
|
||||
function verifyNoEmitChanges(compilerOptions: CompilerOptions) {
|
||||
const noChangeRunWithNoEmit: TscIncremental = {
|
||||
const noChangeRunWithNoEmit: TestTscEdit = {
|
||||
...noChangeRun,
|
||||
subScenario: "No Change run with noEmit",
|
||||
commandLineArgs: ["--p", "src/project", "--noEmit"],
|
||||
...noChangeRun,
|
||||
};
|
||||
const noChangeRunWithEmit: TscIncremental = {
|
||||
const noChangeRunWithEmit: TestTscEdit = {
|
||||
...noChangeRun,
|
||||
subScenario: "No Change run with emit",
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
...noChangeRun,
|
||||
};
|
||||
let optionsString = "";
|
||||
for (const key in compilerOptions) {
|
||||
@@ -140,24 +140,22 @@ const a: string = 10;`, "utf-8"),
|
||||
}
|
||||
}
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: `noEmit changes${optionsString}`,
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
fs,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRunWithNoEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
{
|
||||
subScenario: "Introduce error but still noEmit",
|
||||
commandLineArgs: ["--p", "src/project", "--noEmit"],
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
{
|
||||
subScenario: "Fix error and emit",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
@@ -166,7 +164,6 @@ const a: string = 10;`, "utf-8"),
|
||||
{
|
||||
subScenario: "Introduce error and emit",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
@@ -176,7 +173,6 @@ const a: string = 10;`, "utf-8"),
|
||||
subScenario: "Fix error and no emit",
|
||||
commandLineArgs: ["--p", "src/project", "--noEmit"],
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
@@ -185,23 +181,21 @@ const a: string = 10;`, "utf-8"),
|
||||
],
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: `noEmit changes with initial noEmit${optionsString}`,
|
||||
commandLineArgs: ["--p", "src/project", "--noEmit"],
|
||||
fs,
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRunWithEmit,
|
||||
{
|
||||
subScenario: "Introduce error with emit",
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
{
|
||||
subScenario: "Fix error and no emit",
|
||||
modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
buildKind: BuildKind.IncrementalDtsChange
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
],
|
||||
@@ -236,7 +230,7 @@ const a: string = 10;`, "utf-8"),
|
||||
}
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: `when global file is added, the signatures are updated`,
|
||||
fs: () => loadProjectFromFiles({
|
||||
@@ -257,21 +251,18 @@ const a: string = 10;`, "utf-8"),
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
subScenario: "Modify main file",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
},
|
||||
{
|
||||
subScenario: "Modify main file again",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
},
|
||||
{
|
||||
subScenario: "Add new file and update main file",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(`/src/project/src/newFile.ts`, "function foo() { return 20; }");
|
||||
prependText(fs, `/src/project/src/main.ts`, `/// <reference path="./newFile.ts"/>
|
||||
@@ -281,12 +272,10 @@ const a: string = 10;`, "utf-8"),
|
||||
},
|
||||
{
|
||||
subScenario: "Write file that could not be resolved",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => fs.writeFileSync(`/src/project/src/fileNotFound.ts`, "function something2() { return 20; }"),
|
||||
},
|
||||
{
|
||||
subScenario: "Modify main file",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
},
|
||||
],
|
||||
@@ -334,7 +323,7 @@ declare global {
|
||||
});
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when new file is added to the referenced project",
|
||||
commandLineArgs: ["-i", "-p", `src/projects/project2`],
|
||||
@@ -359,10 +348,9 @@ declare global {
|
||||
}),
|
||||
"/src/projects/project2/class2.ts": `class class2 {}`,
|
||||
}),
|
||||
incrementalScenarios: [
|
||||
edits: [
|
||||
{
|
||||
subScenario: "Add class3 to project1 and build it",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.ts", `class class3 {}`, "utf-8"),
|
||||
cleanBuildDiscrepancies: () => new Map<string, CleanBuildDescrepancy>([
|
||||
// Ts buildinfo will not be updated in incremental build so it will have semantic diagnostics cached from previous build
|
||||
@@ -372,12 +360,10 @@ declare global {
|
||||
},
|
||||
{
|
||||
subScenario: "Add output of class3",
|
||||
buildKind: BuildKind.IncrementalDtsChange,
|
||||
modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"),
|
||||
},
|
||||
{
|
||||
subScenario: "Add excluded file to project1",
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => {
|
||||
fs.mkdirSync("/src/projects/project1/temp");
|
||||
fs.writeFileSync("/src/projects/project1/temp/file.d.ts", `declare class file {}`, "utf-8");
|
||||
@@ -385,7 +371,6 @@ declare global {
|
||||
},
|
||||
{
|
||||
subScenario: "Delete output for class3",
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => fs.unlinkSync("/src/projects/project1/class3.d.ts"),
|
||||
cleanBuildDiscrepancies: () => new Map<string, CleanBuildDescrepancy>([
|
||||
// Ts buildinfo willbe updated but will retain lib file errors from previous build and not others because they are emitted because of change which results in clearing their semantic diagnostics cache
|
||||
@@ -395,14 +380,13 @@ declare global {
|
||||
},
|
||||
{
|
||||
subScenario: "Create output for class3",
|
||||
buildKind: BuildKind.IncrementalDtsUnchanged,
|
||||
modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"),
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "when project has strict true",
|
||||
commandLineArgs: ["-noEmit", "-p", `src/project`],
|
||||
@@ -415,11 +399,11 @@ declare global {
|
||||
}),
|
||||
"/src/project/class1.ts": `export class class1 {}`,
|
||||
}),
|
||||
incrementalScenarios: noChangeOnlyRuns,
|
||||
edits: noChangeOnlyRuns,
|
||||
baselinePrograms: true
|
||||
});
|
||||
|
||||
verifyTscSerializedIncrementalEdits({
|
||||
verifyTscWithEdits({
|
||||
scenario: "incremental",
|
||||
subScenario: "serializing error chains",
|
||||
commandLineArgs: ["-p", `src/project`],
|
||||
@@ -447,7 +431,38 @@ declare global {
|
||||
<div />
|
||||
</Component>)`
|
||||
}, `\ninterface ReadonlyArray<T> { readonly length: number }`),
|
||||
incrementalScenarios: noChangeOnlyRuns,
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "ts file with no-default-lib that augments the global scope",
|
||||
fs: () => loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": Utils.dedent`
|
||||
/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
declare global {
|
||||
interface Test {
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
`,
|
||||
"/src/project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"incremental": true,
|
||||
"outDir": "dist",
|
||||
},
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
|
||||
modifyFs: (fs) => {
|
||||
fs.writeFileSync("/lib/lib.esnext.d.ts", libContent);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,7 +38,11 @@ namespace ts.tscWatch {
|
||||
const files = [file, configFile, libFile];
|
||||
it("using createWatchOfConfigFile ", () => {
|
||||
const baseline = createBaseline(createWatchedSystem(files));
|
||||
const watch = createWatchOfConfigFile(configFile.path, baseline.sys);
|
||||
const watch = createWatchProgram(createWatchCompilerHostOfConfigFileForBaseline({
|
||||
system: baseline.sys,
|
||||
cb: baseline.cb,
|
||||
configFileName: configFile.path,
|
||||
}));
|
||||
// Initially console is cleared if --preserveOutput is not provided since the config file is yet to be parsed
|
||||
runWatchBaseline({
|
||||
scenario,
|
||||
|
||||
@@ -27,200 +27,6 @@ namespace ts.tscWatch {
|
||||
checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles);
|
||||
}
|
||||
|
||||
export function checkProgramRootFiles(program: Program, expectedFiles: readonly string[]) {
|
||||
checkArray(`Program rootFileNames`, program.getRootFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
export type Watch = WatchOfConfigFile<EmitAndSemanticDiagnosticsBuilderProgram> | WatchOfFilesAndCompilerOptions<EmitAndSemanticDiagnosticsBuilderProgram>;
|
||||
|
||||
export function createWatchOfConfigFile(configFileName: string, system: WatchedSystem, optionsToExtend?: CompilerOptions, watchOptionsToExtend?: WatchOptions) {
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile({ configFileName, optionsToExtend, watchOptionsToExtend, system });
|
||||
return createWatchProgram(compilerHost);
|
||||
}
|
||||
|
||||
export function createWatchOfFilesAndCompilerOptions(rootFiles: string[], system: WatchedSystem, options: CompilerOptions = {}, watchOptions?: WatchOptions) {
|
||||
const compilerHost = createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles, options, watchOptions, system });
|
||||
return createWatchProgram(compilerHost);
|
||||
}
|
||||
|
||||
const elapsedRegex = /^Elapsed:: \d+(?:\.\d+)?ms/;
|
||||
const buildVerboseLogRegEx = /^.+ \- /;
|
||||
export enum HostOutputKind {
|
||||
Log,
|
||||
Diagnostic,
|
||||
WatchDiagnostic
|
||||
}
|
||||
|
||||
export interface HostOutputLog {
|
||||
kind: HostOutputKind.Log;
|
||||
expected: string;
|
||||
caption?: string;
|
||||
}
|
||||
|
||||
export interface HostOutputDiagnostic {
|
||||
kind: HostOutputKind.Diagnostic;
|
||||
diagnostic: Diagnostic | string;
|
||||
}
|
||||
|
||||
export interface HostOutputWatchDiagnostic {
|
||||
kind: HostOutputKind.WatchDiagnostic;
|
||||
diagnostic: Diagnostic | string;
|
||||
}
|
||||
|
||||
export type HostOutput = HostOutputLog | HostOutputDiagnostic | HostOutputWatchDiagnostic;
|
||||
|
||||
export function checkOutputErrors(
|
||||
host: WatchedSystem,
|
||||
expected: readonly HostOutput[],
|
||||
disableConsoleClears?: boolean | undefined
|
||||
) {
|
||||
let screenClears = 0;
|
||||
const outputs = host.getOutput();
|
||||
assert.equal(outputs.length, expected.length, JSON.stringify(outputs));
|
||||
let index = 0;
|
||||
forEach(expected, expected => {
|
||||
switch (expected.kind) {
|
||||
case HostOutputKind.Log:
|
||||
return assertLog(expected);
|
||||
case HostOutputKind.Diagnostic:
|
||||
return assertDiagnostic(expected);
|
||||
case HostOutputKind.WatchDiagnostic:
|
||||
return assertWatchDiagnostic(expected);
|
||||
default:
|
||||
return Debug.assertNever(expected);
|
||||
}
|
||||
});
|
||||
assert.equal(host.screenClears.length, screenClears, "Expected number of screen clears");
|
||||
host.clearOutput();
|
||||
|
||||
function isDiagnostic(diagnostic: Diagnostic | string): diagnostic is Diagnostic {
|
||||
return !!(diagnostic as Diagnostic).messageText;
|
||||
}
|
||||
|
||||
function assertDiagnostic({ diagnostic }: HostOutputDiagnostic) {
|
||||
const expected = isDiagnostic(diagnostic) ? formatDiagnostic(diagnostic, host) : diagnostic;
|
||||
assert.equal(outputs[index], expected, getOutputAtFailedMessage("Diagnostic", expected));
|
||||
index++;
|
||||
}
|
||||
|
||||
function getCleanLogString(log: string) {
|
||||
return log.replace(elapsedRegex, "").replace(buildVerboseLogRegEx, "");
|
||||
}
|
||||
|
||||
function assertLog({ caption, expected }: HostOutputLog) {
|
||||
const actual = outputs[index];
|
||||
assert.equal(getCleanLogString(actual), getCleanLogString(expected), getOutputAtFailedMessage(caption || "Log", expected));
|
||||
index++;
|
||||
}
|
||||
|
||||
function assertWatchDiagnostic({ diagnostic }: HostOutputWatchDiagnostic) {
|
||||
if (isString(diagnostic)) {
|
||||
assert.equal(outputs[index], diagnostic, getOutputAtFailedMessage("Diagnostic", diagnostic));
|
||||
}
|
||||
else {
|
||||
const expected = getWatchDiagnosticWithoutDate(diagnostic);
|
||||
if (!disableConsoleClears && contains(screenStartingMessageCodes, diagnostic.code)) {
|
||||
assert.equal(host.screenClears[screenClears], index, `Expected screen clear at this diagnostic: ${expected}`);
|
||||
screenClears++;
|
||||
}
|
||||
assert.isTrue(endsWith(outputs[index], expected), getOutputAtFailedMessage("Watch diagnostic", expected));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
function getOutputAtFailedMessage(caption: string, expectedOutput: string) {
|
||||
return `Expected ${caption}: ${JSON.stringify(expectedOutput)} at ${index} in ${JSON.stringify(outputs)}`;
|
||||
}
|
||||
|
||||
function getWatchDiagnosticWithoutDate(diagnostic: Diagnostic) {
|
||||
const newLines = contains(screenStartingMessageCodes, diagnostic.code)
|
||||
? `${host.newLine}${host.newLine}`
|
||||
: host.newLine;
|
||||
return ` - ${flattenDiagnosticMessageText(diagnostic.messageText, host.newLine)}${newLines}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function hostOutputLog(expected: string, caption?: string): HostOutputLog {
|
||||
return { kind: HostOutputKind.Log, expected, caption };
|
||||
}
|
||||
export function hostOutputDiagnostic(diagnostic: Diagnostic | string): HostOutputDiagnostic {
|
||||
return { kind: HostOutputKind.Diagnostic, diagnostic };
|
||||
}
|
||||
export function hostOutputWatchDiagnostic(diagnostic: Diagnostic | string): HostOutputWatchDiagnostic {
|
||||
return { kind: HostOutputKind.WatchDiagnostic, diagnostic };
|
||||
}
|
||||
|
||||
export function startingCompilationInWatchMode() {
|
||||
return hostOutputWatchDiagnostic(createCompilerDiagnostic(Diagnostics.Starting_compilation_in_watch_mode));
|
||||
}
|
||||
export function foundErrorsWatching(errors: readonly any[]) {
|
||||
return hostOutputWatchDiagnostic(errors.length === 1 ?
|
||||
createCompilerDiagnostic(Diagnostics.Found_1_error_Watching_for_file_changes) :
|
||||
createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errors.length)
|
||||
);
|
||||
}
|
||||
export function fileChangeDetected() {
|
||||
return hostOutputWatchDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation));
|
||||
}
|
||||
|
||||
export function checkOutputErrorsInitial(host: WatchedSystem, errors: readonly Diagnostic[] | readonly string[], disableConsoleClears?: boolean, logsBeforeErrors?: string[]) {
|
||||
checkOutputErrors(
|
||||
host,
|
||||
[
|
||||
startingCompilationInWatchMode(),
|
||||
...map(logsBeforeErrors || emptyArray, expected => hostOutputLog(expected, "logBeforeError")),
|
||||
...map(errors, hostOutputDiagnostic),
|
||||
foundErrorsWatching(errors)
|
||||
],
|
||||
disableConsoleClears
|
||||
);
|
||||
}
|
||||
|
||||
export function checkOutputErrorsIncremental(host: WatchedSystem, errors: readonly Diagnostic[] | readonly string[], disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) {
|
||||
checkOutputErrors(
|
||||
host,
|
||||
[
|
||||
...map(logsBeforeWatchDiagnostic || emptyArray, expected => hostOutputLog(expected, "logsBeforeWatchDiagnostic")),
|
||||
fileChangeDetected(),
|
||||
...map(logsBeforeErrors || emptyArray, expected => hostOutputLog(expected, "logBeforeError")),
|
||||
...map(errors, hostOutputDiagnostic),
|
||||
foundErrorsWatching(errors)
|
||||
],
|
||||
disableConsoleClears
|
||||
);
|
||||
}
|
||||
|
||||
export function checkOutputErrorsIncrementalWithExit(host: WatchedSystem, errors: readonly Diagnostic[] | readonly string[], expectedExitCode: ExitStatus, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) {
|
||||
checkOutputErrors(
|
||||
host,
|
||||
[
|
||||
...map(logsBeforeWatchDiagnostic || emptyArray, expected => hostOutputLog(expected, "logsBeforeWatchDiagnostic")),
|
||||
fileChangeDetected(),
|
||||
...map(logsBeforeErrors || emptyArray, expected => hostOutputLog(expected, "logBeforeError")),
|
||||
...map(errors, hostOutputDiagnostic),
|
||||
],
|
||||
disableConsoleClears
|
||||
);
|
||||
assert.equal(host.exitCode, expectedExitCode);
|
||||
}
|
||||
|
||||
export function checkNormalBuildErrors(
|
||||
host: WatchedSystem,
|
||||
errors: readonly Diagnostic[] | readonly string[],
|
||||
files: readonly ReportFileInError[],
|
||||
reportErrorSummary?: boolean
|
||||
) {
|
||||
checkOutputErrors(
|
||||
host,
|
||||
[
|
||||
...map(errors, hostOutputDiagnostic),
|
||||
...reportErrorSummary ?
|
||||
[hostOutputWatchDiagnostic(getErrorSummaryText(errors.length, files, host.newLine, host))] :
|
||||
emptyArray
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function getDiagnosticMessageChain(message: DiagnosticMessage, args?: (string | number)[], next?: DiagnosticMessageChain[]): DiagnosticMessageChain {
|
||||
let text = getLocaleSpecificMessage(message);
|
||||
if (args?.length) {
|
||||
@@ -293,24 +99,25 @@ namespace ts.tscWatch {
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
}
|
||||
|
||||
export interface TscWatchCompileChange {
|
||||
export type WatchOrSolution<T extends BuilderProgram> = void | SolutionBuilder<T> | WatchOfConfigFile<T> | WatchOfFilesAndCompilerOptions<T>;
|
||||
export interface TscWatchCompileChange<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram> {
|
||||
caption: string;
|
||||
change: (sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles) => void;
|
||||
timeouts: (
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
programs: readonly CommandLineProgram[],
|
||||
watchOrSolution: ReturnType<typeof executeCommandLine>
|
||||
watchOrSolution: WatchOrSolution<T>
|
||||
) => void;
|
||||
}
|
||||
export interface TscWatchCheckOptions {
|
||||
baselineSourceMap?: boolean;
|
||||
baselineDependencies?: boolean;
|
||||
}
|
||||
export interface TscWatchCompileBase extends TscWatchCheckOptions {
|
||||
export interface TscWatchCompileBase<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram> extends TscWatchCheckOptions {
|
||||
scenario: string;
|
||||
subScenario: string;
|
||||
commandLineArgs: readonly string[];
|
||||
changes: readonly TscWatchCompileChange[];
|
||||
changes: readonly TscWatchCompileChange<T>[];
|
||||
}
|
||||
export interface TscWatchCompile extends TscWatchCompileBase {
|
||||
sys: () => WatchedSystem;
|
||||
@@ -355,23 +162,81 @@ namespace ts.tscWatch {
|
||||
});
|
||||
}
|
||||
|
||||
export interface Baseline {
|
||||
export interface BaselineBase {
|
||||
baseline: string[];
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles;
|
||||
oldSnap: SystemSnap;
|
||||
}
|
||||
|
||||
export function createBaseline(system: WatchedSystem): Baseline {
|
||||
const sys = TestFSWithWatch.changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(system)
|
||||
);
|
||||
export interface Baseline extends BaselineBase, CommandLineCallbacks {
|
||||
}
|
||||
|
||||
export function createBaseline(system: WatchedSystem, modifySystem?: (sys: WatchedSystem) => void): Baseline {
|
||||
const initialSys = fakes.patchHostForBuildInfoReadWrite(system);
|
||||
modifySystem?.(initialSys);
|
||||
const sys = TestFSWithWatch.changeToHostTrackingWrittenFiles(initialSys);
|
||||
const baseline: string[] = [];
|
||||
baseline.push("Input::");
|
||||
sys.diff(baseline);
|
||||
return { sys, baseline, oldSnap: sys.snap() };
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
return { sys, baseline, oldSnap: sys.snap(), cb, getPrograms };
|
||||
}
|
||||
|
||||
export function applyChange(sys: Baseline["sys"], baseline: Baseline["baseline"], change: TscWatchCompileChange["change"], caption?: TscWatchCompileChange["caption"]) {
|
||||
export function createSolutionBuilderWithWatchHostForBaseline(sys: WatchedSystem, cb: ExecuteCommandLineCallbacks) {
|
||||
const host = createSolutionBuilderWithWatchHost(sys,
|
||||
/*createProgram*/ undefined,
|
||||
createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
createWatchStatusReporter(sys, /*pretty*/ true)
|
||||
);
|
||||
host.afterProgramEmitAndDiagnostics = cb;
|
||||
host.afterEmitBundle = cb;
|
||||
return host;
|
||||
}
|
||||
|
||||
interface CreateWatchCompilerHostOfConfigFileForBaseline<T extends BuilderProgram> extends CreateWatchCompilerHostOfConfigFileInput<T> {
|
||||
system: WatchedSystem,
|
||||
cb: ExecuteCommandLineCallbacks;
|
||||
}
|
||||
|
||||
export function createWatchCompilerHostOfConfigFileForBaseline<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(
|
||||
input: CreateWatchCompilerHostOfConfigFileForBaseline<T>
|
||||
) {
|
||||
const host = createWatchCompilerHostOfConfigFile({
|
||||
...input,
|
||||
reportDiagnostic: createDiagnosticReporter(input.system, /*pretty*/ true),
|
||||
reportWatchStatus: createWatchStatusReporter(input.system, /*pretty*/ true),
|
||||
});
|
||||
updateWatchHostForBaseline(host, input.cb);
|
||||
return host;
|
||||
}
|
||||
|
||||
interface CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline<T extends BuilderProgram> extends CreateWatchCompilerHostOfFilesAndCompilerOptionsInput<T> {
|
||||
system: WatchedSystem,
|
||||
cb: ExecuteCommandLineCallbacks;
|
||||
}
|
||||
export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>(
|
||||
input: CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline<T>
|
||||
) {
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptions({
|
||||
...input,
|
||||
reportDiagnostic: createDiagnosticReporter(input.system, /*pretty*/ true),
|
||||
reportWatchStatus: createWatchStatusReporter(input.system, /*pretty*/ true),
|
||||
});
|
||||
updateWatchHostForBaseline(host, input.cb);
|
||||
return host;
|
||||
}
|
||||
|
||||
function updateWatchHostForBaseline<T extends BuilderProgram>(host: WatchCompilerHost<T>, cb: ExecuteCommandLineCallbacks) {
|
||||
const emitFilesAndReportErrors = host.afterProgramCreate!;
|
||||
host.afterProgramCreate = builderProgram => {
|
||||
emitFilesAndReportErrors.call(host, builderProgram);
|
||||
cb(builderProgram);
|
||||
};
|
||||
return host;
|
||||
}
|
||||
|
||||
export function applyChange(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], change: TscWatchCompileChange["change"], caption?: TscWatchCompileChange["caption"]) {
|
||||
const oldSnap = sys.snap();
|
||||
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
|
||||
change(sys);
|
||||
@@ -380,17 +245,17 @@ namespace ts.tscWatch {
|
||||
return sys.snap();
|
||||
}
|
||||
|
||||
export interface RunWatchBaseline extends Baseline, TscWatchCompileBase {
|
||||
export interface RunWatchBaseline<T extends BuilderProgram> extends BaselineBase, TscWatchCompileBase<T> {
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles;
|
||||
getPrograms: () => readonly CommandLineProgram[];
|
||||
watchOrSolution: ReturnType<typeof executeCommandLine>;
|
||||
watchOrSolution: WatchOrSolution<T>;
|
||||
}
|
||||
export function runWatchBaseline({
|
||||
export function runWatchBaseline<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>({
|
||||
scenario, subScenario, commandLineArgs,
|
||||
getPrograms, sys, baseline, oldSnap,
|
||||
baselineSourceMap, baselineDependencies,
|
||||
changes, watchOrSolution
|
||||
}: RunWatchBaseline) {
|
||||
}: RunWatchBaseline<T>) {
|
||||
baseline.push(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}`);
|
||||
let programs = watchBaseline({
|
||||
baseline,
|
||||
@@ -415,9 +280,7 @@ namespace ts.tscWatch {
|
||||
baselineDependencies,
|
||||
});
|
||||
}
|
||||
Harness.Baseline.runBaseline(`${isBuild(commandLineArgs) ?
|
||||
isWatch(commandLineArgs) ? "tsbuild/watchMode" : "tsbuild" :
|
||||
isWatch(commandLineArgs) ? "tscWatch" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}.js`, baseline.join("\r\n"));
|
||||
Harness.Baseline.runBaseline(`${isBuild(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch(commandLineArgs) ? "Watch" : ""}/${scenario}/${subScenario.split(" ").join("-")}.js`, baseline.join("\r\n"));
|
||||
}
|
||||
|
||||
function isWatch(commandLineArgs: readonly string[]) {
|
||||
@@ -428,7 +291,7 @@ namespace ts.tscWatch {
|
||||
});
|
||||
}
|
||||
|
||||
export interface WatchBaseline extends Baseline, TscWatchCheckOptions {
|
||||
export interface WatchBaseline extends BaselineBase, TscWatchCheckOptions {
|
||||
oldPrograms: readonly (CommandLineProgram | undefined)[];
|
||||
getPrograms: () => readonly CommandLineProgram[];
|
||||
}
|
||||
|
||||
@@ -28,12 +28,11 @@ namespace ts.tscWatch {
|
||||
{ subScenario, files, optionsToExtend, modifyFs }: VerifyIncrementalWatchEmitInput,
|
||||
incremental: boolean
|
||||
) {
|
||||
const { sys, baseline, oldSnap } = createBaseline(createWatchedSystem(files(), { currentDirectory: project }));
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project }));
|
||||
if (incremental) sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || emptyArray)];
|
||||
baseline.push(`${sys.getExecutingFilePath()} ${argsToPass.join(" ")}`);
|
||||
let oldPrograms: readonly CommandLineProgram[] = emptyArray;
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
build(oldSnap);
|
||||
|
||||
if (modifyFs) {
|
||||
|
||||
@@ -511,7 +511,7 @@ export class A {
|
||||
}]
|
||||
});
|
||||
|
||||
it("correctly migrate files between projects", () => {
|
||||
it("two watch programs are not affected by each other", () => {
|
||||
const file1 = {
|
||||
path: "/a/b/f1.ts",
|
||||
content: `
|
||||
@@ -526,16 +526,46 @@ export class A {
|
||||
path: "/a/d/f3.ts",
|
||||
content: "export let y = 1;"
|
||||
};
|
||||
const host = createWatchedSystem([file1, file2, file3]);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file2.path, file3.path], host);
|
||||
checkProgramActualFiles(watch.getCurrentProgram().getProgram(), [file2.path, file3.path]);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, file1, file2, file3]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [file2.path, file3.path],
|
||||
system: sys,
|
||||
options: { allowNonTsExtensions: true },
|
||||
cb,
|
||||
watchOptions: undefined
|
||||
});
|
||||
createWatchProgram(host);
|
||||
baseline.push(`${sys.getExecutingFilePath()} --w ${file2.path} ${file3.path}`);
|
||||
watchBaseline({
|
||||
baseline,
|
||||
getPrograms,
|
||||
oldPrograms: emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
|
||||
const watch2 = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
checkProgramActualFiles(watch2.getCurrentProgram().getProgram(), [file1.path, file2.path, file3.path]);
|
||||
const {cb: cb2, getPrograms: getPrograms2 } = commandLineCallbacks(sys);
|
||||
const oldSnap2 = sys.snap();
|
||||
baseline.push("createing separate watcher");
|
||||
createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles:[file1.path],
|
||||
system: sys,
|
||||
options: { allowNonTsExtensions: true },
|
||||
cb: cb2,
|
||||
watchOptions: undefined
|
||||
}));
|
||||
watchBaseline({
|
||||
baseline,
|
||||
getPrograms: getPrograms2,
|
||||
oldPrograms: emptyArray,
|
||||
sys,
|
||||
oldSnap: oldSnap2,
|
||||
});
|
||||
|
||||
// Previous program shouldnt be updated
|
||||
checkProgramActualFiles(watch.getCurrentProgram().getProgram(), [file2.path, file3.path]);
|
||||
host.checkTimeoutQueueLength(0);
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
baseline.push(`First program is not updated:: ${getPrograms() === emptyArray}`);
|
||||
baseline.push(`Second program is not updated:: ${getPrograms2() === emptyArray}`);
|
||||
Harness.Baseline.runBaseline(`tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, baseline.join("\r\n"));
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
@@ -1025,9 +1055,25 @@ declare const eval: any`
|
||||
path: "/a/compile",
|
||||
content: "let x = 1"
|
||||
};
|
||||
const host = createWatchedSystem([f, libFile]);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([f.path], host, { allowNonTsExtensions: true });
|
||||
checkProgramActualFiles(watch.getCurrentProgram().getProgram(), [f.path, libFile.path]);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([f, libFile]));
|
||||
const watch = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [f.path],
|
||||
system: sys,
|
||||
options: { allowNonTsExtensions: true },
|
||||
cb,
|
||||
watchOptions: undefined
|
||||
}));
|
||||
runWatchBaseline({
|
||||
scenario,
|
||||
subScenario: "should support files without extensions",
|
||||
commandLineArgs: ["--w", f.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: emptyArray,
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace ts.tscWatch {
|
||||
describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution caching", () => {
|
||||
const scenario = "resolutionCache";
|
||||
it("works", () => {
|
||||
it("caching works", () => {
|
||||
const root = {
|
||||
path: "/a/d/f0.ts",
|
||||
content: `import {x} from "f1"`
|
||||
@@ -11,80 +11,76 @@ namespace ts.tscWatch {
|
||||
content: `foo()`
|
||||
};
|
||||
|
||||
const files = [root, imported, libFile];
|
||||
const host = createWatchedSystem(files);
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
|
||||
|
||||
const f1IsNotModule = getDiagnosticOfFileFromProgram(watch.getCurrentProgram().getProgram(), root.path, root.content.indexOf('"f1"'), '"f1"'.length, Diagnostics.File_0_is_not_a_module, imported.path);
|
||||
const cannotFindFoo = getDiagnosticOfFileFromProgram(watch.getCurrentProgram().getProgram(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo");
|
||||
|
||||
// ensure that imported file was found
|
||||
checkOutputErrorsInitial(host, [f1IsNotModule, cannotFindFoo]);
|
||||
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
options: { module: ModuleKind.AMD },
|
||||
cb,
|
||||
watchOptions: undefined
|
||||
});
|
||||
const originalFileExists = host.fileExists;
|
||||
{
|
||||
const newContent = `import {x} from "f1"
|
||||
var x: string = 1;`;
|
||||
root.content = newContent;
|
||||
host.writeFile(root.path, root.content);
|
||||
|
||||
// patch fileExists to make sure that disk is not touched
|
||||
host.fileExists = notImplemented;
|
||||
|
||||
// trigger synchronization to make sure that import will be fetched from the cache
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// ensure file has correct number of errors after edit
|
||||
checkOutputErrorsIncremental(host, [
|
||||
f1IsNotModule,
|
||||
getDiagnosticOfFileFromProgram(watch.getCurrentProgram().getProgram(), root.path, newContent.indexOf("var x") + "var ".length, "x".length, Diagnostics.Type_0_is_not_assignable_to_type_1, "number", "string"),
|
||||
cannotFindFoo
|
||||
]);
|
||||
}
|
||||
{
|
||||
let fileExistsIsCalled = false;
|
||||
host.fileExists = (fileName): boolean => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
return false;
|
||||
}
|
||||
fileExistsIsCalled = true;
|
||||
assert.isTrue(fileName.indexOf("/f2.") !== -1);
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
|
||||
root.content = `import {x} from "f2"`;
|
||||
host.writeFile(root.path, root.content);
|
||||
|
||||
// trigger synchronization to make sure that system will try to find 'f2' module on disk
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// ensure file has correct number of errors after edit
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch.getCurrentProgram().getProgram(), root, "f2")
|
||||
]);
|
||||
|
||||
assert.isTrue(fileExistsIsCalled);
|
||||
}
|
||||
{
|
||||
let fileExistsCalled = false;
|
||||
host.fileExists = (fileName): boolean => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
return false;
|
||||
}
|
||||
fileExistsCalled = true;
|
||||
assert.isTrue(fileName.indexOf("/f1.") !== -1);
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
|
||||
const newContent = `import {x} from "f1"`;
|
||||
root.content = newContent;
|
||||
|
||||
host.writeFile(root.path, root.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
checkOutputErrorsIncremental(host, [f1IsNotModule, cannotFindFoo]);
|
||||
assert.isTrue(fileExistsCalled);
|
||||
}
|
||||
const watch = createWatchProgram(host);
|
||||
let fileExistsIsCalled = false;
|
||||
runWatchBaseline({
|
||||
scenario: "resolutionCache",
|
||||
subScenario: "caching works",
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [
|
||||
{
|
||||
caption: "Adding text doesnt re-resole the imports",
|
||||
change: sys => {
|
||||
// patch fileExists to make sure that disk is not touched
|
||||
host.fileExists = notImplemented;
|
||||
sys.writeFile(root.path, `import {x} from "f1"
|
||||
var x: string = 1;`);
|
||||
},
|
||||
timeouts: runQueuedTimeoutCallbacks
|
||||
},
|
||||
{
|
||||
caption: "Resolves f2",
|
||||
change: sys => {
|
||||
host.fileExists = (fileName): boolean => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
return false;
|
||||
}
|
||||
fileExistsIsCalled = true;
|
||||
assert.isTrue(fileName.indexOf("/f2.") !== -1);
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
sys.writeFile(root.path, `import {x} from "f2"`);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsIsCalled);
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "Resolve f1",
|
||||
change: sys => {
|
||||
fileExistsIsCalled = false;
|
||||
host.fileExists = (fileName): boolean => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
return false;
|
||||
}
|
||||
fileExistsIsCalled = true;
|
||||
assert.isTrue(fileName.indexOf("/f1.") !== -1);
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
sys.writeFile(root.path, `import {x} from "f1"`);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsIsCalled);
|
||||
}
|
||||
},
|
||||
],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
|
||||
it("loads missing files from disk", () => {
|
||||
@@ -98,10 +94,15 @@ namespace ts.tscWatch {
|
||||
content: `export const y = 1;`
|
||||
};
|
||||
|
||||
const files = [root, libFile];
|
||||
const host = createWatchedSystem(files);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
options: { module: ModuleKind.AMD },
|
||||
cb,
|
||||
watchOptions: undefined
|
||||
});
|
||||
const originalFileExists = host.fileExists;
|
||||
|
||||
let fileExistsCalledForBar = false;
|
||||
host.fileExists = fileName => {
|
||||
if (fileName === "lib.d.ts") {
|
||||
@@ -114,21 +115,30 @@ namespace ts.tscWatch {
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
|
||||
|
||||
const watch = createWatchProgram(host);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
|
||||
checkOutputErrorsInitial(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch.getCurrentProgram().getProgram(), root, "bar")
|
||||
]);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
root.content = `import {y} from "bar"`;
|
||||
host.writeFile(root.path, root.content);
|
||||
host.writeFile(imported.path, imported.content);
|
||||
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
runWatchBaseline({
|
||||
scenario: "resolutionCache",
|
||||
subScenario: "loads missing files from disk",
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [{
|
||||
caption: "write imported file",
|
||||
change: sys => {
|
||||
fileExistsCalledForBar = false;
|
||||
sys.writeFile(root.path,`import {y} from "bar"`);
|
||||
sys.writeFile(imported.path, imported.content);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
}
|
||||
}],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
|
||||
it("should compile correctly when resolved module goes missing and then comes back (module is not part of the root)", () => {
|
||||
@@ -142,7 +152,14 @@ namespace ts.tscWatch {
|
||||
content: `export const y = 1;export const x = 10;`
|
||||
};
|
||||
|
||||
const host = createWatchedSystem([root, libFile, imported]);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
options: { module: ModuleKind.AMD },
|
||||
cb,
|
||||
watchOptions: undefined
|
||||
});
|
||||
const originalFileExists = host.fileExists;
|
||||
let fileExistsCalledForBar = false;
|
||||
host.fileExists = fileName => {
|
||||
@@ -154,26 +171,43 @@ namespace ts.tscWatch {
|
||||
}
|
||||
return originalFileExists.call(host, fileName);
|
||||
};
|
||||
|
||||
const watch = createWatchOfFilesAndCompilerOptions([root.path], host, { module: ModuleKind.AMD });
|
||||
|
||||
const watch = createWatchProgram(host);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
|
||||
checkOutputErrorsInitial(host, emptyArray);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
host.deleteFile(imported.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
checkOutputErrorsIncremental(host, [
|
||||
getDiagnosticModuleNotFoundOfFile(watch.getCurrentProgram().getProgram(), root, "bar")
|
||||
]);
|
||||
|
||||
fileExistsCalledForBar = false;
|
||||
host.writeFile(imported.path, imported.content);
|
||||
host.checkTimeoutQueueLengthAndRun(1); // Scheduled invalidation of resolutions
|
||||
host.checkTimeoutQueueLengthAndRun(1); // Actual update
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
runWatchBaseline({
|
||||
scenario: "resolutionCache",
|
||||
subScenario: "should compile correctly when resolved module goes missing and then comes back",
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [
|
||||
{
|
||||
caption: "Delete imported file",
|
||||
change: sys => {
|
||||
fileExistsCalledForBar = false;
|
||||
sys.deleteFile(imported.path);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "Create imported file",
|
||||
change: sys => {
|
||||
fileExistsCalledForBar = false;
|
||||
sys.writeFile(imported.path, imported.content);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // Scheduled invalidation of resolutions
|
||||
sys.checkTimeoutQueueLengthAndRun(1); // Actual update
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
|
||||
},
|
||||
},
|
||||
],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
@@ -402,7 +436,7 @@ declare namespace myapp {
|
||||
change: noop,
|
||||
timeouts: (sys, [[oldProgram, oldBuilderProgram]], watchorSolution) => {
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
const newProgram = (watchorSolution as Watch).getProgram();
|
||||
const newProgram = (watchorSolution as WatchOfConfigFile<EmitAndSemanticDiagnosticsBuilderProgram>).getProgram();
|
||||
assert.strictEqual(newProgram, oldBuilderProgram, "No change so builder program should be same");
|
||||
assert.strictEqual(newProgram.getProgram(), oldProgram, "No change so program should be same");
|
||||
}
|
||||
|
||||
@@ -4,26 +4,37 @@ namespace ts.tscWatch {
|
||||
interface VerifyWatchInput {
|
||||
files: readonly TestFSWithWatch.FileOrFolderOrSymLink[];
|
||||
config: string;
|
||||
expectedProgramFiles: readonly string[];
|
||||
subScenario: string;
|
||||
}
|
||||
function verifyWatch(
|
||||
{ files, config, expectedProgramFiles }: VerifyWatchInput,
|
||||
alreadyBuilt: boolean
|
||||
) {
|
||||
const sys = createWatchedSystem(files);
|
||||
if (alreadyBuilt) {
|
||||
const solutionBuilder = createSolutionBuilder(sys, [config], {});
|
||||
solutionBuilder.build();
|
||||
solutionBuilder.close();
|
||||
sys.clearOutput();
|
||||
}
|
||||
const host = createWatchCompilerHostOfConfigFile({
|
||||
|
||||
function verifyWatch({ files, config, subScenario }: VerifyWatchInput, alreadyBuilt: boolean) {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
|
||||
createWatchedSystem(files),
|
||||
alreadyBuilt ? sys => {
|
||||
const solutionBuilder = createSolutionBuilder(sys, [config], {});
|
||||
solutionBuilder.build();
|
||||
solutionBuilder.close();
|
||||
sys.clearOutput();
|
||||
} : undefined
|
||||
);
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config,
|
||||
system: sys
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
host.useSourceOfProjectReferenceRedirect = returnTrue;
|
||||
const watch = createWatchProgram(host);
|
||||
checkProgramActualFiles(watch.getCurrentProgram().getProgram(), expectedProgramFiles);
|
||||
runWatchBaseline({
|
||||
scenario: "sourceOfProjectReferenceRedirect",
|
||||
subScenario: `${subScenario}${alreadyBuilt ? " when solution is already built" : ""}`,
|
||||
commandLineArgs: ["--w", "--p", config],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: emptyArray,
|
||||
watchOrSolution: watch
|
||||
});
|
||||
}
|
||||
|
||||
function verifyScenario(input: () => VerifyWatchInput) {
|
||||
@@ -48,7 +59,7 @@ namespace ts.tscWatch {
|
||||
return {
|
||||
files: [{ path: libFile.path, content: libContent }, baseConfig, coreTs, coreConfig, animalTs, dogTs, indexTs, animalsConfig],
|
||||
config: animalsConfig.path,
|
||||
expectedProgramFiles: [libFile.path, indexTs.path, dogTs.path, animalTs.path, coreTs.path]
|
||||
subScenario: "with simple project"
|
||||
};
|
||||
});
|
||||
});
|
||||
@@ -60,6 +71,7 @@ namespace ts.tscWatch {
|
||||
bFoo: File;
|
||||
bBar: File;
|
||||
bSymlink: SymLink;
|
||||
subScenario: string;
|
||||
}
|
||||
function verifySymlinkScenario(packages: () => Packages) {
|
||||
describe("when preserveSymlinks is turned off", () => {
|
||||
@@ -72,13 +84,13 @@ namespace ts.tscWatch {
|
||||
|
||||
function verifySymlinkScenarioWorker(packages: () => Packages, extraOptions: CompilerOptions) {
|
||||
verifyScenario(() => {
|
||||
const { bPackageJson, aTest, bFoo, bBar, bSymlink } = packages();
|
||||
const { bPackageJson, aTest, bFoo, bBar, bSymlink, subScenario } = packages();
|
||||
const aConfig = config("A", extraOptions, ["../B"]);
|
||||
const bConfig = config("B", extraOptions);
|
||||
return {
|
||||
files: [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink],
|
||||
config: aConfig.path,
|
||||
expectedProgramFiles: [libFile.path, aTest.path, bFoo.path, bBar.path]
|
||||
subScenario: `${subScenario}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}`
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -126,7 +138,8 @@ bar();
|
||||
bSymlink: {
|
||||
path: `${projectRoot}/node_modules/${scope}b`,
|
||||
symLink: `${projectRoot}/packages/B`
|
||||
}
|
||||
},
|
||||
subScenario: `when packageJson has types field${scope ? " with scoped package" : ""}`
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -146,7 +159,8 @@ bar();
|
||||
bSymlink: {
|
||||
path: `${projectRoot}/node_modules/${scope}b`,
|
||||
symLink: `${projectRoot}/packages/B`
|
||||
}
|
||||
},
|
||||
subScenario: `when referencing file from subFolder${scope ? " with scoped package" : ""}`
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,15 +18,18 @@ namespace ts.tscWatch {
|
||||
};
|
||||
|
||||
it("verify that module resolution with json extension works when returned without extension", () => {
|
||||
const files = [libFile, mainFile, config, settingsJson];
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile({
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
[libFile, mainFile, config, settingsJson],
|
||||
{ currentDirectory: projectRoot }),
|
||||
);
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
system: host
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
const parsedCommandResult = parseJsonConfigFileContent(configFileJson, host, config.path);
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile) => moduleNames.map(m => {
|
||||
const result = resolveModuleName(m, containingFile, parsedCommandResult.options, compilerHost);
|
||||
const parsedCommandResult = parseJsonConfigFileContent(configFileJson, sys, config.path);
|
||||
host.resolveModuleNames = (moduleNames, containingFile) => moduleNames.map(m => {
|
||||
const result = resolveModuleName(m, containingFile, parsedCommandResult.options, host);
|
||||
const resolvedModule = result.resolvedModule!;
|
||||
return {
|
||||
resolvedFileName: resolvedModule.resolvedFileName,
|
||||
@@ -34,40 +37,62 @@ namespace ts.tscWatch {
|
||||
originalFileName: resolvedModule.originalPath,
|
||||
};
|
||||
});
|
||||
const watch = createWatchProgram(compilerHost);
|
||||
const program = watch.getCurrentProgram().getProgram();
|
||||
checkProgramActualFiles(program, [mainFile.path, libFile.path, settingsJson.path]);
|
||||
const watch = createWatchProgram(host);
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario: "verify that module resolution with json extension works when returned without extension",
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: emptyArray,
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to watch status reporter", () => {
|
||||
const configFileJson: any = {
|
||||
compilerOptions: { module: "commonjs" },
|
||||
files: ["index.ts"]
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify(configFileJson)
|
||||
};
|
||||
const mainFile: File = {
|
||||
path: `${projectRoot}/index.ts`,
|
||||
content: "let compiler = new Compiler(); for (let i = 0; j < 5; i++) {}"
|
||||
};
|
||||
|
||||
it("verify that the error count is correctly passed down to the watch status reporter", () => {
|
||||
const files = [libFile, mainFile, config];
|
||||
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { module: "commonjs" },
|
||||
files: ["index.ts"]
|
||||
})
|
||||
};
|
||||
const mainFile: File = {
|
||||
path: `${projectRoot}/index.ts`,
|
||||
content: "let compiler = new Compiler(); for (let i = 0; j < 5; i++) {}"
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
[libFile, mainFile, config],
|
||||
{ currentDirectory: projectRoot }),
|
||||
);
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
const existing = host.onWatchStatusChange!;
|
||||
let watchedErrorCount;
|
||||
const reportWatchStatus: WatchStatusReporter = (_, __, ___, errorCount) => {
|
||||
host.onWatchStatusChange = (diagnostic, newLine, options, errorCount) => {
|
||||
existing.call(host, diagnostic, newLine, options, errorCount);
|
||||
watchedErrorCount = errorCount;
|
||||
};
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile({
|
||||
configFileName: config.path,
|
||||
system: host,
|
||||
reportWatchStatus
|
||||
});
|
||||
createWatchProgram(compilerHost);
|
||||
const watch = createWatchProgram(host);
|
||||
assert.equal(watchedErrorCount, 2, "The error count was expected to be 2 for the file change");
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario: "verify that the error count is correctly passed down to the watch status reporter",
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: emptyArray,
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,16 +106,33 @@ namespace ts.tscWatch {
|
||||
path: `${projectRoot}/main.ts`,
|
||||
content: "const x = 10;"
|
||||
};
|
||||
const sys = createWatchedSystem([config, mainFile, libFile]);
|
||||
const watchCompilerHost = createWatchCompilerHost(config.path, {}, sys);
|
||||
watchCompilerHost.setTimeout = undefined;
|
||||
watchCompilerHost.clearTimeout = undefined;
|
||||
const watch = createWatchProgram(watchCompilerHost);
|
||||
checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, libFile.path]);
|
||||
// Write new file
|
||||
const barPath = `${projectRoot}/bar.ts`;
|
||||
sys.writeFile(barPath, "const y =10;");
|
||||
checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, barPath, libFile.path]);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile]));
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
host.setTimeout = undefined;
|
||||
host.clearTimeout = undefined;
|
||||
const watch = createWatchProgram(host);
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario: "without timesouts on host program gets updated",
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [{
|
||||
caption: "Write a file",
|
||||
change: sys => sys.writeFile(`${projectRoot}/bar.ts`, "const y =10;"),
|
||||
timeouts: sys => {
|
||||
sys.checkTimeoutQueueLength(0);
|
||||
watch.getProgram();
|
||||
}
|
||||
}],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,139 +150,230 @@ namespace ts.tscWatch {
|
||||
path: `${projectRoot}/other.vue`,
|
||||
content: ""
|
||||
};
|
||||
const sys = createWatchedSystem([config, mainFile, otherFile, libFile]);
|
||||
const watchCompilerHost = createWatchCompilerHost(
|
||||
config.path,
|
||||
{ allowNonTsExtensions: true },
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
/*reportDiagnostics*/ undefined,
|
||||
/*reportWatchStatus*/ undefined,
|
||||
/*watchOptionsToExtend*/ undefined,
|
||||
[{ extension: ".vue", isMixedContent: true, scriptKind: ScriptKind.Deferred }]
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
|
||||
createWatchedSystem([config, mainFile, otherFile, libFile])
|
||||
);
|
||||
const watch = createWatchProgram(watchCompilerHost);
|
||||
checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]);
|
||||
|
||||
const other2 = `${projectRoot}/other2.vue`;
|
||||
sys.writeFile(other2, otherFile.content);
|
||||
checkSingleTimeoutQueueLengthAndRun(sys);
|
||||
checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path, other2]);
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
optionsToExtend: { allowNonTsExtensions: true },
|
||||
extraFileExtensions: [{ extension: ".vue", isMixedContent: true, scriptKind: ScriptKind.Deferred }],
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
const watch = createWatchProgram(host);
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario: "extraFileExtensions are supported",
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [{
|
||||
caption: "Write a file",
|
||||
change: sys => sys.writeFile(`${projectRoot}/other2.vue`, otherFile.content),
|
||||
timeouts: checkSingleTimeoutQueueLengthAndRun,
|
||||
}],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram", () => {
|
||||
function getWatch<T extends BuilderProgram>(config: File, optionsToExtend: CompilerOptions | undefined, sys: System, createProgram: CreateProgram<T>) {
|
||||
const watchCompilerHost = createWatchCompilerHost(config.path, optionsToExtend, sys, createProgram);
|
||||
return createWatchProgram(watchCompilerHost);
|
||||
}
|
||||
|
||||
function setup<T extends BuilderProgram>(createProgram: CreateProgram<T>, configText: string) {
|
||||
function createSystem(configText: string, mainText: string) {
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: configText
|
||||
};
|
||||
const mainFile: File = {
|
||||
path: `${projectRoot}/main.ts`,
|
||||
content: "export const x = 10;"
|
||||
content: mainText
|
||||
};
|
||||
const otherFile: File = {
|
||||
path: `${projectRoot}/other.ts`,
|
||||
content: "export const y = 10;"
|
||||
};
|
||||
const sys = createWatchedSystem([config, mainFile, otherFile, libFile]);
|
||||
const watch = getWatch(config, { noEmit: true }, sys, createProgram);
|
||||
return { sys, watch, mainFile, otherFile, config };
|
||||
return {
|
||||
...createBaseline(createWatchedSystem([config, mainFile, otherFile, libFile])),
|
||||
config,
|
||||
mainFile,
|
||||
otherFile,
|
||||
};
|
||||
}
|
||||
|
||||
function verifyOutputs(sys: System, emitSys: System) {
|
||||
for (const output of [`${projectRoot}/main.js`, `${projectRoot}/main.d.ts`, `${projectRoot}/other.js`, `${projectRoot}/other.d.ts`, `${projectRoot}/tsconfig.tsbuildinfo`]) {
|
||||
assert.strictEqual(sys.readFile(output), emitSys.readFile(output), `Output file text for ${output}`);
|
||||
}
|
||||
}
|
||||
|
||||
function verifyBuilder<T extends BuilderProgram, U extends BuilderProgram>(config: File, sys: System, emitSys: System, createProgram: CreateProgram<T>, createEmitProgram: CreateProgram<U>, optionsToExtend?: CompilerOptions) {
|
||||
const watch = getWatch(config, /*optionsToExtend*/ optionsToExtend, sys, createProgram);
|
||||
const emitWatch = getWatch(config, /*optionsToExtend*/ optionsToExtend, emitSys, createEmitProgram);
|
||||
verifyOutputs(sys, emitSys);
|
||||
function createWatch<T extends BuilderProgram>(
|
||||
baseline: string[],
|
||||
config: File,
|
||||
optionsToExtend: CompilerOptions | undefined,
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
createProgram: CreateProgram<T>
|
||||
) {
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
baseline.push(`tsc --w${optionsToExtend?.noEmit ? " --noEmit" : ""}`);
|
||||
const oldSnap = sys.snap();
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline<T>({
|
||||
configFileName: config.path,
|
||||
optionsToExtend,
|
||||
createProgram,
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
const watch = createWatchProgram(host);
|
||||
watchBaseline({
|
||||
baseline,
|
||||
getPrograms,
|
||||
oldPrograms: emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
watch.close();
|
||||
emitWatch.close();
|
||||
}
|
||||
|
||||
function verifyOutputs(baseline: string[], sys: System, emitSys: System) {
|
||||
baseline.push("Checking if output is same as EmitAndSemanticDiagnosticsBuilderProgram::");
|
||||
for (const output of [`${projectRoot}/main.js`, `${projectRoot}/main.d.ts`, `${projectRoot}/other.js`, `${projectRoot}/other.d.ts`, `${projectRoot}/tsconfig.tsbuildinfo`]) {
|
||||
baseline.push(`Output file text for ${output} is same:: ${sys.readFile(output) === emitSys.readFile(output)}`);
|
||||
}
|
||||
baseline.push("");
|
||||
}
|
||||
|
||||
function createSystemForBuilderTest(configText: string, mainText: string) {
|
||||
const result = createSystem(configText, mainText);
|
||||
const { sys: emitSys, baseline: emitBaseline } = createSystem(configText, mainText);
|
||||
return { ...result, emitSys, emitBaseline };
|
||||
}
|
||||
|
||||
function applyChangeForBuilderTest(
|
||||
baseline: string[],
|
||||
emitBaseline: string[],
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
emitSys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
change: (sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles) => void,
|
||||
caption: string
|
||||
) {
|
||||
// Change file
|
||||
applyChange(sys, baseline, change, caption);
|
||||
applyChange(emitSys, emitBaseline, change, caption);
|
||||
}
|
||||
|
||||
function verifyBuilder<T extends BuilderProgram>(
|
||||
baseline: string[],
|
||||
emitBaseline: string[],
|
||||
config: File,
|
||||
sys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
emitSys: TestFSWithWatch.TestServerHostTrackingWrittenFiles,
|
||||
createProgram: CreateProgram<T>,
|
||||
optionsToExtend?: CompilerOptions) {
|
||||
createWatch(baseline, config, optionsToExtend, sys, createProgram);
|
||||
createWatch(emitBaseline, config, optionsToExtend, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
verifyOutputs(baseline, sys, emitSys);
|
||||
}
|
||||
|
||||
it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => {
|
||||
const { sys, watch, mainFile, otherFile } = setup(createSemanticDiagnosticsBuilderProgram, "{}");
|
||||
checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]);
|
||||
sys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
const program = watch.getProgram().getProgram();
|
||||
assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(mainFile.path)), []);
|
||||
// Should not retrieve diagnostics for other file thats not changed
|
||||
assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(otherFile.path)), /*expected*/ undefined);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;");
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
optionsToExtend: { noEmit: true },
|
||||
createProgram: createSemanticDiagnosticsBuilderProgram,
|
||||
system: sys,
|
||||
cb,
|
||||
});
|
||||
const watch = createWatchProgram(host);
|
||||
runWatchBaseline({
|
||||
scenario: "watchApi",
|
||||
subScenario: "verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram",
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
changes: [{
|
||||
caption: "Modify a file",
|
||||
change: sys => sys.appendFile(mainFile.path, "\n// SomeComment"),
|
||||
timeouts: runQueuedTimeoutCallbacks,
|
||||
}],
|
||||
watchOrSolution: watch
|
||||
});
|
||||
});
|
||||
|
||||
it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
const configText = JSON.stringify({ compilerOptions: { composite: true } });
|
||||
const { sys, watch, config, mainFile } = setup(createSemanticDiagnosticsBuilderProgram, configText);
|
||||
const { sys: emitSys, watch: emitWatch } = setup(createEmitAndSemanticDiagnosticsBuilderProgram, configText);
|
||||
verifyOutputs(sys, emitSys);
|
||||
describe("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
let baseline: string[];
|
||||
let emitBaseline: string[];
|
||||
before(() => {
|
||||
const configText = JSON.stringify({ compilerOptions: { composite: true } });
|
||||
const mainText = "export const x = 10;";
|
||||
const result = createSystemForBuilderTest(configText, mainText);
|
||||
baseline = result.baseline;
|
||||
emitBaseline = result.emitBaseline;
|
||||
const { sys, config, mainFile, emitSys } = result;
|
||||
|
||||
watch.close();
|
||||
emitWatch.close();
|
||||
// No Emit
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true });
|
||||
|
||||
// Emit on both sys should result in same output
|
||||
verifyBuilder(config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
// Emit on both sys should result in same output
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
|
||||
// Change file
|
||||
sys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
emitSys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
// Change file
|
||||
applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
|
||||
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true });
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, { noEmit: true });
|
||||
|
||||
// Emit on both sys should result in same output
|
||||
verifyBuilder(config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
// Emit on both sys should result in same output
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
|
||||
// Change file
|
||||
sys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
emitSys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
// Change file
|
||||
applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
|
||||
|
||||
// Emit on both the builders should result in same files
|
||||
verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram);
|
||||
// Emit on both the builders should result in same files
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
|
||||
});
|
||||
after(() => {
|
||||
baseline = undefined!;
|
||||
emitBaseline = undefined!;
|
||||
});
|
||||
it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, baseline.join("\r\n"));
|
||||
});
|
||||
it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n"));
|
||||
});
|
||||
});
|
||||
|
||||
it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: { composite: true } })
|
||||
};
|
||||
const mainFile: File = {
|
||||
path: `${projectRoot}/main.ts`,
|
||||
content: "export const x: string = 10;"
|
||||
};
|
||||
const otherFile: File = {
|
||||
path: `${projectRoot}/other.ts`,
|
||||
content: "export const y = 10;"
|
||||
};
|
||||
const sys = createWatchedSystem([config, mainFile, otherFile, libFile]);
|
||||
const emitSys = createWatchedSystem([config, mainFile, otherFile, libFile]);
|
||||
describe("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
let baseline: string[];
|
||||
let emitBaseline: string[];
|
||||
before(() => {
|
||||
const configText = JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } });
|
||||
const mainText = "export const x: string = 10;";
|
||||
const result = createSystemForBuilderTest(configText, mainText);
|
||||
baseline = result.baseline;
|
||||
emitBaseline = result.emitBaseline;
|
||||
const { sys, config, mainFile, emitSys } = result;
|
||||
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true });
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
|
||||
|
||||
// Change file
|
||||
sys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
emitSys.appendFile(mainFile.path, "\n// SomeComment");
|
||||
// Change file
|
||||
applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment");
|
||||
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true });
|
||||
// Verify noEmit results in same output
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
|
||||
|
||||
// Fix error
|
||||
const fixed = "export const x = 10;";
|
||||
sys.appendFile(mainFile.path, fixed);
|
||||
emitSys.appendFile(mainFile.path, fixed);
|
||||
// Fix error
|
||||
const fixed = "export const x = 10;";
|
||||
applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.writeFile(mainFile.path, fixed), "Fix error");
|
||||
|
||||
// Emit on both the builders should result in same files
|
||||
verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true });
|
||||
// Emit on both the builders should result in same files
|
||||
verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram);
|
||||
});
|
||||
|
||||
it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, baseline.join("\r\n"));
|
||||
});
|
||||
it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => {
|
||||
Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -282,9 +415,10 @@ namespace ts.tscWatch {
|
||||
};
|
||||
const system = createWatchedSystem([config1, class1, class1Dts, config2, class2, libFile]);
|
||||
const baseline = createBaseline(system);
|
||||
const compilerHost = createWatchCompilerHostOfConfigFile({
|
||||
configFileName: config2.path,
|
||||
const compilerHost = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
cb: baseline.cb,
|
||||
system,
|
||||
configFileName: config2.path,
|
||||
optionsToExtend: { extendedDiagnostics: true }
|
||||
});
|
||||
compilerHost.useSourceOfProjectReferenceRedirect = useSourceOfProjectReferenceRedirect;
|
||||
@@ -312,7 +446,6 @@ namespace ts.tscWatch {
|
||||
subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine",
|
||||
commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"],
|
||||
...baseline,
|
||||
getPrograms: () => [[watch.getCurrentProgram().getProgram(), watch.getCurrentProgram()]],
|
||||
changes: [
|
||||
{
|
||||
caption: "Add class3 to project1",
|
||||
@@ -344,7 +477,6 @@ namespace ts.tscWatch {
|
||||
subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect",
|
||||
commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"],
|
||||
...baseline,
|
||||
getPrograms: () => [[watch.getCurrentProgram().getProgram(), watch.getCurrentProgram()]],
|
||||
changes: [
|
||||
{
|
||||
caption: "Add class3 to project1",
|
||||
|
||||
@@ -13,15 +13,20 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
interface MakeReferenceEntry extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
isDefinition?: boolean;
|
||||
isWriteAccess?: boolean;
|
||||
}
|
||||
function makeReferenceEntry({ isDefinition, ...rest }: MakeReferenceEntry): ReferenceEntry {
|
||||
return {
|
||||
function makeReferencedSymbolEntry({ isDefinition, isWriteAccess, ...rest }: MakeReferenceEntry): ReferencedSymbolEntry {
|
||||
const result = {
|
||||
...documentSpanFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
isWriteAccess: !!isWriteAccess,
|
||||
isInString: undefined,
|
||||
};
|
||||
if (isDefinition === undefined) {
|
||||
delete result.isDefinition;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function checkDeclarationFiles(file: File, session: TestSession, expectedFiles: readonly File[]): void {
|
||||
@@ -373,17 +378,18 @@ namespace ts.projectSystem {
|
||||
]);
|
||||
});
|
||||
|
||||
const referenceATs = (aTs: File): protocol.ReferencesResponseItem => makeReferenceItem({
|
||||
const referenceATs = (aTs: File, isDefinition: true | undefined): protocol.ReferencesResponseItem => makeReferenceItem({
|
||||
file: aTs,
|
||||
isDefinition: true,
|
||||
isDefinition,
|
||||
isWriteAccess: true,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}",
|
||||
lineText: "export function fnA() {}"
|
||||
});
|
||||
const referencesUserTs = (userTs: File): readonly protocol.ReferencesResponseItem[] => [
|
||||
const referencesUserTs = (userTs: File, isDefinition: false | undefined): readonly protocol.ReferencesResponseItem[] => [
|
||||
makeReferenceItem({
|
||||
file: userTs,
|
||||
isDefinition: false,
|
||||
isDefinition,
|
||||
text: "fnA",
|
||||
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
|
||||
}),
|
||||
@@ -394,7 +400,7 @@ namespace ts.projectSystem {
|
||||
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
|
||||
refs: [...referencesUserTs(userTs), referenceATs(aTs)],
|
||||
refs: [...referencesUserTs(userTs, /*isDefinition*/ undefined), referenceATs(aTs, /*isDefinition*/ true)], // Presently inconsistent across projects
|
||||
symbolName: "fnA",
|
||||
symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnA()").offset,
|
||||
symbolDisplayString: "function fnA(): void",
|
||||
@@ -408,7 +414,7 @@ namespace ts.projectSystem {
|
||||
openFilesForSession([aTs], session); // If it's not opened, the reference isn't found.
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(aTs, "fnA"));
|
||||
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
|
||||
refs: [referenceATs(aTs), ...referencesUserTs(userTs)],
|
||||
refs: [referenceATs(aTs, /*isDefinition*/ true), ...referencesUserTs(userTs, /*isDefinition*/ false)],
|
||||
symbolName: "fnA",
|
||||
symbolStartOffset: protocolLocationFromSubstring(aTs.content, "fnA").offset,
|
||||
symbolDisplayString: "function fnA(): void",
|
||||
@@ -448,8 +454,8 @@ namespace ts.projectSystem {
|
||||
],
|
||||
},
|
||||
references: [
|
||||
makeReferenceEntry({ file: userTs, /*isDefinition*/ isDefinition: false, text: "fnA" }),
|
||||
makeReferenceEntry({ file: aTs, /*isDefinition*/ isDefinition: true, text: "fnA", contextText: "export function fnA() {}" }),
|
||||
makeReferencedSymbolEntry({ file: userTs, text: "fnA" }),
|
||||
makeReferencedSymbolEntry({ file: aTs, text: "fnA", isDefinition: true, isWriteAccess: true, contextText: "export function fnA() {}" }),
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -502,16 +508,15 @@ namespace ts.projectSystem {
|
||||
name: "function f(): void",
|
||||
},
|
||||
references: [
|
||||
makeReferenceEntry({
|
||||
makeReferencedSymbolEntry({
|
||||
file: aTs,
|
||||
text: "f",
|
||||
options: { index: 1 },
|
||||
contextText: "function f() {}",
|
||||
isDefinition: true
|
||||
isWriteAccess: true,
|
||||
}),
|
||||
{
|
||||
fileName: bTs.path,
|
||||
isDefinition: false,
|
||||
isInString: undefined,
|
||||
isWriteAccess: false,
|
||||
textSpan: { start: 0, length: 1 },
|
||||
@@ -529,14 +534,13 @@ namespace ts.projectSystem {
|
||||
refs: [
|
||||
makeReferenceItem({
|
||||
file: bDts,
|
||||
isDefinition: true,
|
||||
isWriteAccess: true,
|
||||
text: "fnB",
|
||||
contextText: "export declare function fnB(): void;",
|
||||
lineText: "export declare function fnB(): void;"
|
||||
}),
|
||||
makeReferenceItem({
|
||||
file: userTs,
|
||||
isDefinition: false,
|
||||
text: "fnB",
|
||||
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
|
||||
}),
|
||||
|
||||
@@ -44,10 +44,10 @@ namespace ts.projectSystem {
|
||||
|
||||
const expectResponse: protocol.FileReferencesResponseBody = {
|
||||
refs: [
|
||||
makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isDefinition: false, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isDefinition: false, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isDefinition: false, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isDefinition: false, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isWriteAccess: false }),
|
||||
makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isWriteAccess: false }),
|
||||
],
|
||||
symbolName: `"${aTs.path}"`,
|
||||
};
|
||||
|
||||
@@ -713,7 +713,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
export interface MakeReferenceItem extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
isDefinition?: boolean;
|
||||
isWriteAccess?: boolean;
|
||||
lineText: string;
|
||||
}
|
||||
@@ -722,7 +722,7 @@ namespace ts.projectSystem {
|
||||
return {
|
||||
...protocolFileSpanWithContextFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isWriteAccess === undefined ? isDefinition : isWriteAccess,
|
||||
isWriteAccess: isWriteAccess === undefined ? !!isDefinition : isWriteAccess,
|
||||
lineText,
|
||||
};
|
||||
}
|
||||
|
||||
+2
-1
@@ -12,5 +12,6 @@
|
||||
"flags": "JSDoc",
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 1
|
||||
}
|
||||
},
|
||||
"postfix": false
|
||||
}
|
||||
+2
-1
@@ -12,5 +12,6 @@
|
||||
"flags": "JSDoc",
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 1
|
||||
}
|
||||
},
|
||||
"postfix": true
|
||||
}
|
||||
+2
-1
@@ -12,5 +12,6 @@
|
||||
"flags": "JSDoc",
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 1
|
||||
}
|
||||
},
|
||||
"postfix": false
|
||||
}
|
||||
+2
-1
@@ -12,5 +12,6 @@
|
||||
"flags": "JSDoc",
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 1
|
||||
}
|
||||
},
|
||||
"postfix": true
|
||||
}
|
||||
@@ -12,7 +12,7 @@ enum E { A, B, C, "non identifier" }
|
||||
>A : E.A
|
||||
>B : E.B
|
||||
>C : E.C
|
||||
>"non identifier" : typeof E["non identifier"]
|
||||
>"non identifier" : (typeof E)["non identifier"]
|
||||
|
||||
const c1 = "abc";
|
||||
>c1 : "abc"
|
||||
@@ -54,8 +54,8 @@ const c8 = E.A;
|
||||
>A : E.A
|
||||
|
||||
const c8b = E["non identifier"];
|
||||
>c8b : typeof E["non identifier"]
|
||||
>E["non identifier"] : typeof E["non identifier"]
|
||||
>c8b : (typeof E)["non identifier"]
|
||||
>E["non identifier"] : (typeof E)["non identifier"]
|
||||
>E : typeof E
|
||||
>"non identifier" : "non identifier"
|
||||
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
// === /tests/cases/fourslash/user.ts ===
|
||||
// import {/*FIND ALL REFS*/[|x|]} from "jquery";
|
||||
|
||||
[
|
||||
{
|
||||
"definition": {
|
||||
"containerKind": "",
|
||||
"containerName": "",
|
||||
"fileName": "/tests/cases/fourslash/user.ts",
|
||||
"kind": "alias",
|
||||
"name": "(alias) module \"jquery\"\nimport x",
|
||||
"textSpan": {
|
||||
"start": 8,
|
||||
"length": 1
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "alias",
|
||||
"kind": "text"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "module",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "\"jquery\"",
|
||||
"kind": "stringLiteral"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": "import",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "x",
|
||||
"kind": "aliasName"
|
||||
}
|
||||
],
|
||||
"contextSpan": {
|
||||
"start": 0,
|
||||
"length": 25
|
||||
}
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 8,
|
||||
"length": 1
|
||||
},
|
||||
"fileName": "/tests/cases/fourslash/user.ts",
|
||||
"contextSpan": {
|
||||
"start": 0,
|
||||
"length": 25
|
||||
},
|
||||
"isWriteAccess": true,
|
||||
"isDefinition": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// === /tests/cases/fourslash/user2.ts ===
|
||||
// import {/*FIND ALL REFS*/[|x|]} from "jquery";
|
||||
|
||||
[
|
||||
{
|
||||
"definition": {
|
||||
"containerKind": "",
|
||||
"containerName": "",
|
||||
"fileName": "/tests/cases/fourslash/user2.ts",
|
||||
"kind": "alias",
|
||||
"name": "(alias) module \"jquery\"\nimport x",
|
||||
"textSpan": {
|
||||
"start": 8,
|
||||
"length": 1
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "alias",
|
||||
"kind": "text"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "module",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "\"jquery\"",
|
||||
"kind": "stringLiteral"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": "import",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "x",
|
||||
"kind": "aliasName"
|
||||
}
|
||||
],
|
||||
"contextSpan": {
|
||||
"start": 0,
|
||||
"length": 25
|
||||
}
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 8,
|
||||
"length": 1
|
||||
},
|
||||
"fileName": "/tests/cases/fourslash/user2.ts",
|
||||
"contextSpan": {
|
||||
"start": 0,
|
||||
"length": 25
|
||||
},
|
||||
"isWriteAccess": true,
|
||||
"isDefinition": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
+23
-15
@@ -523,16 +523,17 @@ declare namespace ts {
|
||||
YieldContext = 8192,
|
||||
DecoratorContext = 16384,
|
||||
AwaitContext = 32768,
|
||||
ThisNodeHasError = 65536,
|
||||
JavaScriptFile = 131072,
|
||||
ThisNodeOrAnySubNodesHasError = 262144,
|
||||
HasAggregatedChildData = 524288,
|
||||
JSDoc = 4194304,
|
||||
JsonFile = 33554432,
|
||||
DisallowConditionalTypesContext = 65536,
|
||||
ThisNodeHasError = 131072,
|
||||
JavaScriptFile = 262144,
|
||||
ThisNodeOrAnySubNodesHasError = 524288,
|
||||
HasAggregatedChildData = 1048576,
|
||||
JSDoc = 8388608,
|
||||
JsonFile = 67108864,
|
||||
BlockScoped = 3,
|
||||
ReachabilityCheckFlags = 768,
|
||||
ReachabilityAndEmitFlags = 2816,
|
||||
ContextFlags = 25358336,
|
||||
ContextFlags = 50720768,
|
||||
TypeExcludesFlags = 40960,
|
||||
}
|
||||
export enum ModifierFlags {
|
||||
@@ -1805,10 +1806,12 @@ declare namespace ts {
|
||||
export interface JSDocNonNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNonNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
export interface JSDocNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
export interface JSDocOptionalType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocOptionalType;
|
||||
@@ -1983,7 +1986,7 @@ declare namespace ts {
|
||||
Label = 12,
|
||||
Condition = 96
|
||||
}
|
||||
export type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCall | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel;
|
||||
export type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel;
|
||||
export interface FlowNodeBase {
|
||||
flags: FlowFlags;
|
||||
id?: number;
|
||||
@@ -3164,7 +3167,7 @@ declare namespace ts {
|
||||
realpath?(path: string): string;
|
||||
getCurrentDirectory?(): string;
|
||||
getDirectories?(path: string): string[];
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean);
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean) | undefined;
|
||||
}
|
||||
/**
|
||||
* Used by services to specify the minimum host area required to set up source files under any compilation settings
|
||||
@@ -3654,9 +3657,9 @@ declare namespace ts {
|
||||
updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
|
||||
createJSDocAllType(): JSDocAllType;
|
||||
createJSDocUnknownType(): JSDocUnknownType;
|
||||
createJSDocNonNullableType(type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNonNullableType(type: TypeNode, postfix?: boolean): JSDocNonNullableType;
|
||||
updateJSDocNonNullableType(node: JSDocNonNullableType, type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNullableType(type: TypeNode): JSDocNullableType;
|
||||
createJSDocNullableType(type: TypeNode, postfix?: boolean): JSDocNullableType;
|
||||
updateJSDocNullableType(node: JSDocNullableType, type: TypeNode): JSDocNullableType;
|
||||
createJSDocOptionalType(type: TypeNode): JSDocOptionalType;
|
||||
updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType;
|
||||
@@ -6206,7 +6209,6 @@ declare namespace ts {
|
||||
}
|
||||
interface ReferenceEntry extends DocumentSpan {
|
||||
isWriteAccess: boolean;
|
||||
isDefinition: boolean;
|
||||
isInString?: true;
|
||||
}
|
||||
interface ImplementationLocation extends DocumentSpan {
|
||||
@@ -6320,7 +6322,10 @@ declare namespace ts {
|
||||
}
|
||||
interface ReferencedSymbol {
|
||||
definition: ReferencedSymbolDefinitionInfo;
|
||||
references: ReferenceEntry[];
|
||||
references: ReferencedSymbolEntry[];
|
||||
}
|
||||
interface ReferencedSymbolEntry extends ReferenceEntry {
|
||||
isDefinition?: boolean;
|
||||
}
|
||||
enum SymbolDisplayPartKind {
|
||||
aliasName = 0,
|
||||
@@ -7853,9 +7858,12 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
isWriteAccess: boolean;
|
||||
/**
|
||||
* True if reference is a definition, false otherwise.
|
||||
* Present only if the search was triggered from a declaration.
|
||||
* True indicates that the references refers to the same symbol
|
||||
* (i.e. has the same meaning) as the declaration that began the
|
||||
* search.
|
||||
*/
|
||||
isDefinition: boolean;
|
||||
isDefinition?: boolean;
|
||||
}
|
||||
/**
|
||||
* The body of a "references" response message.
|
||||
|
||||
+18
-13
@@ -523,16 +523,17 @@ declare namespace ts {
|
||||
YieldContext = 8192,
|
||||
DecoratorContext = 16384,
|
||||
AwaitContext = 32768,
|
||||
ThisNodeHasError = 65536,
|
||||
JavaScriptFile = 131072,
|
||||
ThisNodeOrAnySubNodesHasError = 262144,
|
||||
HasAggregatedChildData = 524288,
|
||||
JSDoc = 4194304,
|
||||
JsonFile = 33554432,
|
||||
DisallowConditionalTypesContext = 65536,
|
||||
ThisNodeHasError = 131072,
|
||||
JavaScriptFile = 262144,
|
||||
ThisNodeOrAnySubNodesHasError = 524288,
|
||||
HasAggregatedChildData = 1048576,
|
||||
JSDoc = 8388608,
|
||||
JsonFile = 67108864,
|
||||
BlockScoped = 3,
|
||||
ReachabilityCheckFlags = 768,
|
||||
ReachabilityAndEmitFlags = 2816,
|
||||
ContextFlags = 25358336,
|
||||
ContextFlags = 50720768,
|
||||
TypeExcludesFlags = 40960,
|
||||
}
|
||||
export enum ModifierFlags {
|
||||
@@ -1805,10 +1806,12 @@ declare namespace ts {
|
||||
export interface JSDocNonNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNonNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
export interface JSDocNullableType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocNullableType;
|
||||
readonly type: TypeNode;
|
||||
readonly postfix: boolean;
|
||||
}
|
||||
export interface JSDocOptionalType extends JSDocType {
|
||||
readonly kind: SyntaxKind.JSDocOptionalType;
|
||||
@@ -1983,7 +1986,7 @@ declare namespace ts {
|
||||
Label = 12,
|
||||
Condition = 96
|
||||
}
|
||||
export type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCall | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel;
|
||||
export type FlowNode = FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation | FlowCall | FlowReduceLabel;
|
||||
export interface FlowNodeBase {
|
||||
flags: FlowFlags;
|
||||
id?: number;
|
||||
@@ -3164,7 +3167,7 @@ declare namespace ts {
|
||||
realpath?(path: string): string;
|
||||
getCurrentDirectory?(): string;
|
||||
getDirectories?(path: string): string[];
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean);
|
||||
useCaseSensitiveFileNames?: boolean | (() => boolean) | undefined;
|
||||
}
|
||||
/**
|
||||
* Used by services to specify the minimum host area required to set up source files under any compilation settings
|
||||
@@ -3654,9 +3657,9 @@ declare namespace ts {
|
||||
updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
|
||||
createJSDocAllType(): JSDocAllType;
|
||||
createJSDocUnknownType(): JSDocUnknownType;
|
||||
createJSDocNonNullableType(type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNonNullableType(type: TypeNode, postfix?: boolean): JSDocNonNullableType;
|
||||
updateJSDocNonNullableType(node: JSDocNonNullableType, type: TypeNode): JSDocNonNullableType;
|
||||
createJSDocNullableType(type: TypeNode): JSDocNullableType;
|
||||
createJSDocNullableType(type: TypeNode, postfix?: boolean): JSDocNullableType;
|
||||
updateJSDocNullableType(node: JSDocNullableType, type: TypeNode): JSDocNullableType;
|
||||
createJSDocOptionalType(type: TypeNode): JSDocOptionalType;
|
||||
updateJSDocOptionalType(node: JSDocOptionalType, type: TypeNode): JSDocOptionalType;
|
||||
@@ -6206,7 +6209,6 @@ declare namespace ts {
|
||||
}
|
||||
interface ReferenceEntry extends DocumentSpan {
|
||||
isWriteAccess: boolean;
|
||||
isDefinition: boolean;
|
||||
isInString?: true;
|
||||
}
|
||||
interface ImplementationLocation extends DocumentSpan {
|
||||
@@ -6320,7 +6322,10 @@ declare namespace ts {
|
||||
}
|
||||
interface ReferencedSymbol {
|
||||
definition: ReferencedSymbolDefinitionInfo;
|
||||
references: ReferenceEntry[];
|
||||
references: ReferencedSymbolEntry[];
|
||||
}
|
||||
interface ReferencedSymbolEntry extends ReferenceEntry {
|
||||
isDefinition?: boolean;
|
||||
}
|
||||
enum SymbolDisplayPartKind {
|
||||
aliasName = 0,
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
//// [arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts]
|
||||
// regression test for https://github.com/microsoft/TypeScript/issues/32914
|
||||
declare var value: boolean;
|
||||
declare var a: any;
|
||||
|
||||
const test = () => ({
|
||||
// "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space.
|
||||
prop: !value, // remove ! to see that errors will be gone
|
||||
run: () => { //replace arrow function with regular function to see that errors will be gone
|
||||
// comment next line or remove "()" to see that errors will be gone
|
||||
if(!a.b()) { return 'special'; }
|
||||
|
||||
return 'default';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//// [arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.js]
|
||||
var test = function () { return ({
|
||||
// "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space.
|
||||
prop: !value,
|
||||
run: function () {
|
||||
// comment next line or remove "()" to see that errors will be gone
|
||||
if (!a.b()) {
|
||||
return 'special';
|
||||
}
|
||||
return 'default';
|
||||
}
|
||||
}); };
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
=== tests/cases/compiler/arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts ===
|
||||
// regression test for https://github.com/microsoft/TypeScript/issues/32914
|
||||
declare var value: boolean;
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 1, 11))
|
||||
|
||||
declare var a: any;
|
||||
>a : Symbol(a, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 2, 11))
|
||||
|
||||
const test = () => ({
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 4, 5))
|
||||
|
||||
// "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space.
|
||||
prop: !value, // remove ! to see that errors will be gone
|
||||
>prop : Symbol(prop, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 4, 21))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 1, 11))
|
||||
|
||||
run: () => { //replace arrow function with regular function to see that errors will be gone
|
||||
>run : Symbol(run, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 6, 17))
|
||||
|
||||
// comment next line or remove "()" to see that errors will be gone
|
||||
if(!a.b()) { return 'special'; }
|
||||
>a : Symbol(a, Decl(arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts, 2, 11))
|
||||
|
||||
return 'default';
|
||||
}
|
||||
});
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
=== tests/cases/compiler/arrowFunctionParsingDoesNotConfuseParenthesizedObjectForArrowHead.ts ===
|
||||
// regression test for https://github.com/microsoft/TypeScript/issues/32914
|
||||
declare var value: boolean;
|
||||
>value : boolean
|
||||
|
||||
declare var a: any;
|
||||
>a : any
|
||||
|
||||
const test = () => ({
|
||||
>test : () => { prop: boolean; run: () => "special" | "default"; }
|
||||
>() => ({ // "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space. prop: !value, // remove ! to see that errors will be gone run: () => { //replace arrow function with regular function to see that errors will be gone // comment next line or remove "()" to see that errors will be gone if(!a.b()) { return 'special'; } return 'default'; }}) : () => { prop: boolean; run: () => "special" | "default"; }
|
||||
>({ // "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space. prop: !value, // remove ! to see that errors will be gone run: () => { //replace arrow function with regular function to see that errors will be gone // comment next line or remove "()" to see that errors will be gone if(!a.b()) { return 'special'; } return 'default'; }}) : { prop: boolean; run: () => "special" | "default"; }
|
||||
>{ // "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space. prop: !value, // remove ! to see that errors will be gone run: () => { //replace arrow function with regular function to see that errors will be gone // comment next line or remove "()" to see that errors will be gone if(!a.b()) { return 'special'; } return 'default'; }} : { prop: boolean; run: () => "special" | "default"; }
|
||||
|
||||
// "Identifier expected." error on "!" and two "Duplicate identifier '(Missing)'." errors on space.
|
||||
prop: !value, // remove ! to see that errors will be gone
|
||||
>prop : boolean
|
||||
>!value : boolean
|
||||
>value : boolean
|
||||
|
||||
run: () => { //replace arrow function with regular function to see that errors will be gone
|
||||
>run : () => "special" | "default"
|
||||
>() => { //replace arrow function with regular function to see that errors will be gone // comment next line or remove "()" to see that errors will be gone if(!a.b()) { return 'special'; } return 'default'; } : () => "special" | "default"
|
||||
|
||||
// comment next line or remove "()" to see that errors will be gone
|
||||
if(!a.b()) { return 'special'; }
|
||||
>!a.b() : boolean
|
||||
>a.b() : any
|
||||
>a.b : any
|
||||
>a : any
|
||||
>b : any
|
||||
>'special' : "special"
|
||||
|
||||
return 'default';
|
||||
>'default' : "default"
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
//// [arrowFunctionParsingGenericInObject.ts]
|
||||
const fn1 = () => ({
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
extraValue: () => {},
|
||||
})
|
||||
|
||||
const fn1async = () => ({
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
extraValue: () => {},
|
||||
})
|
||||
|
||||
const fn2 = () => ({
|
||||
test: <T>(value: T): T => value,
|
||||
extraValue: () => {},
|
||||
})
|
||||
|
||||
const fn2async = () => ({
|
||||
test: async <T>(value: T): Promise<T> => value,
|
||||
extraValue: () => {},
|
||||
})
|
||||
|
||||
const fn3 = () => ({
|
||||
extraValue: () => {},
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
})
|
||||
|
||||
const fn3async = () => ({
|
||||
extraValue: () => {},
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
})
|
||||
|
||||
const fn4 = () => ({
|
||||
extraValue: '',
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
})
|
||||
|
||||
const fn4async = () => ({
|
||||
extraValue: '',
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
})
|
||||
|
||||
|
||||
//// [arrowFunctionParsingGenericInObject.js]
|
||||
const fn1 = () => ({
|
||||
test: (value) => value,
|
||||
extraValue: () => { },
|
||||
});
|
||||
const fn1async = () => ({
|
||||
test: async (value) => value,
|
||||
extraValue: () => { },
|
||||
});
|
||||
const fn2 = () => ({
|
||||
test: (value) => value,
|
||||
extraValue: () => { },
|
||||
});
|
||||
const fn2async = () => ({
|
||||
test: async (value) => value,
|
||||
extraValue: () => { },
|
||||
});
|
||||
const fn3 = () => ({
|
||||
extraValue: () => { },
|
||||
test: (value) => value,
|
||||
});
|
||||
const fn3async = () => ({
|
||||
extraValue: () => { },
|
||||
test: async (value) => value,
|
||||
});
|
||||
const fn4 = () => ({
|
||||
extraValue: '',
|
||||
test: (value) => value,
|
||||
});
|
||||
const fn4async = () => ({
|
||||
extraValue: '',
|
||||
test: async (value) => value,
|
||||
});
|
||||
@@ -0,0 +1,133 @@
|
||||
=== tests/cases/compiler/arrowFunctionParsingGenericInObject.ts ===
|
||||
const fn1 = () => ({
|
||||
>fn1 : Symbol(fn1, Decl(arrowFunctionParsingGenericInObject.ts, 0, 5))
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 0, 20))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 1, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 1, 26))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 1, 11))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 1, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 1, 26))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 1, 48))
|
||||
|
||||
})
|
||||
|
||||
const fn1async = () => ({
|
||||
>fn1async : Symbol(fn1async, Decl(arrowFunctionParsingGenericInObject.ts, 5, 5))
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 5, 25))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 6, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 6, 32))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 6, 17))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 6, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 6, 32))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 6, 63))
|
||||
|
||||
})
|
||||
|
||||
const fn2 = () => ({
|
||||
>fn2 : Symbol(fn2, Decl(arrowFunctionParsingGenericInObject.ts, 10, 5))
|
||||
|
||||
test: <T>(value: T): T => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 10, 20))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 11, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 11, 14))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 11, 11))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 11, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 11, 14))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 11, 36))
|
||||
|
||||
})
|
||||
|
||||
const fn2async = () => ({
|
||||
>fn2async : Symbol(fn2async, Decl(arrowFunctionParsingGenericInObject.ts, 15, 5))
|
||||
|
||||
test: async <T>(value: T): Promise<T> => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 15, 25))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 16, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 16, 20))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 16, 17))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 16, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 16, 20))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 16, 51))
|
||||
|
||||
})
|
||||
|
||||
const fn3 = () => ({
|
||||
>fn3 : Symbol(fn3, Decl(arrowFunctionParsingGenericInObject.ts, 20, 5))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 20, 20))
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 21, 25))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 22, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 22, 26))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 22, 11))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 22, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 22, 26))
|
||||
|
||||
})
|
||||
|
||||
const fn3async = () => ({
|
||||
>fn3async : Symbol(fn3async, Decl(arrowFunctionParsingGenericInObject.ts, 25, 5))
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 25, 25))
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 26, 25))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 27, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 27, 32))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 27, 17))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 27, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 27, 32))
|
||||
|
||||
})
|
||||
|
||||
const fn4 = () => ({
|
||||
>fn4 : Symbol(fn4, Decl(arrowFunctionParsingGenericInObject.ts, 30, 5))
|
||||
|
||||
extraValue: '',
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 30, 20))
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 31, 19))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 32, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 32, 26))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 32, 11))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 32, 11))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 32, 26))
|
||||
|
||||
})
|
||||
|
||||
const fn4async = () => ({
|
||||
>fn4async : Symbol(fn4async, Decl(arrowFunctionParsingGenericInObject.ts, 35, 5))
|
||||
|
||||
extraValue: '',
|
||||
>extraValue : Symbol(extraValue, Decl(arrowFunctionParsingGenericInObject.ts, 35, 25))
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : Symbol(test, Decl(arrowFunctionParsingGenericInObject.ts, 36, 19))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 37, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 37, 32))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 37, 17))
|
||||
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(arrowFunctionParsingGenericInObject.ts, 37, 17))
|
||||
>value : Symbol(value, Decl(arrowFunctionParsingGenericInObject.ts, 37, 32))
|
||||
|
||||
})
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
=== tests/cases/compiler/arrowFunctionParsingGenericInObject.ts ===
|
||||
const fn1 = () => ({
|
||||
>fn1 : () => { test: <T = undefined>(value: T) => T; extraValue: () => void; }
|
||||
>() => ({ test: <T = undefined>(value: T): T => value, extraValue: () => {},}) : () => { test: <T = undefined>(value: T) => T; extraValue: () => void; }
|
||||
>({ test: <T = undefined>(value: T): T => value, extraValue: () => {},}) : { test: <T = undefined>(value: T) => T; extraValue: () => void; }
|
||||
>{ test: <T = undefined>(value: T): T => value, extraValue: () => {},} : { test: <T = undefined>(value: T) => T; extraValue: () => void; }
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : <T = undefined>(value: T) => T
|
||||
><T = undefined>(value: T): T => value : <T = undefined>(value: T) => T
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
})
|
||||
|
||||
const fn1async = () => ({
|
||||
>fn1async : () => { test: <T = undefined>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>() => ({ test: async <T = undefined>(value: T): Promise<T> => value, extraValue: () => {},}) : () => { test: <T = undefined>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>({ test: async <T = undefined>(value: T): Promise<T> => value, extraValue: () => {},}) : { test: <T = undefined>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>{ test: async <T = undefined>(value: T): Promise<T> => value, extraValue: () => {},} : { test: <T = undefined>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : <T = undefined>(value: T) => Promise<T>
|
||||
>async <T = undefined>(value: T): Promise<T> => value : <T = undefined>(value: T) => Promise<T>
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
})
|
||||
|
||||
const fn2 = () => ({
|
||||
>fn2 : () => { test: <T>(value: T) => T; extraValue: () => void; }
|
||||
>() => ({ test: <T>(value: T): T => value, extraValue: () => {},}) : () => { test: <T>(value: T) => T; extraValue: () => void; }
|
||||
>({ test: <T>(value: T): T => value, extraValue: () => {},}) : { test: <T>(value: T) => T; extraValue: () => void; }
|
||||
>{ test: <T>(value: T): T => value, extraValue: () => {},} : { test: <T>(value: T) => T; extraValue: () => void; }
|
||||
|
||||
test: <T>(value: T): T => value,
|
||||
>test : <T>(value: T) => T
|
||||
><T>(value: T): T => value : <T>(value: T) => T
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
})
|
||||
|
||||
const fn2async = () => ({
|
||||
>fn2async : () => { test: <T>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>() => ({ test: async <T>(value: T): Promise<T> => value, extraValue: () => {},}) : () => { test: <T>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>({ test: async <T>(value: T): Promise<T> => value, extraValue: () => {},}) : { test: <T>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
>{ test: async <T>(value: T): Promise<T> => value, extraValue: () => {},} : { test: <T>(value: T) => Promise<T>; extraValue: () => void; }
|
||||
|
||||
test: async <T>(value: T): Promise<T> => value,
|
||||
>test : <T>(value: T) => Promise<T>
|
||||
>async <T>(value: T): Promise<T> => value : <T>(value: T) => Promise<T>
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
})
|
||||
|
||||
const fn3 = () => ({
|
||||
>fn3 : () => { extraValue: () => void; test: <T = undefined>(value: T) => T; }
|
||||
>() => ({ extraValue: () => {}, test: <T = undefined>(value: T): T => value,}) : () => { extraValue: () => void; test: <T = undefined>(value: T) => T; }
|
||||
>({ extraValue: () => {}, test: <T = undefined>(value: T): T => value,}) : { extraValue: () => void; test: <T = undefined>(value: T) => T; }
|
||||
>{ extraValue: () => {}, test: <T = undefined>(value: T): T => value,} : { extraValue: () => void; test: <T = undefined>(value: T) => T; }
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : <T = undefined>(value: T) => T
|
||||
><T = undefined>(value: T): T => value : <T = undefined>(value: T) => T
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
})
|
||||
|
||||
const fn3async = () => ({
|
||||
>fn3async : () => { extraValue: () => void; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>() => ({ extraValue: () => {}, test: async <T = undefined>(value: T): Promise<T> => value,}) : () => { extraValue: () => void; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>({ extraValue: () => {}, test: async <T = undefined>(value: T): Promise<T> => value,}) : { extraValue: () => void; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>{ extraValue: () => {}, test: async <T = undefined>(value: T): Promise<T> => value,} : { extraValue: () => void; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
|
||||
extraValue: () => {},
|
||||
>extraValue : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : <T = undefined>(value: T) => Promise<T>
|
||||
>async <T = undefined>(value: T): Promise<T> => value : <T = undefined>(value: T) => Promise<T>
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
})
|
||||
|
||||
const fn4 = () => ({
|
||||
>fn4 : () => { extraValue: string; test: <T = undefined>(value: T) => T; }
|
||||
>() => ({ extraValue: '', test: <T = undefined>(value: T): T => value,}) : () => { extraValue: string; test: <T = undefined>(value: T) => T; }
|
||||
>({ extraValue: '', test: <T = undefined>(value: T): T => value,}) : { extraValue: string; test: <T = undefined>(value: T) => T; }
|
||||
>{ extraValue: '', test: <T = undefined>(value: T): T => value,} : { extraValue: string; test: <T = undefined>(value: T) => T; }
|
||||
|
||||
extraValue: '',
|
||||
>extraValue : string
|
||||
>'' : ""
|
||||
|
||||
test: <T = undefined>(value: T): T => value,
|
||||
>test : <T = undefined>(value: T) => T
|
||||
><T = undefined>(value: T): T => value : <T = undefined>(value: T) => T
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
})
|
||||
|
||||
const fn4async = () => ({
|
||||
>fn4async : () => { extraValue: string; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>() => ({ extraValue: '', test: async <T = undefined>(value: T): Promise<T> => value,}) : () => { extraValue: string; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>({ extraValue: '', test: async <T = undefined>(value: T): Promise<T> => value,}) : { extraValue: string; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
>{ extraValue: '', test: async <T = undefined>(value: T): Promise<T> => value,} : { extraValue: string; test: <T = undefined>(value: T) => Promise<T>; }
|
||||
|
||||
extraValue: '',
|
||||
>extraValue : string
|
||||
>'' : ""
|
||||
|
||||
test: async <T = undefined>(value: T): Promise<T> => value,
|
||||
>test : <T = undefined>(value: T) => Promise<T>
|
||||
>async <T = undefined>(value: T): Promise<T> => value : <T = undefined>(value: T) => Promise<T>
|
||||
>value : T
|
||||
>value : T
|
||||
|
||||
})
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
"length": 1
|
||||
},
|
||||
"fileName": "/b/b.ts",
|
||||
"isWriteAccess": false,
|
||||
"isDefinition": false
|
||||
"isWriteAccess": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ tests/cases/compiler/baseCheck.ts(26,9): error TS2304: Cannot find name 'x'.
|
||||
super(0, loc);
|
||||
~~~
|
||||
!!! error TS2552: Cannot find name 'loc'. Did you mean 'Lock'?
|
||||
!!! related TS2728 /.ts/lib.dom.d.ts:8963:13: 'Lock' is declared here.
|
||||
!!! related TS2728 /.ts/lib.dom.d.ts:9089:13: 'Lock' is declared here.
|
||||
}
|
||||
|
||||
m() {
|
||||
|
||||
@@ -5,7 +5,7 @@ enum ENUM1 { A, B, "" };
|
||||
>ENUM1 : ENUM1
|
||||
>A : ENUM1.A
|
||||
>B : ENUM1.B
|
||||
>"" : typeof ENUM1[""]
|
||||
>"" : (typeof ENUM1)[""]
|
||||
|
||||
// enum type var
|
||||
var ResultIsNumber1 = ~ENUM1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user