Complete October 2021 GraphQL spec compliance#1930
Conversation
…ion/@skip/@include 🤖 Generated with Claude Code
🤖 Generated with Claude Code
🤖 Generated with Claude Code
🤖 Generated with Claude Code
There was a problem hiding this comment.
Pull request overview
Updates the subscription validation rule to align SingleFieldSubscription with the October 2021 GraphQL spec, particularly around fragment expansion at the subscription root and additional root-level restrictions.
Changes:
- Rework
SingleFieldSubscriptionvalidation to expand inline/named fragments before counting top-level subscription fields. - Add new validation failures for introspection fields and
@skip/@includedirectives at the subscription root. - Add/extend PHPUnit coverage for fragment expansion, recursion handling, introspection fields, directive rejection, and the “no subscription type” skip behavior; document the change in the changelog.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/Validator/Rules/SingleFieldSubscription.php |
Rewrites validation logic to expand fragments, reject introspection fields, and reject @skip/@include at the subscription root. |
tests/Validator/SingleFieldSubscriptionsTest.php |
Adds extensive tests mirroring graphql-js coverage for the updated subscription rule behavior. |
CHANGELOG.md |
Records the spec-compliance fix under Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Matches graphql-js behavior: only expand inline fragments and fragment spreads whose type condition matches the subscription root type. 🤖 Generated with Claude Code
Covers the no-type-condition and non-matching type condition paths to improve patch coverage. 🤖 Generated with Claude Code
🤖 Generated with Claude Code
🤖 Generated with Claude Code
🤖 Generated with Claude Code
🤖 Generated with Claude Code
The commonmark.org URL in the @deprecated directive description must match graphql-js exactly since it's part of the introspection schema. 🤖 Generated with Claude Code
October 2021 is fully compliant, September 2025 tracked in #1931. 🤖 Generated with Claude Code
simPod
left a comment
There was a problem hiding this comment.
AI review note: the @skip/@include rejection appears to be current-draft / graphql-js 17 behavior, not October 2021 behavior. If the intent is to match current graphql-js, the code direction makes sense, but the README/changelog wording around “October 2021 compliance” is misleading.
| // Check for @skip/@include on top-level selections | ||
| /** @var array<int, DirectiveNode> $forbiddenDirectiveNodes */ | ||
| $forbiddenDirectiveNodes = []; | ||
| foreach ($node->selectionSet->selections as $selection) { |
There was a problem hiding this comment.
AI review:
@skip/@include are only checked on the operation’s immediate top-level selections here, but subscription root fields can also be contributed by expanded fragments. That means this currently accepts a root field with a forbidden directive when it comes from a fragment:
subscription sub {
...frag
}
fragment frag on SubscriptionRoot {
catSubscribe @include(if: true) {
meows
}
}The draft/reference CollectSubscriptionFields logic applies the directive check during recursive collection, so fragment-contributed root selections should be checked as they are collected too.
Full October 2021 Spec Compliance 🎉
This PR completes
webonyx/graphql-php's compliance with the October 2021 GraphQL specification.After auditing the spec against the implementation,
SingleFieldSubscription(section 5.2.3.1) was the last remaining gap.Changes
Rewrite
SingleFieldSubscriptionvalidation to match the reference graphql-js implementation:__schema,__type,__typename) at the subscription root@skip/@includedirectives on top-level selectionsTest plan
SingleFieldSubscriptionsRule-test.ts(40 assertions)make testmake stan🤖 Generated with Claude Code