Skip to content

fix(replaceVariables): preserve sources for fragment variable values #4389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 12, 2025

Conversation

yaacovCR
Copy link
Contributor

@yaacovCR yaacovCR commented May 5, 2025

The new flow for coercing input literals -- see #3814 -- introduces a replaceVariables() prior to calling coerceInputLiteral() such that we go:

from ValueNode => ConstValueNode => coerced value

The main advantages being that:
(1) we can trivially support embedding variables within complex scalars -- despite this being non-spec defined behavior!
(2) userland implementations of custom scalar coerceInputLiteral() methods do not need to worry about handling variables or fragment variables.

Prior to this PR, we did not properly handle this in the case of fragment definition variables/fragment spread arguments. replaceVariableValues() assumes that the uncoerced value is preserved as source, but instead of grabbing this value from the argument on the spread, we were incorrectly attempting to retrieve the already stored value from existing variables.

This was not caught because we previously did not have any actual tests for this custom unspecified behavior and were using incorrect types and bespoke builders in our tests for replaceVariables().

This PR:

(a) fixes the bug by storing the argument from the spread
(b) fixes our bespoke builders in replaceVariables()
(c) add explicit tests for embedding variables within custom scalars to protect against future changes.

As a post-script, because within getFragmentVariableValues() we now end up within a ValueNode stored on source, to coerce this value, we can extract a new helper coerceArgumentValue() from experimentalGetArgumentValues(), rather than calling it after we are done for all the values, which has some additional overhead.

This has the side benefit of removing the need for a separate experimentalGetArgumentValues() function altogether. We initially introduced it to have a more flexible signature for getArgumentValues() that encompasses argument for fragment spreads, but now this is taken care of using our more directed helper.

@yaacovCR yaacovCR requested a review from a team as a code owner May 5, 2025 21:27
@yaacovCR yaacovCR force-pushed the fragment-variables branch from e6fa60a to 3f6e32b Compare May 5, 2025 21:28
@yaacovCR yaacovCR added the PR: bug fix 🐞 requires increase of "patch" version number label May 5, 2025
@yaacovCR yaacovCR force-pushed the fragment-variables branch from 44d33e4 to 32541f6 Compare May 6, 2025 08:02
@yaacovCR
Copy link
Contributor Author

yaacovCR commented May 6, 2025

I broke this up into separate commits to aid review.

First commit: introduces the failing test.
Second commit: introduces a new type FragmentVariableValues to the code base, for now identical to VariableValues
Third commit: fix bug by updating FragmentVariableValues so that the source value for a variable is of type ValueNode
Fourth commit: optimize getFragmentVariableValues()/remove experimentalGetArgumentValues()

yaacovCR added 3 commits May 6, 2025 11:49
by introducing internal helper coerceArgument

goals:

(1) removes need to build temporary array of `varSignatures` in `getFragmentVariableValues()`
(2) removes need to rebuild map of `varSignatures` when `getFragmentVariableValues()` would call `experimentalGetArgumentValues()`.
(3) reuses `argumentNode` variable instead of duplicating selection from the `argNodeMap`
(4) allows us to preserve original `getArgumentValues()` signature and dispense with `experimentalGetArgumentValues()` altogether.
@yaacovCR yaacovCR changed the title fix: preserve sources for fragment variable values fix(replaceVariables): preserve sources for fragment variable values May 6, 2025
yaacovCR added a commit to yaacovCR/transform that referenced this pull request May 6, 2025
for now we will disable support for fragment arguments, pending graphql/graphql-js#4389
yaacovCR added a commit to yaacovCR/transform that referenced this pull request May 7, 2025
* minimize TransformationContext

* consolidate loops

* switch from filtering to actual routing of root fields

* for now we will disable support for fragment arguments, pending graphql/graphql-js#4389

* add changeset

* fix support for fragment argument

* lint
@yaacovCR yaacovCR merged commit f808084 into graphql:main May 12, 2025
15 of 16 checks passed
@yaacovCR yaacovCR deleted the fragment-variables branch May 12, 2025 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: bug fix 🐞 requires increase of "patch" version number
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants