Skip to content

Commit 98a2368

Browse files
captbaritonefacebook-github-bot
authored andcommitted
Enforce that terse resolvers don't expose list of non-nullable types
Reviewed By: alunyov Differential Revision: D50517685 fbshipit-source-id: c69a581c1824d756a6ca5a8f6e23abdaf8443291
1 parent 930864a commit 98a2368

10 files changed

+68
-139
lines changed

compiler/crates/relay-docblock/src/docblock_ir.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,9 @@ fn parse_terse_relay_resolver_ir(
366366
value: description.item,
367367
});
368368

369-
if let TypeAnnotation::NonNull(non_null) = field.type_ {
370-
return Err(vec![Diagnostic::error(
371-
IrParsingErrorMessages::FieldWithNonNullType,
372-
Location::new(type_str.location.source_location(), non_null.span),
373-
)]);
374-
}
369+
let type_name_location = type_str.location.with_span(field.type_.span());
370+
371+
validate_type_annotation(&field.type_, type_name_location)?;
375372

376373
validate_field_arguments(&field.arguments, location.source_location())?;
377374

@@ -534,25 +531,29 @@ fn parse_type_annotation(
534531
value.location.span().start,
535532
)?;
536533

537-
let valid_type_annotation = match &type_annotation {
538-
TypeAnnotation::Named(_) => type_annotation,
534+
validate_type_annotation(&type_annotation, value.location)?;
535+
536+
Ok(WithLocation::new(value.location, type_annotation))
537+
}
538+
539+
fn validate_type_annotation(
540+
type_annotation: &TypeAnnotation,
541+
location: Location,
542+
) -> DiagnosticsResult<()> {
543+
match type_annotation {
544+
TypeAnnotation::Named(_) => Ok(()),
539545
TypeAnnotation::List(item_type) => match &item_type.type_ {
540-
TypeAnnotation::NonNull(_) => {
541-
return Err(vec![Diagnostic::error(
542-
IrParsingErrorMessages::UnexpectedNonNullableItemInListEdgeTo {},
543-
value.location,
544-
)]);
545-
}
546-
_ => type_annotation,
546+
TypeAnnotation::NonNull(_) => Err(vec![Diagnostic::error(
547+
IrParsingErrorMessages::FieldWithNonNullableListItems {},
548+
location,
549+
)]),
550+
_ => Ok(()),
547551
},
548-
TypeAnnotation::NonNull(_) => {
549-
return Err(vec![Diagnostic::error(
550-
IrParsingErrorMessages::UnexpectedNonNullableEdgeTo {},
551-
value.location,
552-
)]);
553-
}
554-
};
555-
Ok(WithLocation::new(value.location, valid_type_annotation))
552+
TypeAnnotation::NonNull(_) => Err(vec![Diagnostic::error(
553+
IrParsingErrorMessages::FieldWithNonNullType {},
554+
location,
555+
)]),
556+
}
556557
}
557558

558559
fn get_optional_unpopulated_field_named(

compiler/crates/relay-docblock/src/errors.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ pub enum IrParsingErrorMessages {
7979
)]
8080
FieldWithNonNullType,
8181

82+
#[error(
83+
"Unexpected Relay Resolver field returning list with non-nullable items. Relay expects all plural Resolver fields to have nullable items since errors thrown by Resolvers are turned into `null` values."
84+
)]
85+
FieldWithNonNullableListItems,
86+
8287
#[error(
8388
"The compiler attempted to parse this `@RelayResolver` block as a {resolver_type}, but there were unexpected fields: {field_string}."
8489
)]
@@ -90,12 +95,6 @@ pub enum IrParsingErrorMessages {
9095
#[error("Defining arguments with default values for resolver fields is not supported, yet.")]
9196
ArgumentDefaultValuesNoSupported,
9297

93-
#[error("Unexpected non-nullable type given in `@edgeTo`.")]
94-
UnexpectedNonNullableEdgeTo,
95-
96-
#[error("Unexpected non-nullable item in list type given in `@edgeTo`.")]
97-
UnexpectedNonNullableItemInListEdgeTo,
98-
9998
#[error(
10099
"The type specified in the fragment (`{fragment_type_condition}`) and the type specified in `@{on_field_name}` (`{on_field_value}`) are different. Please make sure these are exactly the same."
101100
)]

compiler/crates/relay-docblock/tests/parse/fixtures/edge-to-non-null-plural-item.invalid.expected

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,9 @@
77
*/
88

99
// expected-to-throw
10-
// relay:allow_legacy_verbose_syntax
1110

