diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 79953a4e0..6684075fd 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -328,7 +328,7 @@ GraphQL supports two abstract types: interfaces and unions. An `Interface` defines a list of fields; `Object` types and other Interface types which implement this Interface are guaranteed to implement those fields. Whenever a field claims it will return an Interface type, it will return a valid -implementing Object type during execution. +implementing Object type during _execution_. A `Union` defines a list of possible types; similar to interfaces, whenever the type system claims a union will be returned, one of the possible types will be @@ -505,7 +505,7 @@ information on the serialization of scalars in common JSON and other formats. If a GraphQL service expects a scalar type as input to an argument, coercion is observable and the rules must be well defined. If an input value does not match a coercion rule, a _request error_ must be raised (input values are validated -before execution begins). +before _execution_ begins). GraphQL has different constant literals to represent integer and floating-point input values, and coercion rules may apply differently depending on which type @@ -810,7 +810,7 @@ And will yield the subset of each object type queried: **Field Ordering** When querying an Object, the resulting mapping of fields are conceptually -ordered in the same order in which they were encountered during execution, +ordered in the same order in which they were encountered during _execution_, excluding fragments for which the type does not apply and fields or fragments that are skipped via `@skip` or `@include` directives. This ordering is correctly produced when using the {CollectFields()} algorithm. @@ -2058,8 +2058,8 @@ directive @example on Directives can also be used to annotate the type system definition language as well, which can be a useful tool for supplying additional metadata in order to -generate GraphQL execution services, produce client generated runtime code, or -many other useful extensions of the GraphQL semantics. +generate GraphQL services, produce client generated runtime code, or many other +useful extensions of the GraphQL semantics. In this example, the directive `@example` annotates field and argument definitions: @@ -2122,7 +2122,7 @@ directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT ``` The `@skip` _built-in directive_ may be provided for fields, fragment spreads, -and inline fragments, and allows for conditional exclusion during execution as +and inline fragments, and allows for conditional exclusion during _execution_ as described by the `if` argument. In this example `experimentalField` will only be queried if the variable @@ -2142,7 +2142,7 @@ directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT The `@include` _built-in directive_ may be provided for fields, fragment spreads, and inline fragments, and allows for conditional inclusion during -execution as described by the `if` argument. +_execution_ as described by the `if` argument. In this example `experimentalField` will only be queried if the variable `$someTest` has the value `true` diff --git a/spec/Section 4 -- Introspection.md b/spec/Section 4 -- Introspection.md index d7f8e629f..39e2ca249 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -72,7 +72,7 @@ GraphQL supports type name introspection within any _selection set_ in an operation, with the single exception of selections at the root of a subscription operation. Type name introspection is accomplished via the meta-field `__typename: String!` on any Object, Interface, or Union. It returns the name of -the concrete Object type at that point during execution. +the concrete Object type at that point during _execution_. This is most often used when querying against Interface or Union types to identify which actual Object type of the possible types has been returned. diff --git a/spec/Section 5 -- Validation.md b/spec/Section 5 -- Validation.md index 206814d6d..b7e8c7e91 100644 --- a/spec/Section 5 -- Validation.md +++ b/spec/Section 5 -- Validation.md @@ -7,7 +7,8 @@ given GraphQL schema. An invalid request is still technically executable, and will always produce a stable result as defined by the algorithms in the Execution section, however that result may be ambiguous, surprising, or unexpected relative to a request -containing validation errors, so execution should only occur for valid requests. +containing validation errors, so _execution_ should only occur for valid +requests. Typically validation is performed in the context of a request immediately before execution, however a GraphQL service may execute a request without explicitly @@ -108,7 +109,7 @@ input FindDogInput { GraphQL execution will only consider the executable definitions Operation and Fragment. Type system definitions and extensions are not executable, and are not -considered during execution. +considered during _execution_. To avoid ambiguity, a document containing {TypeSystemDefinitionOrExtension} is invalid for execution. @@ -579,7 +580,7 @@ type that is either an Object, Interface or Union type. **Explanatory Text** If multiple field selections with the same _response name_ are encountered -during execution, the field and arguments to execute and the resulting value +during _execution_, the field and arguments to execute and the resulting value should be unambiguous. Therefore any two field selections which might both be encountered for the same object are only valid if they are equivalent. diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index b2c533bb3..c3b7c024e 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -18,9 +18,9 @@ A GraphQL service generates a response from a request via execution. - {extensions} (optional): A map reserved for implementation-specific additional information. -Given this information, the result of {ExecuteRequest(schema, document, -operationName, variableValues, initialValue)} produces the response, to be -formatted according to the Response section below. +Given this information, the result of {Request(schema, document, operationName, +variableValues, initialValue)} produces the response, to be formatted according +to the Response section below. Implementations should not add additional properties to a _request_, which may conflict with future editions of the GraphQL specification. Instead, @@ -39,27 +39,44 @@ and have no effect on the observable execution, validation, or response of a GraphQL document. Descriptions and comments on executable documents MAY be used for non-observable purposes, such as logging and other developer tools. -## Executing Requests +## Processing Requests -To execute a request, the executor must have a parsed {Document} and a selected + + + + +To process a request, the executor must have a parsed {Document} and a selected operation name to run if the document defines multiple operations, otherwise the document is expected to only contain a single operation. The result of the -request is determined by the result of executing this operation according to the -"Executing Operations” section below. +request is determined by the result of performing this operation according to +the "Performing Operations” section below. + +The {Request()} algorithm contains the preamble for _execution_, handling +concerns such as determining the operation and coercing the inputs, before +passing the request on to the relevant algorithm for the operation's type which +then performs any other necessary preliminary steps (for example establishing +the source event stream for subscription operations) and then initiates +_execution_. + +Note: An error raised before _execution_ begins will typically be a _request +error_, and once _execution_ begins will typically be an _execution error_. + +:: We define _execution_ as the process of executing the operation's _root +selection set_ through {ExecuteRootSelectionSet()}, and hence _execution_ begins +when {ExecuteRootSelectionSet()} is called for the first time in a request. -ExecuteRequest(schema, document, operationName, variableValues, initialValue): +Request(schema, document, operationName, variableValues, initialValue): - Let {operation} be the result of {GetOperation(document, operationName)}. - Let {coercedVariableValues} be the result of {CoerceVariableValues(schema, operation, variableValues)}. - If {operation} is a query operation: - - Return {ExecuteQuery(operation, schema, coercedVariableValues, - initialValue)}. + - Return {Query(operation, schema, coercedVariableValues, initialValue)}. - Otherwise if {operation} is a mutation operation: - - Return {ExecuteMutation(operation, schema, coercedVariableValues, - initialValue)}. + - Return {Mutation(operation, schema, coercedVariableValues, initialValue)}. - Otherwise if {operation} is a subscription operation: - - Return {Subscribe(operation, schema, coercedVariableValues, initialValue)}. + - Return {Subscription(operation, schema, coercedVariableValues, + initialValue)}. GetOperation(document, operationName): @@ -74,27 +91,28 @@ GetOperation(document, operationName): ### Validating Requests -As explained in the Validation section, only requests which pass all validation -rules should be executed. If validation errors are known, they should be -reported in the list of "errors" in the response and the request must fail -without execution. +As explained in the Validation section, only operations from documents which +pass all validation rules should be executed. If validation errors are known, +they should be reported in the list of "errors" in the response and the request +must fail without execution. Typically validation is performed in the context of a request immediately before -execution, however a GraphQL service may execute a request without immediately -validating it if that exact same request is known to have been validated before. -A GraphQL service should only execute requests which _at some point_ were known -to be free of any validation errors, and have since not changed. +calling {Request()}, however a GraphQL service may process a request without +immediately validating the document if that exact same document is known to have +been validated before. A GraphQL service should only execute operations which +_at some point_ were known to be free of any validation errors, and have since +not changed. -For example: the request may be validated during development, provided it does -not later change, or a service may validate a request once and memoize the -result to avoid validating the same request again in the future. +For example: the document may be validated during development, provided it does +not later change, or a service may validate a document once and memoize the +result to avoid validating the same document again in the future. ### Coercing Variable Values If the operation has defined any variables, then the values for those variables need to be coerced using the input coercion rules of variable's declared type. If a _request error_ is encountered during input coercion of variable values, -then the operation fails without execution. +then the request fails without _execution_. CoerceVariableValues(schema, operation, variableValues): @@ -131,7 +149,11 @@ CoerceVariableValues(schema, operation, variableValues): Note: This algorithm is very similar to {CoerceArgumentValues()}. -## Executing Operations +## Performing Operations + + + + The type system, as described in the "Type System" section of the spec, must provide a query root operation type. If mutations or subscriptions are @@ -144,9 +166,9 @@ If the operation is a query, the result of the operation is the result of executing the operation’s _root selection set_ with the query root operation type. -An initial value may be provided when executing a query operation. +An initial value may be provided when performing a query operation. -ExecuteQuery(query, schema, variableValues, initialValue): +Query(query, schema, variableValues, initialValue): - Let {queryType} be the root Query type in {schema}. - Assert: {queryType} is an Object type. @@ -164,7 +186,7 @@ It is expected that the top level fields in a mutation operation perform side-effects on the underlying data system. Serial execution of the provided mutations ensures against race conditions during these side-effects. -ExecuteMutation(mutation, schema, variableValues, initialValue): +Mutation(mutation, schema, variableValues, initialValue): - Let {mutationType} be the root Mutation type in {schema}. - Assert: {mutationType} is an Object type. @@ -176,12 +198,13 @@ ExecuteMutation(mutation, schema, variableValues, initialValue): If the operation is a subscription, the result is an _event stream_ called the _response stream_ where each event in the event stream is the result of -executing the operation for each new event on an underlying _source stream_. +executing the operation’s _root selection set_ for each new event on an +underlying _source stream_. -Executing a subscription operation creates a persistent function on the service +Performing a subscription operation creates a persistent function on the service that maps an underlying _source stream_ to a returned _response stream_. -Subscribe(subscription, schema, variableValues, initialValue): +Subscription(subscription, schema, variableValues, initialValue): - Let {sourceStream} be the result of running {CreateSourceEventStream(subscription, schema, variableValues, initialValue)}. @@ -190,9 +213,9 @@ Subscribe(subscription, schema, variableValues, initialValue): variableValues)}. - Return {responseStream}. -Note: In a large-scale subscription system, the {Subscribe()} and -{ExecuteSubscriptionEvent()} algorithms may be run on separate services to -maintain predictable scaling properties. See the section below on Supporting +Note: In a large-scale subscription system, the {Subscription()} and +{SubscriptionEvent()} algorithms may be run on separate services to maintain +predictable scaling properties. See the section below on Supporting Subscriptions at Scale. As an example, consider a chat application. To subscribe to new messages posted @@ -313,8 +336,7 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues): - Let {responseStream} be a new _event stream_. - When {sourceStream} emits {sourceValue}: - Let {executionResult} be the result of running - {ExecuteSubscriptionEvent(subscription, schema, variableValues, - sourceValue)}. + {SubscriptionEvent(subscription, schema, variableValues, sourceValue)}. - If internal {error} was raised: - Cancel {sourceStream}. - Complete {responseStream} with {error}. @@ -328,12 +350,12 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues): - Complete {responseStream} normally. - Return {responseStream}. -Note: Since {ExecuteSubscriptionEvent()} handles all _execution error_, and -_request error_ only occur during {CreateSourceEventStream()}, the only -remaining error condition handled from {ExecuteSubscriptionEvent()} are internal -exceptional errors not described by this specification. +Note: Since {SubscriptionEvent()} handles all _execution error_, and _request +error_ only occur during {CreateSourceEventStream()}, the only remaining error +condition handled from {SubscriptionEvent()} are internal exceptional errors not +described by this specification. -ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue): +SubscriptionEvent(subscription, schema, variableValues, initialValue): - Let {subscriptionType} be the root Subscription type in {schema}. - Assert: {subscriptionType} is an Object type. @@ -341,8 +363,8 @@ ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue): - Return {ExecuteRootSelectionSet(variableValues, initialValue, subscriptionType, rootSelectionSet, "normal")}. -Note: The {ExecuteSubscriptionEvent()} algorithm is intentionally similar to -{ExecuteQuery()} since this is how each event result is produced. +Note: The {SubscriptionEvent()} algorithm is intentionally similar to {Query()} +since this is how each event result is produced. #### Unsubscribe @@ -638,7 +660,7 @@ A valid GraphQL executor can resolve the four fields in whatever order it chose (however of course `birthday` must be resolved before `month`, and `address` before `street`). -When executing a mutation, the selections in the top most selection set will be +When performing a mutation, the selections in the top most selection set will be executed in serial order, starting with the first appearing field textually. When executing a collected fields map serially, the executor must consider each @@ -788,9 +810,9 @@ CoerceArgumentValues(objectType, field, variableValues): Any _request error_ raised as a result of input coercion during {CoerceArgumentValues()} should be treated instead as an _execution error_. -Note: Variable values are not coerced because they are expected to be coerced -before executing the operation in {CoerceVariableValues()}, and valid operations -must only allow usage of variables of appropriate types. +Note: Variable values are not coerced because they are expected to be coerced by +{CoerceVariableValues()} before _execution_ begins, and valid operations must +only allow usage of variables of appropriate types. Note: Implementations are encouraged to optimize the coercion of an argument's default value by doing so only once and caching the resulting coerced value. diff --git a/spec/Section 7 -- Response.md b/spec/Section 7 -- Response.md index f79100cd2..3f974aa37 100644 --- a/spec/Section 7 -- Response.md +++ b/spec/Section 7 -- Response.md @@ -24,11 +24,11 @@ An _execution result_ must be map. The _execution result_ must contain an entry with key {"data"}. The value of this entry is described in the "Data" section. -If execution raised any errors, the _execution result_ must contain an entry -with key {"errors"}. The value of this entry must be a non-empty list of -_execution error_ raised during execution. Each error must be a map as described -in the "Errors" section below. If the request completed without raising any -errors, this entry must not be present. +If any errors are raised during _execution_, the _execution result_ must contain +an entry with key {"errors"}. The value of this entry must be a non-empty list +of _execution error_ raised during execution. Each error must be a map as +described in the "Errors" section below. If the request completed without +raising any errors, this entry must not be present. Note: When {"errors"} is present in a _execution result_, it may be helpful for it to appear first when serialized to make it more apparent that errors are @@ -115,20 +115,24 @@ found at `["hero", "friends"]`, the hero's first friend at ### Data -The {"data"} entry in the _execution result_ will be the result of the execution -of the requested operation. If the operation was a query, this output will be an -object of the query root operation type; if the operation was a mutation, this -output will be an object of the mutation root operation type. +The {"data"} entry in the _execution result_ will be the result of the +_execution_ of the requested operation. If the operation was a query, this +output will be an object of the query root operation type; if the operation was +a mutation, this output will be an object of the mutation root operation type. The response data is the result of accumulating the resolved result of all response positions during execution. -If an error was raised before execution begins, the _response_ must be a +If an error was raised before _execution_ begins, the _response_ must be a _request error result_ which will result in no response data. -If an error was raised during the execution that prevented a valid response, the +If an error was raised during _execution_ that prevented a valid response, the {"data"} entry in the response should be `null`. +Note: Request errors (including those raised during {Request()}) occur before +_execution_ begins; when a request error is raised the {"data"} entry should not +be present in the result. + ### Errors The {"errors"} entry in the _execution result_ or _request error result_ is a @@ -138,7 +142,7 @@ of data described by the error result format below. **Request Errors** :: A _request error_ is an error raised during a _request_ which results in no -response data. Typically raised before execution begins, a request error may +response data. Typically raised before _execution_ begins, a request error may occur due to a parse grammar or validation error in the _Document_, an inability to determine which operation to execute, or invalid input values for variables.