Check type before resolving in inline fragments to fix panic when using inline fragments with interfaces (, )

This commit is contained in:
Lukas Kalbertodt 2020-12-09 19:26:59 +01:00 committed by GitHub
parent 4ffd276a5b
commit 2c15ea798c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 29 deletions

View file

@ -51,6 +51,10 @@ where
QueryT::name(info)
}
fn concrete_type_name(&self, context: &Self::Context, info: &Self::TypeInfo) -> String {
self.query_type.concrete_type_name(context, info)
}
fn resolve_field(
&self,
info: &Self::TypeInfo,

View file

@ -1,6 +1,7 @@
use crate::{
ast::InputValue,
executor::Variables,
graphql_value,
schema::model::RootNode,
tests::fixtures::starwars::schema::{Database, Query},
types::scalars::{EmptyMutation, EmptySubscription},
@ -731,3 +732,36 @@ async fn test_object_typename() {
))
);
}
#[tokio::test]
async fn interface_inline_fragment_friends() {
let doc = r#"{
human(id: "1002") {
friends {
name
... on Human { homePlanet }
... on Droid { primaryFunction }
}
}
}"#;
let database = Database::new();
let schema = RootNode::new(
Query,
EmptyMutation::<Database>::new(),
EmptySubscription::<Database>::new(),
);
assert_eq!(
crate::execute(doc, None, &schema, &Variables::new(), &database).await,
Ok((
graphql_value!({"human": {
"friends": [
{"name": "Luke Skywalker", "homePlanet": "Tatooine"},
{"name": "Leia Organa", "homePlanet": "Alderaan"},
{"name": "R2-D2", "primaryFunction": "Astromech"},
],
}}),
vec![],
))
);
}

View file

@ -323,6 +323,9 @@ where
);
if let Some(ref type_condition) = fragment.type_condition {
// Check whether the type matches the type condition.
let concrete_type_name = instance.concrete_type_name(sub_exec.context(), info);
if type_condition.item == concrete_type_name {
let sub_result = instance
.resolve_into_type_async(
info,
@ -344,6 +347,7 @@ where
} else if let Err(e) = sub_result {
sub_exec.push_error_at(e, *start_pos);
}
}
} else {
async_values.push(AsyncValueFuture::InlineFragment2(async move {
let value = resolve_selection_set_into_async(

View file

@ -532,6 +532,9 @@ where
);
if let Some(ref type_condition) = fragment.type_condition {
// Check whether the type matches the type condition.
let concrete_type_name = instance.concrete_type_name(sub_exec.context(), info);
if type_condition.item == concrete_type_name {
let sub_result = instance.resolve_into_type(
info,
type_condition.item,
@ -546,6 +549,7 @@ where
} else if let Err(e) = sub_result {
sub_exec.push_error_at(e, *start_pos);
}
}
} else if !resolve_selection_set_into(
instance,
info,