rmosolgo / graphql-ruby

Ruby implementation of GraphQL
http://graphql-ruby.org
MIT License
5.38k stars 1.39k forks source link

C Parser incompatibility with AST nodes #5043

Closed swalkinshaw closed 3 months ago

swalkinshaw commented 3 months ago

Describe the bug I believe https://github.com/rmosolgo/graphql-ruby/pull/4949 created an incompatibility with the C parser since the @source is expected to exist on every language node which points to the parser instance.

Versions graphql version: >= 2.3.3

Steps to reproduce Use the C parser to parse a document that causes a FragmentSpreadsArePossibleError (and possibly other validation errors)

Expected behavior It parses ๐Ÿ˜„

Actual behavior

NoMethodError ยท undefined method 'line_at' for nil

gems/graphql-2.3.10/lib/graphql/language/nodes.rb:37 GraphQL::Language::Nodes::AbstractNode#line
gems/graphql-2.3.10/lib/graphql/static_validation/error.rb:39 block in GraphQL::StaticValidation::Error#locations
gems/graphql-2.3.10/lib/graphql/static_validation/error.rb:38 Array#map
gems/graphql-2.3.10/lib/graphql/static_validation/error.rb:38 GraphQL::StaticValidation::Error#locations
gems/graphql-2.3.10/lib/graphql/static_validation/error.rb:29 GraphQL::StaticValidation::Error#to_h
gems/graphql-2.3.10/lib/graphql/static_validation/rules/fragment_spreads_are_possible_error.rb:25 GraphQL::StaticValidation::FragmentSpreadsArePossibleError#to_h

Additional context Did the C parser set source_string before? It does look like there was better conditional checking if source_string existed vs always assuming that @source does now.

rmosolgo commented 3 months ago

It's supposed to work by the C parser assigning @line and @col during parsing, causing the ||= @source.line_at(...) to never evaluate. But it must be missing a spot ๐Ÿค”

rmosolgo commented 3 months ago

Could you share an example string that causes this error? All of GraphQL-Ruby's tests run with with GraphQL::CParser on CI and don't encounter this error, including the tests for this validation (which aren't very extensive, admittedly: https://github.com/rmosolgo/graphql-ruby/blob/master/spec/graphql/static_validation/rules/fragment_spreads_are_possible_spec.rb)

But I added some debugging with

line || raise("No line given: #{line.inspect}")

and couldn't find any cases where it wasn't passed in by the parser ๐Ÿ˜–

swalkinshaw commented 3 months ago

Okay I mistakenly assumed this had to be caused by the C parser and it's not. Sorry for sending you down this rabbit hole ๐Ÿ˜“

The root cause of this is programmatically creating an invalid document from AST nodes. Now, we shouldn't be creating invalid documents of course but I'm kind of curious if this exposes an assumption that nodes always come from a parsed source or not.

rmosolgo commented 3 months ago

Ah, that makes sense. I guess the best thing would be to return nil in this case -- certainly not to raise this error ๐Ÿคฆ

swalkinshaw commented 3 months ago

For now I'm working around it by setting both pos attributes to 0 but I do think preserving the nil behaviour makes sense

swalkinshaw commented 3 months ago

Thank you โค๏ธ