From 1e48b21452726f1800bff53e1610e6de274fc6b5 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 3 Jul 2025 13:54:45 +0100 Subject: [PATCH 1/5] Incorporate meta-fields into ExecuteCollectedFields --- spec/Section 6 -- Execution.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index c615e526e..e625a1b33 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -581,9 +581,14 @@ variableValues): - For each {responseName} and {fields} in {collectedFieldsMap}: - Let {fieldName} be the name of the first entry in {fields}. Note: This value is unaffected if an alias is used. - - Let {fieldType} be the return type defined for the field {fieldName} of - {objectType}. - - If {fieldType} is defined: + - If {fieldName} is a meta-field as defined in the Introspection section: + - Let {responseValue} be the result of resolving that meta-field as per the + rules of the [Introspection](#sec-Introspection) section. + - Set {responseValue} as the value for {responseName} in {resultMap}. + - Otherwise, if a field named {fieldName} is defined on {objectType}: + - Let {fieldType} be the return type defined for the field {fieldName} of + {objectType}. + - Assert: {fieldType} must exist. - Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType, fields, variableValues)}. - Set {responseValue} as the value for {responseName} in {resultMap}. From 3d6864ea91a31bd23d267d052fc3cf91c468e5f9 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Jul 2025 14:00:24 +0100 Subject: [PATCH 2/5] Introduce ResolveMetaFieldValue algorithm --- spec/Section 6 -- Execution.md | 42 ++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index e625a1b33..4dd17c4e0 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -581,14 +581,12 @@ variableValues): - For each {responseName} and {fields} in {collectedFieldsMap}: - Let {fieldName} be the name of the first entry in {fields}. Note: This value is unaffected if an alias is used. - - If {fieldName} is a meta-field as defined in the Introspection section: - - Let {responseValue} be the result of resolving that meta-field as per the - rules of the [Introspection](#sec-Introspection) section. - - Set {responseValue} as the value for {responseName} in {resultMap}. - - Otherwise, if a field named {fieldName} is defined on {objectType}: - - Let {fieldType} be the return type defined for the field {fieldName} of - {objectType}. - - Assert: {fieldType} must exist. + - If {fieldName} is a meta-field as defined in the + [Introspection](#sec-Introspection) section, let {fieldType} be the return + type of that meta-field. + - Otherwise, let {fieldType} be the return type defined for the field + {fieldName} of {objectType}. + - If {fieldType} is defined: - Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType, fields, variableValues)}. - Set {responseValue} as the value for {responseName} in {resultMap}. @@ -730,8 +728,11 @@ ExecuteField(objectType, objectValue, fieldType, fields, variableValues): - Let {fieldName} be the field name of {field}. - Let {argumentValues} be the result of {CoerceArgumentValues(objectType, field, variableValues)}. -- Let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, fieldName, - argumentValues)}. +- If {fieldName} is a meta-field as defined in the + [Introspection](#sec-Introspection) section, let {resolvedValue} be + {ResolveMetaFieldValue(objectType, fieldName, argumentValues)}. +- Otherwise, let {resolvedValue} be {ResolveFieldValue(objectType, objectValue, + fieldName, argumentValues)}. - Return the result of {CompleteValue(fieldType, fields, resolvedValue, variableValues)}. @@ -823,6 +824,27 @@ necessitates the rest of a GraphQL executor to handle an asynchronous execution flow. If the field is of a list type, each value in the collection of values returned by {resolver} may itself be retrieved asynchronously. +### Meta-Field Resolution + +The meta-fields `__typename`, `__schema` and `__type` are resolved as per the +rules in the [Introspection](#sec-Introspection) section. + +ResolveMetaFieldValue(objectType, fieldName, argumentValues): + +- If {fieldName} is {"\_\_typename"}: + - Return the name of {objectType}. +- If {fieldName} is {"\_\_schema"}: + - Assert: {objectType} must be the _root operation type_ in {schema} for query + operations. + - Return {schema}. +- If {fieldName} is {"\_\_type"}: + - Assert: {objectType} must be the _root operation type_ in {schema} for query + operations. + - Let {typeName} be the value provided in {argumentValues} for the name + {"name"}. + - Let {type} be the type with name {typeName} in {schema}. + - Return {type} if it exists; otherwise {null}. + ### Value Completion After resolving the value for a field, it is completed by ensuring it adheres to From d65ee7585250260ab7ed94b353388b6fe3718611 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Jul 2025 14:03:25 +0100 Subject: [PATCH 3/5] Refactor to add assertion --- spec/Section 6 -- Execution.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 4dd17c4e0..642580c5c 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -831,8 +831,6 @@ rules in the [Introspection](#sec-Introspection) section. ResolveMetaFieldValue(objectType, fieldName, argumentValues): -- If {fieldName} is {"\_\_typename"}: - - Return the name of {objectType}. - If {fieldName} is {"\_\_schema"}: - Assert: {objectType} must be the _root operation type_ in {schema} for query operations. @@ -844,6 +842,8 @@ ResolveMetaFieldValue(objectType, fieldName, argumentValues): {"name"}. - Let {type} be the type with name {typeName} in {schema}. - Return {type} if it exists; otherwise {null}. +- Assert: {fieldName} is {"\_\_typename"}. +- Return the name of {objectType}. ### Value Completion From c65fcd21cc87c66e492cbd4211cd4ab7308eae4e Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Jul 2025 14:04:32 +0100 Subject: [PATCH 4/5] This should require less refactoring when we add future meta-fields --- spec/Section 6 -- Execution.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 642580c5c..bc8141be0 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -835,15 +835,16 @@ ResolveMetaFieldValue(objectType, fieldName, argumentValues): - Assert: {objectType} must be the _root operation type_ in {schema} for query operations. - Return {schema}. -- If {fieldName} is {"\_\_type"}: +- Otherwise, if {fieldName} is {"\_\_type"}: - Assert: {objectType} must be the _root operation type_ in {schema} for query operations. - Let {typeName} be the value provided in {argumentValues} for the name {"name"}. - Let {type} be the type with name {typeName} in {schema}. - Return {type} if it exists; otherwise {null}. -- Assert: {fieldName} is {"\_\_typename"}. -- Return the name of {objectType}. +- Otherwise: + - Assert: {fieldName} is {"\_\_typename"}. + - Return the name of {objectType}. ### Value Completion From 4b7c111802bebde1703ae8f6c661847f4fce3caa Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 4 Jul 2025 14:09:45 +0100 Subject: [PATCH 5/5] Could be an introspection type --- spec/Section 6 -- Execution.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index bc8141be0..540539361 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -840,7 +840,9 @@ ResolveMetaFieldValue(objectType, fieldName, argumentValues): operations. - Let {typeName} be the value provided in {argumentValues} for the name {"name"}. - - Let {type} be the type with name {typeName} in {schema}. + - If {typeName} begins with {"\_\_"}, let {type} be the type with name + {typeName} in the introspection schema. + - Otherwise, let {type} be the type with name {typeName} in {schema}. - Return {type} if it exists; otherwise {null}. - Otherwise: - Assert: {fieldName} is {"\_\_typename"}.