@@ -229,6 +229,15 @@ class await_async : public coro::suspend_always
229229 }
230230};
231231
232+ // Directive order matters, and some of them are repeatable. So rather than passing them in a
233+ // response::Value, pass directives in something like the underlying response::MapType which
234+ // preserves the order of the elements without complete uniqueness.
235+ using Directives = std::vector<std::pair<std::string_view, response::Value>>;
236+
237+ // Traversing a fragment spread adds a new set of directives.
238+ using FragmentDefinitionDirectiveStack = std::list<std::reference_wrapper<const Directives>>;
239+ using FragmentSpreadDirectiveStack = std::list<Directives>;
240+
232241// Pass a common bundle of parameters to all of the generated Object::getField accessors in a
233242// SelectionSet
234243struct SelectionSetParams
@@ -239,14 +248,14 @@ struct SelectionSetParams
239248 // The lifetime of each of these borrowed references is guaranteed until the future returned
240249 // by the accessor is resolved or destroyed. They are owned by the OperationData shared pointer.
241250 const std::shared_ptr<RequestState>& state;
242- const response::Value & operationDirectives;
243- const response::Value& fragmentDefinitionDirectives;
251+ const Directives & operationDirectives;
252+ const std::shared_ptr<FragmentDefinitionDirectiveStack> fragmentDefinitionDirectives;
244253
245254 // Fragment directives are shared for all fields in that fragment, but they aren't kept alive
246255 // after the call to the last accessor in the fragment. If you need to keep them alive longer,
247- // you'll need to explicitly copy them into other instances of response::Value .
248- const response::Value& fragmentSpreadDirectives;
249- const response::Value& inlineFragmentDirectives;
256+ // you'll need to explicitly copy them into other instances of Directives .
257+ const std::shared_ptr<FragmentSpreadDirectiveStack> fragmentSpreadDirectives;
258+ const std::shared_ptr<FragmentSpreadDirectiveStack> inlineFragmentDirectives;
250259
251260 // Field error path to this selection set.
252261 std::optional<field_path> errorPath;
@@ -259,12 +268,12 @@ struct SelectionSetParams
259268struct FieldParams : SelectionSetParams
260269{
261270 GRAPHQLSERVICE_EXPORT explicit FieldParams (
262- SelectionSetParams&& selectionSetParams, response::Value directives);
271+ SelectionSetParams&& selectionSetParams, Directives directives);
263272
264273 // Each field owns its own field-specific directives. Once the accessor returns it will be
265274 // destroyed, but you can move it into another instance of response::Value to keep it alive
266275 // longer.
267- response::Value fieldDirectives;
276+ Directives fieldDirectives;
268277};
269278
270279// Field accessors may return either a result of T, an awaitable of T, or a std::future<T>, so at
@@ -379,11 +388,11 @@ class Fragment
379388
380389 std::string_view getType () const ;
381390 const peg::ast_node& getSelection () const ;
382- const response::Value & getDirectives () const ;
391+ const Directives & getDirectives () const ;
383392
384393private:
385394 std::string_view _type;
386- response::Value _directives;
395+ Directives _directives;
387396
388397 std::reference_wrapper<const peg::ast_node> _selection;
389398};
@@ -399,16 +408,16 @@ struct ResolverParams : SelectionSetParams
399408{
400409 GRAPHQLSERVICE_EXPORT explicit ResolverParams (const SelectionSetParams& selectionSetParams,
401410 const peg::ast_node& field, std::string&& fieldName, response::Value arguments,
402- response::Value fieldDirectives, const peg::ast_node* selection,
403- const FragmentMap& fragments, const response::Value& variables);
411+ Directives fieldDirectives, const peg::ast_node* selection, const FragmentMap& fragments ,
412+ const response::Value& variables);
404413
405414 GRAPHQLSERVICE_EXPORT schema_location getLocation () const ;
406415
407416 // These values are different for each resolver.
408417 const peg::ast_node& field;
409418 std::string fieldName;
410419 response::Value arguments { response::Type::Map };
411- response::Value fieldDirectives { response::Type::Map } ;
420+ Directives fieldDirectives;
412421 const peg::ast_node* selection;
413422
414423 // These values remain unchanged for the entire operation, but they're passed to each of the
@@ -944,19 +953,20 @@ struct SubscriptionParams
944953struct OperationData : std::enable_shared_from_this<OperationData>
945954{
946955 explicit OperationData (std::shared_ptr<RequestState> state, response::Value variables,
947- response::Value directives, FragmentMap fragments);
956+ Directives directives, FragmentMap fragments);
948957
949958 std::shared_ptr<RequestState> state;
950959 response::Value variables;
951- response::Value directives;
960+ Directives directives;
952961 FragmentMap fragments;
953962};
954963
955964// Subscription callbacks receive the response::Value representing the result of evaluating the
956965// SelectionSet against the payload.
957966using SubscriptionCallback = std::function<void (response::Value)>;
958967using SubscriptionArguments = std::map<std::string_view, response::Value>;
959- using SubscriptionFilterCallback = std::function<bool (response::MapType::const_reference)>;
968+ using SubscriptionArgumentFilterCallback = std::function<bool (response::MapType::const_reference)>;
969+ using SubscriptionDirectiveFilterCallback = std::function<bool (Directives::const_reference)>;
960970
961971// Subscriptions are stored in maps using these keys.
962972using SubscriptionKey = size_t ;
@@ -970,15 +980,15 @@ using AwaitableDeliver = internal::Awaitable<void>;
970980struct SubscriptionData : std::enable_shared_from_this<SubscriptionData>
971981{
972982 explicit SubscriptionData (std::shared_ptr<OperationData> data, SubscriptionName&& field,
973- response::Value arguments, response::Value fieldDirectives, peg::ast&& query,
983+ response::Value arguments, Directives fieldDirectives, peg::ast&& query,
974984 std::string&& operationName, SubscriptionCallback&& callback,
975985 const peg::ast_node& selection);
976986
977987 std::shared_ptr<OperationData> data;
978988
979989 SubscriptionName field;
980990 response::Value arguments;
981- response::Value fieldDirectives;
991+ Directives fieldDirectives;
982992 peg::ast query;
983993 std::string operationName;
984994 SubscriptionCallback callback;
@@ -1023,29 +1033,29 @@ class Request : public std::enable_shared_from_this<Request>
10231033 GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
10241034 const SubscriptionArguments& arguments, std::shared_ptr<Object> subscriptionObject) const ;
10251035 GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1026- const SubscriptionArguments& arguments, const SubscriptionArguments & directives,
1036+ const SubscriptionArguments& arguments, const Directives & directives,
10271037 std::shared_ptr<Object> subscriptionObject) const ;
10281038 GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1029- const SubscriptionFilterCallback & applyArguments,
1039+ const SubscriptionArgumentFilterCallback & applyArguments,
10301040 std::shared_ptr<Object> subscriptionObject) const ;
10311041 GRAPHQLSERVICE_EXPORT void deliver (const SubscriptionName& name,
1032- const SubscriptionFilterCallback & applyArguments,
1033- const SubscriptionFilterCallback & applyDirectives,
1042+ const SubscriptionArgumentFilterCallback & applyArguments,
1043+ const SubscriptionDirectiveFilterCallback & applyDirectives,
10341044 std::shared_ptr<Object> subscriptionObject) const ;
10351045
10361046 GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
10371047 std::shared_ptr<Object> subscriptionObject) const ;
10381048 GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
10391049 const SubscriptionArguments& arguments, std::shared_ptr<Object> subscriptionObject) const ;
10401050 GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1041- const SubscriptionArguments& arguments, const SubscriptionArguments & directives,
1051+ const SubscriptionArguments& arguments, const Directives & directives,
10421052 std::shared_ptr<Object> subscriptionObject) const ;
10431053 GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1044- const SubscriptionFilterCallback & applyArguments,
1054+ const SubscriptionArgumentFilterCallback & applyArguments,
10451055 std::shared_ptr<Object> subscriptionObject) const ;
10461056 GRAPHQLSERVICE_EXPORT AwaitableDeliver deliver (await_async launch, const SubscriptionName& name,
1047- const SubscriptionFilterCallback & applyArguments,
1048- const SubscriptionFilterCallback & applyDirectives,
1057+ const SubscriptionArgumentFilterCallback & applyArguments,
1058+ const SubscriptionDirectiveFilterCallback & applyDirectives,
10491059 std::shared_ptr<Object> subscriptionObject) const ;
10501060
10511061private:
0 commit comments