Skip to content

Commit 6141780

Browse files
committed
Initial fix
1 parent d769960 commit 6141780

File tree

4 files changed

+51
-16
lines changed

4 files changed

+51
-16
lines changed

juniper/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
extern crate core;
1010
extern crate self as juniper;
1111

12+
#[cfg(test)]
13+
mod for_benches_only {
14+
use bencher as _;
15+
}
16+
1217
use std::fmt;
1318

1419
// These are required by the code generated via the `juniper_codegen` macros.

juniper/src/types/async_await.rs

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,13 @@ where
159159
))
160160
}
161161

162+
#[derive(Debug)]
162163
struct AsyncField<S> {
163164
name: String,
164165
value: Option<Value<S>>,
165166
}
166167

168+
#[derive(Debug)]
167169
enum AsyncValue<S> {
168170
Field(AsyncField<S>),
169171
Nested(Value<S>),
@@ -184,16 +186,17 @@ where
184186
use futures::stream::{FuturesOrdered, StreamExt as _};
185187

186188
#[enum_derive(Future)]
187-
enum AsyncValueFuture<A, B, C, D> {
188-
Field(A),
189-
FragmentSpread(B),
190-
InlineFragment1(C),
191-
InlineFragment2(D),
189+
enum AsyncValueFuture<F1, F2, FS, IF1, IF2> {
190+
Field1(F1),
191+
Field2(F2),
192+
FragmentSpread(FS),
193+
InlineFragment1(IF1),
194+
InlineFragment2(IF2),
192195
}
193196

194197
let mut object = Object::with_capacity(selection_set.len());
195198

196-
let mut async_values = FuturesOrdered::<AsyncValueFuture<_, _, _, _>>::new();
199+
let mut async_values = FuturesOrdered::<AsyncValueFuture<_, _, _, _, _>>::new();
197200

198201
let meta_type = executor
199202
.schema()
@@ -258,7 +261,7 @@ where
258261
let is_non_null = meta_field.field_type.is_non_null();
259262

260263
let response_name = response_name.to_string();
261-
async_values.push_back(AsyncValueFuture::Field(async move {
264+
async_values.push_back(AsyncValueFuture::Field1(async move {
262265
// TODO: implement custom future type instead of
263266
// two-level boxing.
264267
let res = instance
@@ -327,6 +330,19 @@ where
327330
})),
328331
));
329332
}
333+
} else if let Ok(Value::Null) = sub_result {
334+
// NOTE: Executing a fragment cannot really result in a `Value::Null`,
335+
// because it represents a set of fields, so normal execution always
336+
// results in a `Value::Object`. However, a `Value::Null` is used here
337+
// to indicate that fragment execution failed somewhere and, because
338+
// of non-`null` types involved, its error should be propagated to the
339+
// parent field.
340+
async_values.push_back(AsyncValueFuture::Field2(future::ready(
341+
AsyncValue::Field(AsyncField {
342+
name: String::new(), // doesn't matter here
343+
value: None,
344+
}),
345+
)));
330346
} else if let Err(e) = sub_result {
331347
sub_exec.push_error_at(e, span.start);
332348
}
@@ -371,6 +387,19 @@ where
371387
})),
372388
));
373389
}
390+
} else if let Ok(Value::Null) = sub_result {
391+
// NOTE: Executing a fragment cannot really result in a `Value::Null`,
392+
// because it represents a set of fields, so normal execution
393+
// always results in a `Value::Object`. However, a `Value::Null`
394+
// is used here to indicate that fragment execution failed
395+
// somewhere and, because of non-`null` types involved, its error
396+
// should be propagated to the parent field.
397+
async_values.push_back(AsyncValueFuture::Field2(future::ready(
398+
AsyncValue::Field(AsyncField {
399+
name: String::new(), // doesn't matter here
400+
value: None,
401+
}),
402+
)));
374403
} else if let Err(e) = sub_result {
375404
sub_exec.push_error_at(e, span.start);
376405
}

juniper/src/validation/test_harness.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum FurColor {
6262
Spotted,
6363
}
6464

65+
#[expect(dead_code, reason = "GraphQL schema testing")]
6566
#[derive(Debug)]
6667
struct ComplexInput {
6768
required_field: bool,

tests/integration/tests/issue_1287.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct Query;
1717
#[graphql_object]
1818
impl Query {
1919
fn my_object() -> MyObject {
20-
MyObject {}
20+
MyObject
2121
}
2222

2323
fn just_a_field() -> i32 {
@@ -36,18 +36,18 @@ async fn error_propagates_same_way() {
3636
}";
3737
// language=GraphQL
3838
let with_fragment = r"
39-
query {
40-
myObject {
41-
...MyObjectFragment
42-
}
39+
query {
40+
myObject {
41+
...MyObjectFragment
42+
}
4343
justAField
4444
}
45-
46-
fragment MyObjectFragment on MyObject {
47-
erroringField
45+
46+
fragment MyObjectFragment on MyObject {
47+
erroringField
4848
}
4949
";
50-
50+
5151
let (expected, _) = juniper::execute(
5252
without_fragment,
5353
None,

0 commit comments

Comments
 (0)