Add tracking of the current type being resolved in the Executor
This is not 100% accurate - it will be set to the literal type of what a field returns, so it might be wrapped in non-null/list when it technically shouldn't. For this use-case it's fine, but if we want to (officially) add it to the public API surface, we should probably make it accurate.
This commit is contained in:
parent
8cf2707faa
commit
d0e9202f41
3 changed files with 50 additions and 10 deletions
juniper/src
|
@ -14,7 +14,7 @@ use parser::SourcePosition;
|
||||||
|
|
||||||
use schema::meta::{Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, ListMeta,
|
use schema::meta::{Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, ListMeta,
|
||||||
MetaType, NullableMeta, ObjectMeta, PlaceholderMeta, ScalarMeta, UnionMeta};
|
MetaType, NullableMeta, ObjectMeta, PlaceholderMeta, ScalarMeta, UnionMeta};
|
||||||
use schema::model::{RootNode, SchemaType};
|
use schema::model::{RootNode, SchemaType, TypeType};
|
||||||
|
|
||||||
use types::base::GraphQLType;
|
use types::base::GraphQLType;
|
||||||
use types::name::Name;
|
use types::name::Name;
|
||||||
|
@ -46,6 +46,7 @@ where
|
||||||
fragments: &'a HashMap<&'a str, &'a Fragment<'a>>,
|
fragments: &'a HashMap<&'a str, &'a Fragment<'a>>,
|
||||||
variables: &'a Variables,
|
variables: &'a Variables,
|
||||||
current_selection_set: Option<&'a [Selection<'a>]>,
|
current_selection_set: Option<&'a [Selection<'a>]>,
|
||||||
|
current_type: TypeType<'a>,
|
||||||
schema: &'a SchemaType<'a>,
|
schema: &'a SchemaType<'a>,
|
||||||
context: &'a CtxT,
|
context: &'a CtxT,
|
||||||
errors: &'a RwLock<Vec<ExecutionError>>,
|
errors: &'a RwLock<Vec<ExecutionError>>,
|
||||||
|
@ -305,6 +306,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
fragments: self.fragments,
|
fragments: self.fragments,
|
||||||
variables: self.variables,
|
variables: self.variables,
|
||||||
current_selection_set: self.current_selection_set,
|
current_selection_set: self.current_selection_set,
|
||||||
|
current_type: self.current_type.clone(),
|
||||||
schema: self.schema,
|
schema: self.schema,
|
||||||
context: ctx,
|
context: ctx,
|
||||||
errors: self.errors,
|
errors: self.errors,
|
||||||
|
@ -313,9 +315,10 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn sub_executor(
|
pub fn field_sub_executor(
|
||||||
&self,
|
&self,
|
||||||
field_name: Option<&'a str>,
|
field_alias: &'a str,
|
||||||
|
field_name: &'a str,
|
||||||
location: SourcePosition,
|
location: SourcePosition,
|
||||||
selection_set: Option<&'a [Selection]>,
|
selection_set: Option<&'a [Selection]>,
|
||||||
) -> Executor<CtxT> {
|
) -> Executor<CtxT> {
|
||||||
|
@ -323,13 +326,36 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
fragments: self.fragments,
|
fragments: self.fragments,
|
||||||
variables: self.variables,
|
variables: self.variables,
|
||||||
current_selection_set: selection_set,
|
current_selection_set: selection_set,
|
||||||
|
current_type: self.schema.make_type(
|
||||||
|
&self.current_type
|
||||||
|
.innermost_concrete()
|
||||||
|
.field_by_name(field_name).expect("Field not found on inner type")
|
||||||
|
.field_type),
|
||||||
schema: self.schema,
|
schema: self.schema,
|
||||||
context: self.context,
|
context: self.context,
|
||||||
errors: self.errors,
|
errors: self.errors,
|
||||||
field_path: match field_name {
|
field_path: FieldPath::Field(field_alias, location, &self.field_path),
|
||||||
Some(name) => FieldPath::Field(name, location, &self.field_path),
|
}
|
||||||
None => self.field_path.clone(),
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn type_sub_executor(
|
||||||
|
&self,
|
||||||
|
type_name: Option<&'a str>,
|
||||||
|
selection_set: Option<&'a [Selection]>,
|
||||||
|
) -> Executor<CtxT> {
|
||||||
|
Executor {
|
||||||
|
fragments: self.fragments,
|
||||||
|
variables: self.variables,
|
||||||
|
current_selection_set: selection_set,
|
||||||
|
current_type: match type_name {
|
||||||
|
Some(type_name) => self.schema.type_by_name(type_name).expect("Type not found"),
|
||||||
|
None => self.current_type.clone(),
|
||||||
},
|
},
|
||||||
|
schema: self.schema,
|
||||||
|
context: self.context,
|
||||||
|
errors: self.errors,
|
||||||
|
field_path: self.field_path.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,6 +372,11 @@ impl<'a, CtxT> Executor<'a, CtxT> {
|
||||||
self.schema
|
self.schema
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn current_type(&self) -> &TypeType<'a> {
|
||||||
|
&self.current_type
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn variables(&self) -> &'a Variables {
|
pub fn variables(&self) -> &'a Variables {
|
||||||
self.variables
|
self.variables
|
||||||
|
@ -492,6 +523,11 @@ where
|
||||||
final_vars = &all_vars;
|
final_vars = &all_vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let root_type = match op.item.operation_type {
|
||||||
|
OperationType::Query => root_node.schema.query_type(),
|
||||||
|
OperationType::Mutation => root_node.schema.mutation_type().expect("No mutation type found")
|
||||||
|
};
|
||||||
|
|
||||||
let executor = Executor {
|
let executor = Executor {
|
||||||
fragments: &fragments
|
fragments: &fragments
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -499,6 +535,7 @@ where
|
||||||
.collect(),
|
.collect(),
|
||||||
variables: final_vars,
|
variables: final_vars,
|
||||||
current_selection_set: Some(&op.item.selection_set[..]),
|
current_selection_set: Some(&op.item.selection_set[..]),
|
||||||
|
current_type: root_type,
|
||||||
schema: &root_node.schema,
|
schema: &root_node.schema,
|
||||||
context: context,
|
context: context,
|
||||||
errors: &errors,
|
errors: &errors,
|
||||||
|
|
|
@ -35,6 +35,7 @@ pub struct SchemaType<'a> {
|
||||||
|
|
||||||
impl<'a> Context for SchemaType<'a> {}
|
impl<'a> Context for SchemaType<'a> {}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum TypeType<'a> {
|
pub enum TypeType<'a> {
|
||||||
Concrete(&'a MetaType<'a>),
|
Concrete(&'a MetaType<'a>),
|
||||||
NonNull(Box<TypeType<'a>>),
|
NonNull(Box<TypeType<'a>>),
|
||||||
|
|
|
@ -367,8 +367,9 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
|
|
||||||
let exec_vars = executor.variables();
|
let exec_vars = executor.variables();
|
||||||
|
|
||||||
let sub_exec = executor.sub_executor(
|
let sub_exec = executor.field_sub_executor(
|
||||||
Some(response_name),
|
response_name,
|
||||||
|
&f.name.item,
|
||||||
start_pos.clone(),
|
start_pos.clone(),
|
||||||
f.selection_set.as_ref().map(|v| &v[..]),
|
f.selection_set.as_ref().map(|v| &v[..]),
|
||||||
);
|
);
|
||||||
|
@ -434,8 +435,9 @@ fn resolve_selection_set_into<T, CtxT>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sub_exec = executor
|
let sub_exec = executor.type_sub_executor(
|
||||||
.sub_executor(None, start_pos.clone(), Some(&fragment.selection_set[..]));
|
fragment.type_condition.as_ref().map(|c| c.item),
|
||||||
|
Some(&fragment.selection_set[..]));
|
||||||
|
|
||||||
if let Some(ref type_condition) = fragment.type_condition {
|
if let Some(ref type_condition) = fragment.type_condition {
|
||||||
let sub_result = instance.resolve_into_type(
|
let sub_result = instance.resolve_into_type(
|
||||||
|
|
Loading…
Add table
Reference in a new issue