1211
/**
13-
* @RelayResolver
14-
*
15-
* @onType User
16-
* @fieldName favorite_page
17-
* @edgeTo [Page!]
12+
* @RelayResolver User.favorite_page: [Page!]
1813
* @rootFragment myRootFragment
1914
*
2015
* The user's favorite page! They probably clicked something in the UI
@@ -29,10 +24,10 @@ graphql`
2924
}
3025
`
3126
==================================== ERROR ====================================
32-
✖︎ Unexpected non-nullable item in list type given in `@edgeTo`.
27+
✖︎ Unexpected Relay Resolver field returning list with non-nullable items. Relay expects all plural Resolver fields to have nullable items since errors thrown by Resolvers are turned into `null` values.
3328

34-
/path/to/test/fixture/edge-to-non-null-plural-item.invalid.js:16:12
35-
15 * @fieldName favorite_page
36-
16 │ * @edgeTo [Page!]
37-
│ ^^^^^^^
38-
17 │ * @rootFragment myRootFragment
29+
/path/to/test/fixture/edge-to-non-null-plural-item.invalid.js:11:39
30+
10*
31+
11 │ * @RelayResolver User.favorite_page: [Page!]
32+
^^^^^^^
33+
12 │ * @rootFragment myRootFragment

compiler/crates/relay-docblock/tests/parse/fixtures/edge-to-non-null-plural-item.invalid.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,9 @@
66
*/
77

88
// expected-to-throw
9-
// relay:allow_legacy_verbose_syntax
109

1110
/**
12-
* @RelayResolver
13-
*
14-
* @onType User
15-
* @fieldName favorite_page
16-
* @edgeTo [Page!]
11+
* @RelayResolver User.favorite_page: [Page!]
1712
* @rootFragment myRootFragment
1813
*
1914
* The user's favorite page! They probably clicked something in the UI

compiler/crates/relay-docblock/tests/parse/fixtures/edge-to-non-null.invalid.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ graphql`
2929
}
3030
`
3131
==================================== ERROR ====================================
32-
✖︎ Unexpected non-nullable type given in `@edgeTo`.
32+
✖︎ Unexpected Relay Resolver field with non-nullable type. Relay expects all Resolver fields to be nullable since errors thrown by Resolvers are turned into `null` values.
3333

3434
/path/to/test/fixture/edge-to-non-null.invalid.js:16:12
3535
15 │ * @fieldName favorite_page

compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected

Lines changed: 0 additions & 85 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
==================================== INPUT ====================================
2+
/**
3+
* Copyright (c) Meta Platforms, Inc. and affiliates.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
// expected-to-throw
10+
11+
/**
12+
* @RelayResolver User.mandatory_greeting: [String!]
13+
* Non-nullable
14+
*/
15+
==================================== ERROR ====================================
16+
✖︎ Unexpected Relay Resolver field returning list with non-nullable items. Relay expects all plural Resolver fields to have nullable items since errors thrown by Resolvers are turned into `null` values.
17+
18+
/path/to/test/fixture/terse-relay-resolver-non-nullable-list-item.invalid.js:11:44
19+
10 │ *
20+
11 │ * @RelayResolver User.mandatory_greeting: [String!]
21+
│ ^^^^^^^^^
22+
12 │ * Non-nullable

compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.js renamed to compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.invalid.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
// expected-to-throw
9+
810
/**
911
* @RelayResolver User.mandatory_greeting: [String!]
1012
* Non-nullable

compiler/crates/relay-docblock/tests/parse_test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<c8739ad0b60736cf314b0c9beeecd93a>>
7+
* @generated SignedSource<<fcaf5f3ed475c0aa56f387b6cd82691e>>
88
*/
99

1010
mod parse;
@@ -328,8 +328,8 @@ async fn terse_relay_resolver_non_nullable_list() {
328328
}
329329

330330
#[tokio::test]
331-
async fn terse_relay_resolver_non_nullable_list_item() {
332-
let input = include_str!("parse/fixtures/terse-relay-resolver-non-nullable-list-item.js");
333-
let expected = include_str!("parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected");
334-
test_fixture(transform_fixture, "terse-relay-resolver-non-nullable-list-item.js", "parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected", input, expected).await;
331+
async fn terse_relay_resolver_non_nullable_list_item_invalid() {
332+
let input = include_str!("parse/fixtures/terse-relay-resolver-non-nullable-list-item.invalid.js");
333+
let expected = include_str!("parse/fixtures/terse-relay-resolver-non-nullable-list-item.invalid.expected");
334+
test_fixture(transform_fixture, "terse-relay-resolver-non-nullable-list-item.invalid.js", "parse/fixtures/terse-relay-resolver-non-nullable-list-item.invalid.expected", input, expected).await;
335335
}

compiler/crates/relay-docblock/tests/to_schema/fixtures/client-edge-to-non-null-plural-server-object-relay-resolver.invalid.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ graphql`
2424
}
2525
`
2626
==================================== ERROR ====================================
27-
✖︎ Unexpected non-nullable type given in `@edgeTo`.
27+
✖︎ Unexpected Relay Resolver field with non-nullable type. Relay expects all Resolver fields to be nullable since errors thrown by Resolvers are turned into `null` values.
2828

2929
/path/to/test/fixture/client-edge-to-non-null-plural-server-object-relay-resolver.invalid.js:6:12
3030
5 │ * @fieldName favorite_pages

0 commit comments

Comments
 (0)