graphql v1.2.0 Release Notes
Release Date: 2016-11-07 // over 7 years ago-
๐ฅ Breaking changes
A breaking change from 1.1.0 was reverted: two-character
"\\u"
is longer treated as the Unicode escape character #372Due to the execution bug described below, the internal representation of a query has changed. Although
Node
responds to the same methods, tree is built differently and query analyzers visit it differently. #373, #379
The difference is in cases like this:
outer { ... on A { inner1 { inner2 } } ... on B { inner1 { inner3 } } }
Previously, visits would be:
outer
, which has one child:inner1
, which has two definitions (one onA
, another onB
), then visit its twochildren
:inner2
which has one definition (on the return type ofinner1
)inner3
which has one definition (on the return type ofinner1
)
This can be wrong for some cases. For example, if
A
andB
are mutually exclusive (both object types, or union types with no shared members), theninner2
andinner3
will never be executed together.Now, the visit goes like this:
outer
which has two entries intyped_children
, one onA
and another onB
. Visit eachtyped_chidren
branch:inner1
, then its onetyped_children
branch:inner2
inner1
, then its onetyped_children
branch:inner3
As you can see, we visit
inner1
twice, once for each type condition.inner2
andinner3
are no longer visited as siblings. Instead they're visited as ... cousins? (They share a grandparent, not a parent.)Although
Node#children
is still present, it may not contain all children actually resolved at runtime, since multipletyped_children
branches could apply to the same runtime type (eg, two branches on interface types can apply to the same object type). To track all children, you have to do some bookkeeping during visitation, seeQueryComplexity
for an example.You can see PR #373 for how built-in analyzers were changed to reflect this.
๐ Deprecations
- ๐
InternalRepresentation::Node#children
andInternalRepresentation::Node#definitions
are deprecated due to the bug described below and the breaking change described above. Instead, useInternalRepresentation::Node#typed_children
andInternalRepresentation::Node#defininition
. #373
๐ New features
0๏ธโฃ
null
support for the whole library: as a query literal, variable value, and argument default value. To check for the presence of a nullable, useArguments#key?
#369GraphQL::Schema::UniqueWithinType.default_id_separator
may be assigned to a custom value #381Context#add_error(err)
may be used to add aGraphQL::ExecutionError
to the response's"errors"
key (and the resolve function can still return a value) #367The third argument of
resolve
is now aFieldResolutionContext
, which behaves just like aQuery::Context
, except that it is not modified during query execution. This means you can capture a reference to that context and access some field-level details after the fact:#path
,#ast_node
,#irep_node
. (Other methods are delegated to the underlyingQuery::Context
) #379TimeoutMiddleware
's second argument is a proxied query object: it's#context
method returns theFieldResolutionContext
(see above) for the timed-out field. Other methods are delegated to the underlyingQuery
#379
๐ Bug fixes
- ๐ Fix deep selection merging on divergently-typed fragments. #370, #373, #379 Previously, nested selections on different fragments were not distinguished. Consider a case like this:
... on A { inner1 { inner2 } } ... on B { inner1 { inner3 } }
Previously, an object of type
A
would resolveinner1
, then the result would receive bothinner2
andinner3
. The same was true for an object of typeB
.Now, those are properly distinguished. An object of type
A
resolvesinner1
, then its result receivesinner2
. An object of typeB
receivesinner1
, theninner3
.