Skip to content

Conversation

N-Olbert
Copy link
Contributor

This is a follow-up of #8677 Summary of the changes (Less than 80 chars)

  • Retain location of the original VariableNode during rewrite
  • Detail 2

Closes #bugnumber (in this specific format)

This is a follow-up of #8677 and resolves the issue discussed during review with @tobias-tengler that for variables, the location always points to the outermost argument.

For example in

query($v: String!) { fieldWithNestedObjectInput(arg: { inner: { id: $v } } }
the location points to arg: { inner: { id: $v } }.

With this PR, the location of the original VariableNode is retained when rewriting it to the corresponding ValueNode, solving the issue so that the example above will correctly point to $v.

I am not sure whether it is acceptable to introduce a new method into such a central interface like IValueNode; alternatively, it could be extracted into a separate interface (e.g., ILocationAdjustable).

return false;
}

rewritten = rewritten.WithLocation(original.Location);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the original location inserted again. There are multiple issues with this.

  1. The location is not really correct after a rewrite. Think about multiple rewrites happening that shorten and lengthening strings. The location after a rewrite is inherently incorrect.

  2. Wither now does an additional copy which means that we create an additional object for this mutation, potentially in the hot path on large syntax trees that have maybe hundreds of these mutations.

  3. Location on a production server should be simply shut off to save perf.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to read into the issue a bit more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding 1: Shouldn’t the location always reflect the position of the associated (input) syntax element within the original document? For example, given

query($v: String!) { foo(arg: { bar: { id: $v } }) }

with

{ "v": "MyLongString" }

supplied as an argument, I would expect that in the rewritten query

query($v: String!) { foo(arg: { bar: { id: "MyLongString" } }) }

the location of "MyLongString" would still point back to $v (at least as a dev).
If this assumption is incorrect, the entire PR can be closed.
I dont see how multiple rewrites should do harm here, as we always stay with the original location - can you give a sample? My assumption here is that for simple variable-to-value rewrites (any only for such!, probably I should just adjust the first case of the switch), retaining the original variable location is the most useful behavior.

Regarding 2:
I see the concern. A possible workaround would be to pass the original location directly when creating the rewritten value node. This would avoid introducing any additional overhead and doesnt look too complicated

Regarding 3:
Is this possible today? At least for a public API I think this would be problematic, as error messages require a loaction (well OK, its not strictly required, ist only "should" be present according to the spec)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding 3, yes, this is a well used practice that is also used by the GraphQL reference implementation.

https://github.com/graphql/graphql-js/blob/60ae6c48b9c78332bf3d6036e7d931a3617d0674/src/language/parser.ts#L79

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants