Skip to content

Commit

Permalink
Fixed issue where directive middleware would interfere with mutation …
Browse files Browse the repository at this point in the history
…middleware. (ChilliCream#4537)
  • Loading branch information
michaelstaib authored Dec 10, 2021
1 parent 447bf4f commit e7ea02b
Show file tree
Hide file tree
Showing 18 changed files with 243 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static bool TryCoerceArguments(

foreach (ArgumentValue argument in arguments.Values)
{
if (argument.IsFinal)
if (argument.IsFullyCoerced)
{
args.Add(argument.Name, argument);
}
Expand All @@ -58,8 +58,8 @@ public static bool TryCoerceArguments(
literal.TryGetValueKind(out ValueKind kind)
? kind
: ValueKind.Unknown,
argument.IsFinal,
argument.IsImplicit,
argument.IsFullyCoerced,
argument.IsDefaultValue,
null,
literal));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using HotChocolate.Resolvers;

#nullable enable

Expand All @@ -20,7 +21,7 @@ public ArgumentMap(IReadOnlyDictionary<NameString, ArgumentValue> arguments)
{
foreach (ArgumentValue argument in arguments.Values)
{
if (!argument.IsFinal)
if (!argument.IsFullyCoerced)
{
IsFinal = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public ValueTask<T> ResolveAsync<T>() =>
public void RegisterForCleanup(Action action) =>
_middlewareContext.RegisterForCleanup(action);

public IReadOnlyDictionary<NameString, ArgumentValue> ReplaceArguments(
IReadOnlyDictionary<NameString, ArgumentValue> argumentValues) =>
_middlewareContext.ReplaceArguments(argumentValues);

public ValueKind ArgumentKind(NameString name) =>
_middlewareContext.ArgumentKind(name);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using HotChocolate.Resolvers;

namespace HotChocolate.Execution.Processing;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using HotChocolate.Language;
using HotChocolate.Resolvers;
Expand Down Expand Up @@ -47,7 +48,7 @@ public Optional<T> ArgumentOptional<T>(NameString name)
throw ResolverContext_ArgumentDoesNotExist(_selection.SyntaxNode, Path, name);
}

return argument.IsImplicit
return argument.IsDefaultValue
? Optional<T>.Empty(CoerceArgumentValue<T>(argument))
: new Optional<T>(CoerceArgumentValue<T>(argument));
}
Expand Down Expand Up @@ -88,7 +89,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)

// if the argument is final and has an already coerced
// runtime version we can skip over parsing it.
if (!argument.IsFinal)
if (!argument.IsFullyCoerced)
{
value = _parser.ParseLiteral(argument.ValueLiteral!, argument, typeof(T));
}
Expand Down Expand Up @@ -122,4 +123,17 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)
argument.Name,
typeof(T));
}

public IReadOnlyDictionary<NameString, ArgumentValue> ReplaceArguments(
IReadOnlyDictionary<NameString, ArgumentValue> argumentValues)
{
if (argumentValues is null)
{
throw new ArgumentNullException(nameof(argumentValues));
}

IReadOnlyDictionary<NameString, ArgumentValue> original = Arguments;
Arguments = argumentValues;
return original;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public Optional<T> ArgumentOptional<T>(NameString name)
throw ResolverContext_ArgumentDoesNotExist(_selection.SyntaxNode, _path, name);
}

return argument.IsImplicit
return argument.IsDefaultValue
? Optional<T>.Empty(CoerceArgumentValue<T>(argument))
: new Optional<T>(CoerceArgumentValue<T>(argument));
}
Expand All @@ -150,7 +150,7 @@ private T CoerceArgumentValue<T>(ArgumentValue argument)

