diff --git a/include/graphqlservice/GraphQLService.h b/include/graphqlservice/GraphQLService.h index 381cae3f..99c8aff1 100644 --- a/include/graphqlservice/GraphQLService.h +++ b/include/graphqlservice/GraphQLService.h @@ -249,8 +249,17 @@ class [[nodiscard("unnecessary construction")]] await_async final using Directives = std::vector>; // Traversing a fragment spread adds a new set of directives. -using FragmentDefinitionDirectiveStack = std::list>; -using FragmentSpreadDirectiveStack = std::list; +struct [[nodiscard("unnecessary construction")]] FragmentDefinitionDirectiveStack +{ + const std::reference_wrapper directives; + const std::shared_ptr outer; +}; + +struct [[nodiscard("unnecessary construction")]] FragmentSpreadDirectiveStack +{ + const Directives directives; + const std::shared_ptr outer; +}; // Pass a common bundle of parameters to all of the generated Object::getField accessors in a // SelectionSet diff --git a/samples/today/TodayMock.cpp b/samples/today/TodayMock.cpp index 4d808469..236b45cf 100644 --- a/samples/today/TodayMock.cpp +++ b/samples/today/TodayMock.cpp @@ -907,15 +907,15 @@ NestedType::NestedType(service::FieldParams&& params, int depth) : depth(depth) { _capturedParams.push({ { params.operationDirectives }, - params.fragmentDefinitionDirectives->empty() + !params.fragmentDefinitionDirectives ? service::Directives {} - : service::Directives { params.fragmentDefinitionDirectives->front().get() }, - params.fragmentSpreadDirectives->empty() + : service::Directives { params.fragmentDefinitionDirectives->directives.get() }, + !params.fragmentSpreadDirectives ? service::Directives {} - : service::Directives { params.fragmentSpreadDirectives->front() }, - params.inlineFragmentDirectives->empty() + : service::Directives { params.fragmentSpreadDirectives->directives }, + !params.inlineFragmentDirectives ? service::Directives {} - : service::Directives { params.inlineFragmentDirectives->front() }, + : service::Directives { params.inlineFragmentDirectives->directives }, std::move(params.fieldDirectives) }); } diff --git a/src/GraphQLService.cpp b/src/GraphQLService.cpp index 9b704d8b..63bc919a 100644 --- a/src/GraphQLService.cpp +++ b/src/GraphQLService.cpp @@ -244,7 +244,7 @@ void await_worker_queue::resumePending() // Default to immediate synchronous execution. await_async::await_async() : _pimpl { std::static_pointer_cast( - std::make_shared>(std::make_shared())) } + std::make_shared>(std::make_shared())) } { } @@ -252,9 +252,9 @@ await_async::await_async() await_async::await_async(std::launch launch) : _pimpl { ((launch & std::launch::async) == std::launch::async) ? std::static_pointer_cast(std::make_shared>( - std::make_shared())) + std::make_shared())) : std::static_pointer_cast(std::make_shared>( - std::make_shared())) } + std::make_shared())) } { } @@ -896,6 +896,8 @@ class SelectionVisitor const TypeNames& _typeNames; const ResolverMap& _resolvers; + static const Directives s_emptyFragmentDefinitionDirectives; + std::shared_ptr _fragmentDefinitionDirectives; std::shared_ptr _fragmentSpreadDirectives; std::shared_ptr _inlineFragmentDirectives; @@ -903,6 +905,8 @@ class SelectionVisitor std::vector _values; }; +const Directives SelectionVisitor::s_emptyFragmentDefinitionDirectives {}; + SelectionVisitor::SelectionVisitor(const SelectionSetParams& selectionSetParams, const FragmentMap& fragments, const response::Value& variables, const TypeNames& typeNames, const ResolverMap& resolvers, std::size_t count) @@ -917,19 +921,17 @@ SelectionVisitor::SelectionVisitor(const SelectionSetParams& selectionSetParams, , _variables(variables) , _typeNames(typeNames) , _resolvers(resolvers) - , _fragmentDefinitionDirectives { selectionSetParams.fragmentDefinitionDirectives } - , _fragmentSpreadDirectives { selectionSetParams.fragmentSpreadDirectives } - , _inlineFragmentDirectives { selectionSetParams.inlineFragmentDirectives } + , _fragmentDefinitionDirectives { std::make_shared( + FragmentDefinitionDirectiveStack { std::cref(s_emptyFragmentDefinitionDirectives), + selectionSetParams.fragmentDefinitionDirectives }) } + , _fragmentSpreadDirectives { std::make_shared( + FragmentSpreadDirectiveStack { {}, selectionSetParams.fragmentSpreadDirectives }) } + , _inlineFragmentDirectives { std::make_shared( + FragmentSpreadDirectiveStack { {}, selectionSetParams.inlineFragmentDirectives }) } { - static const Directives s_emptyFragmentDefinitionDirectives; - // Traversing a SelectionSet from an Object type field should start tracking new fragment // directives. The outer fragment directives are still there in the FragmentSpreadDirectiveStack // if the field accessors want to inspect them. - _fragmentDefinitionDirectives->push_front(std::cref(s_emptyFragmentDefinitionDirectives)); - _fragmentSpreadDirectives->push_front({}); - _inlineFragmentDirectives->push_front({}); - _names.reserve(count); _values.reserve(count); } @@ -1126,8 +1128,12 @@ void SelectionVisitor::visitFragmentSpread(const peg::ast_node& fragmentSpread) return; } - _fragmentDefinitionDirectives->push_front(itr->second.getDirectives()); - _fragmentSpreadDirectives->push_front(directiveVisitor.getDirectives()); + _fragmentDefinitionDirectives = std::make_shared( + FragmentDefinitionDirectiveStack { itr->second.getDirectives(), + _fragmentDefinitionDirectives }); + _fragmentSpreadDirectives = std::make_shared( + FragmentSpreadDirectiveStack { directiveVisitor.getDirectives(), + _fragmentSpreadDirectives }); const std::size_t count = itr->second.getSelection().children.size(); @@ -1142,8 +1148,8 @@ void SelectionVisitor::visitFragmentSpread(const peg::ast_node& fragmentSpread) visit(*selection); } - _fragmentSpreadDirectives->pop_front(); - _fragmentDefinitionDirectives->pop_front(); + _fragmentSpreadDirectives = _fragmentSpreadDirectives->outer; + _fragmentDefinitionDirectives = _fragmentDefinitionDirectives->outer; } void SelectionVisitor::visitInlineFragment(const peg::ast_node& inlineFragment) @@ -1172,7 +1178,9 @@ void SelectionVisitor::visitInlineFragment(const peg::ast_node& inlineFragment) { peg::on_first_child(inlineFragment, [this, &directiveVisitor](const peg::ast_node& child) { - _inlineFragmentDirectives->push_front(directiveVisitor.getDirectives()); + _inlineFragmentDirectives = std::make_shared( + FragmentSpreadDirectiveStack { directiveVisitor.getDirectives(), + _inlineFragmentDirectives }); const std::size_t count = child.children.size(); @@ -1187,7 +1195,7 @@ void SelectionVisitor::visitInlineFragment(const peg::ast_node& inlineFragment) visit(*selection); } - _inlineFragmentDirectives->pop_front(); + _inlineFragmentDirectives = _inlineFragmentDirectives->outer; }); } } @@ -1438,9 +1446,9 @@ void OperationDefinitionVisitor::visit( _resolverContext, _params->state, _params->directives, - std::make_shared(), - std::make_shared(), - std::make_shared(), + std::shared_ptr {}, + std::shared_ptr {}, + std::shared_ptr {}, std::nullopt, _launch, }; @@ -1855,10 +1863,10 @@ AwaitableSubscribe Request::subscribe(RequestSubscribeParams params) ResolverContext::NotifySubscribe, registration->data->state, registration->data->directives, - std::make_shared(), - std::make_shared(), - std::make_shared(), - {}, + std::shared_ptr {}, + std::shared_ptr {}, + std::shared_ptr {}, + std::nullopt, launch, }; @@ -1917,10 +1925,10 @@ AwaitableUnsubscribe Request::unsubscribe(RequestUnsubscribeParams params) ResolverContext::NotifyUnsubscribe, registration->data->state, registration->data->directives, - std::make_shared(), - std::make_shared(), - std::make_shared(), - {}, + std::shared_ptr {}, + std::shared_ptr {}, + std::shared_ptr {}, + std::nullopt, params.launch, }; @@ -1980,9 +1988,9 @@ AwaitableDeliver Request::deliver(RequestDeliverParams params) const ResolverContext::Subscription, registration->data->state, registration->data->directives, - std::make_shared(), - std::make_shared(), - std::make_shared(), + std::shared_ptr {}, + std::shared_ptr {}, + std::shared_ptr {}, std::nullopt, params.launch, };