diff --git a/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt b/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt index f20c8e80..a3573690 100644 --- a/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt +++ b/src/GraphQLParser.ApiTests/GraphQLParser.approved.txt @@ -840,6 +840,10 @@ namespace GraphQLParser.Visitors public int MaxDepth { get; set; } public System.Collections.Generic.Stack Parents { get; set; } } + public struct DefaultVisitorContext : GraphQLParser.Visitors.IASTVisitorContext + { + public System.Threading.CancellationToken CancellationToken { get; set; } + } public interface IASTVisitorContext { System.Threading.CancellationToken CancellationToken { get; } @@ -871,6 +875,10 @@ namespace GraphQLParser.Visitors public MaxDepthVisitor() { } public override System.Threading.Tasks.ValueTask VisitAsync(GraphQLParser.AST.ASTNode? node, TContext context) { } } + public struct NullVisitorContext : GraphQLParser.Visitors.IASTVisitorContext + { + public System.Threading.CancellationToken CancellationToken { get; } + } public static class PrintContextExtensions { public static System.Threading.Tasks.ValueTask WriteAsync(this TContext context, GraphQLParser.ROM value) diff --git a/src/GraphQLParser.Tests/Visitors/ASTVisitorTests.cs b/src/GraphQLParser.Tests/Visitors/ASTVisitorTests.cs index 1abaea09..9f1be0e9 100644 --- a/src/GraphQLParser.Tests/Visitors/ASTVisitorTests.cs +++ b/src/GraphQLParser.Tests/Visitors/ASTVisitorTests.cs @@ -33,12 +33,13 @@ public void ASTVisitor_Should_Throw_On_Unknown_Node() } [Fact] - public void ASTVisitor_Should_Respect_CancellationToken() + public void ASTVisitor_Should_Pass_CancellationToken() { var document = "scalar JSON".Parse(); var visitor = new MyVisitor(); using var cts = new CancellationTokenSource(500); var context = new Context { CancellationToken = cts.Token }; + context.CancellationToken.ThrowIfCancellationRequested(); Should.Throw(() => visitor.VisitAsync(document, context).GetAwaiter().GetResult()); } @@ -48,6 +49,7 @@ private sealed class MyVisitor : ASTVisitor protected override async ValueTask VisitScalarTypeDefinitionAsync(GraphQLScalarTypeDefinition scalarTypeDefinition, Context context) { await Task.Delay(700); + context.CancellationToken.ThrowIfCancellationRequested(); await base.VisitScalarTypeDefinitionAsync(scalarTypeDefinition, context); } } diff --git a/src/GraphQLParser/Visitors/ASTVisitor.cs b/src/GraphQLParser/Visitors/ASTVisitor.cs index df9d0910..2b6103f8 100644 --- a/src/GraphQLParser/Visitors/ASTVisitor.cs +++ b/src/GraphQLParser/Visitors/ASTVisitor.cs @@ -597,8 +597,6 @@ protected virtual async ValueTask VisitInputObjectTypeExtensionAsync(GraphQLInpu /// Context passed into all INodeVisitor.VisitXXX methods. public virtual ValueTask VisitAsync(ASTNode? node, TContext context) { - context.CancellationToken.ThrowIfCancellationRequested(); - return node == null ? default : node switch diff --git a/src/GraphQLParser/Visitors/DefaultVisitorContext.cs b/src/GraphQLParser/Visitors/DefaultVisitorContext.cs new file mode 100644 index 00000000..69489945 --- /dev/null +++ b/src/GraphQLParser/Visitors/DefaultVisitorContext.cs @@ -0,0 +1,11 @@ +namespace GraphQLParser.Visitors; + +/// +/// An implementation of that only contains a . +/// Ideal for use in cases where there is no context variables. +/// +public struct DefaultVisitorContext : IASTVisitorContext +{ + /// + public CancellationToken CancellationToken { get; set; } +} diff --git a/src/GraphQLParser/Visitors/NullVisitorContext.cs b/src/GraphQLParser/Visitors/NullVisitorContext.cs new file mode 100644 index 00000000..5093a9be --- /dev/null +++ b/src/GraphQLParser/Visitors/NullVisitorContext.cs @@ -0,0 +1,12 @@ +namespace GraphQLParser.Visitors; + +/// +/// An implementation of that does nothing. +/// Ideal for use in cases where the visitor runs synchronously, there is no context +/// variables, and cancellation is not required. +/// +public struct NullVisitorContext : IASTVisitorContext +{ + /// + public readonly CancellationToken CancellationToken => default; +}