// if the argument is final and has an already coerced
// runtime version we can skip over parsing it.
if (!argument.IsFinal)
if (!argument.IsFullyCoerced)
{
value = _parentContext._parser.ParseLiteral(
argument.ValueLiteral!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using HotChocolate.Execution.Instrumentation;
using HotChocolate.Execution.Processing.Plan;
using HotChocolate.Fetching;
using HotChocolate.Resolvers;
using HotChocolate.Types;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.ObjectPool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HotChocolate.Resolvers;
using HotChocolate.Types;

namespace HotChocolate.Execution.Processing.Tasks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,15 @@ public MutationConventionMiddleware(
throw new ArgumentNullException(nameof(resolverArguments));
}

public ValueTask InvokeAsync(IMiddlewareContext context)
=> InvokeInternalAsync((MiddlewareContext)context);

private async ValueTask InvokeInternalAsync(MiddlewareContext context)
public async ValueTask InvokeAsync(IMiddlewareContext context)
{
var input = context.ArgumentValue<IDictionary<string, object?>>(_inputArgumentName);
var inputLiteral = context.ArgumentLiteral<ObjectValueNode>(_inputArgumentName)
.Fields.ToDictionary(t => t.Name.Value, t => t.Value);
var inputArgument = context.Arguments[_inputArgumentName];

var preservedArguments = context.Arguments;
var arguments = new Dictionary<NameString, ArgumentValue>();
var preservedArguments = context.ReplaceArguments(arguments);
var inputArgument = preservedArguments[_inputArgumentName];

foreach (ResolverArgument argument in _resolverArguments)
{
Expand All @@ -58,20 +55,19 @@ private async ValueTask InvokeInternalAsync(MiddlewareContext context)
new ArgumentValue(
argument,
kind,
inputArgument.IsFinal,
inputArgument.IsImplicit,
inputArgument.IsFullyCoerced,
inputArgument.IsDefaultValue,
value,
valueLiteral));
}

try
{
context.Arguments = arguments;
await _next(context);
}
finally
{
context.Arguments = preservedArguments;
context.ReplaceArguments(preservedArguments);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,16 @@ private void CompleteNames()
_interceptor.OnAfterCompleteTypeNames();
}

internal RegisteredType InitializeType(TypeSystemObjectBase type)
internal RegisteredType InitializeType(
TypeSystemObjectBase type)
{
var typeReg = new RegisteredType(
type,
false,
_typeRegistry,
_typeLookup,
_context,
new TypeInterceptor(),
_interceptor,
null);

typeReg.References.Add(TypeReference.Create(type));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,71 @@
using HotChocolate.Language;
using HotChocolate.Types;

namespace HotChocolate.Execution.Processing;
namespace HotChocolate.Resolvers;

/// <summary>
/// Represents an argument value withing the field execution pipeline.
/// </summary>
public sealed class ArgumentValue : IInputFieldInfo
{
private readonly IInputFieldInfo _argument;

/// <summary>
/// Initializes a new instance of <see cref="ArgumentValue"/>.
/// </summary>
/// <param name="argument">The argument.</param>
/// <param name="kind">
/// The value kind.
/// </param>
/// <param name="isFullyCoerced">
/// Specifies if this value is final or if it needs to be coerced during field execution..
/// Values with variables for instance need coercion during field execution.
/// </param>
/// <param name="isDefaultValue">
/// Defines if the provided value represents the argument default value and was not explicitly
/// provided by the user.
/// </param>
/// <param name="value">
/// The runtime value representation.
/// </param>
/// <param name="valueLiteral">
/// The syntax value representation.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="argument"/> or <param name="valueLiteral"></param> is <c>null</c>.
/// </exception>
public ArgumentValue(
IInputFieldInfo argument,
ValueKind kind,
bool isFinal,
bool isImplicit,
bool isFullyCoerced,
bool isDefaultValue,
object? value,
IValueNode valueLiteral)
{
_argument = argument ?? throw new ArgumentNullException(nameof(argument));
Kind = kind;
IsFinal = isFinal;
IsImplicit = isImplicit;
IsFullyCoerced = isFullyCoerced;
IsDefaultValue = isDefaultValue;
HasError = false;
Error = null;
Value = value;
ValueLiteral = valueLiteral ?? throw new ArgumentNullException(nameof(valueLiteral));
}

/// <summary>
/// Initializes a new instance of <see cref="ArgumentValue"/>.
/// </summary>
/// <param name="argument">The argument.</param>
/// <param name="error">The argument value error.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="argument"/> or <param name="error"></param> is <c>null</c>.
/// </exception>
public ArgumentValue(IInputFieldInfo argument, IError error)
{
_argument = argument ?? throw new ArgumentNullException(nameof(argument));
Error = error ?? throw new ArgumentNullException(nameof(error));
HasError = true;
IsFinal = true;
IsFullyCoerced = true;
Kind = null;
Value = null;
ValueLiteral = null;
Expand Down Expand Up @@ -67,20 +102,27 @@ public ArgumentValue(IInputFieldInfo argument, IError error)
/// </summary>
public IInputValueFormatter? Formatter => _argument.Formatter;

/// <summary>
/// Specifies the value structure.
/// </summary>
public ValueKind? Kind { get; }

/// <summary>
/// Defines if this argument value is fully coerced and
/// need no post processing.
/// needs no post processing.
/// </summary>
public bool IsFinal { get; }
public bool IsFullyCoerced { get; }

/// <summary>
/// Defines if this argument value has errors.
/// Defines if this argument value has errors that will
/// be thrown during field execution.
/// </summary>
public bool HasError { get; }

public bool IsImplicit { get; }
/// <summary>
/// Defines if the value was inferred from the default value.
/// </summary>
public bool IsDefaultValue { get; }

/// <summary>
/// Gets the runtime value representation of this argument.
Expand Down
14 changes: 14 additions & 0 deletions src/HotChocolate/Core/src/Types/Resolvers/IMiddlewareContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using HotChocolate.Types;

Expand Down Expand Up @@ -42,4 +43,17 @@ public interface IMiddlewareContext : IResolverContext
/// Cleanup action.
/// </param>
void RegisterForCleanup(Action action);

/// <summary>
/// Replaces the argument values for the current field execution pipeline.
/// </summary>
/// <param name="argumentValues">
/// The new argument values that shall replace the current argument values.
/// </param>
/// <returns>
/// Returns the original argument values map so that a middleware is able to conserve them
/// and restore the initial state of the context after it finished to execute.
/// </returns>
IReadOnlyDictionary<NameString, ArgumentValue> ReplaceArguments(
IReadOnlyDictionary<NameString, ArgumentValue> argumentValues);
}
Loading

0 comments on commit e7ea02b

Please sign in to comment.