Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions src/error/GraphQLError.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { getLocation } from '../language/location';
import type { ASTNode } from '../language/ast';
import type { Source } from '../language/source';

export type GraphQLErrorLocation = {|
+line: number,
+column: number,
|};

/**
* A GraphQLError describes an Error found during the parse, validate, or
* execute phases of performing a GraphQL operation. In addition to a message
Expand All @@ -20,10 +25,10 @@ import type { Source } from '../language/source';
declare class GraphQLError extends Error {
constructor(
message: string,
nodes?: ?Array<*>,
nodes?: ?$ReadOnlyArray<ASTNode>,
source?: ?Source,
positions?: ?Array<number>,
path?: ?Array<string | number>,
positions?: ?$ReadOnlyArray<number>,
path?: ?$ReadOnlyArray<string | number>,
originalError?: ?Error,
extensions?: ?{ [key: string]: mixed },
): void;
Expand All @@ -32,6 +37,8 @@ declare class GraphQLError extends Error {
* A message describing the Error for debugging purposes.
*
* Enumerable, and appears in the result of JSON.stringify().
*
* Note: should be treated as readonly, despite invariant usage.
*/
message: string;

Expand All @@ -45,49 +52,49 @@ declare class GraphQLError extends Error {
*
* Enumerable, and appears in the result of JSON.stringify().
*/
locations: Array<{ line: number, column: number }> | void;
+locations: $ReadOnlyArray<GraphQLErrorLocation> | void;

/**
* An array describing the JSON-path into the execution response which
* corresponds to this error. Only included for errors during execution.
*
* Enumerable, and appears in the result of JSON.stringify().
*/
path: Array<string | number> | void;
+path: $ReadOnlyArray<string | number> | void;

/**
* An array of GraphQL AST Nodes corresponding to this error.
*/
nodes: Array<ASTNode> | void;
+nodes: $ReadOnlyArray<ASTNode> | void;

/**
* The source GraphQL document corresponding to this error.
*/
source: Source | void;
+source: Source | void;

/**
* An array of character offsets within the source GraphQL document
* which correspond to this error.
*/
positions: Array<number> | void;
+positions: $ReadOnlyArray<number> | void;

/**
* The original error thrown from a field resolver during execution.
*/
originalError: ?Error;
+originalError: ?Error;

/**
* The original error thrown from a field resolver during execution.
*/
extensions: ?{ [key: string]: mixed };
+extensions: ?{ [key: string]: mixed };
}

export function GraphQLError( // eslint-disable-line no-redeclare
message: string,
nodes?: ?Array<*>,
nodes?: ?$ReadOnlyArray<ASTNode>,
source?: ?Source,
positions?: ?Array<number>,
path?: ?Array<string | number>,
positions?: ?$ReadOnlyArray<number>,
path?: ?$ReadOnlyArray<string | number>,
originalError?: ?Error,
extensions?: ?{ [key: string]: mixed },
) {
Expand All @@ -100,9 +107,12 @@ export function GraphQLError( // eslint-disable-line no-redeclare

let _positions = positions;
if (!_positions && nodes) {
_positions = nodes
.filter(node => Boolean(node.loc))
.map(node => node.loc.start);
_positions = nodes.reduce((list, node) => {
if (node.loc) {
list.push(node.loc.start);
}
return list;
}, []);
}
if (_positions && _positions.length === 0) {
_positions = undefined;
Expand Down
15 changes: 6 additions & 9 deletions src/error/formatError.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import invariant from '../jsutils/invariant';
import type { GraphQLError } from './GraphQLError';
import type { GraphQLError, GraphQLErrorLocation } from './GraphQLError';

/**
* Given a GraphQLError, format it according to the rules described by the
Expand All @@ -25,12 +25,9 @@ export function formatError(error: GraphQLError): GraphQLFormattedError {
}

export type GraphQLFormattedError = {
message: string,
locations: ?Array<GraphQLErrorLocation>,
path: ?Array<string | number>,
};

export type GraphQLErrorLocation = {
line: number,
column: number,
+message: string,
+locations: $ReadOnlyArray<GraphQLErrorLocation> | void,
+path: $ReadOnlyArray<string | number> | void,
// Extensions
+[key: string]: mixed,
};
6 changes: 2 additions & 4 deletions src/error/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,5 @@ export { syntaxError } from './syntaxError';
export { locatedError } from './locatedError';
export { formatError } from './formatError';

export type {
GraphQLFormattedError,
GraphQLErrorLocation,
} from './formatError';
export type { GraphQLErrorLocation } from './GraphQLError';
export type { GraphQLFormattedError } from './formatError';
5 changes: 3 additions & 2 deletions src/error/locatedError.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import { GraphQLError } from './GraphQLError';
import type { ASTNode } from '../language/ast';

/**
* Given an arbitrary Error, presumably thrown while attempting to execute a
Expand All @@ -16,8 +17,8 @@ import { GraphQLError } from './GraphQLError';
*/
export function locatedError(
originalError: ?Error,
nodes: Array<*>,
path: Array<string | number>,
nodes: $ReadOnlyArray<ASTNode>,
path: $ReadOnlyArray<string | number>,
): GraphQLError {
// Note: this uses a brand-check to support GraphQL errors originating from
// other contexts.
Expand Down
28 changes: 14 additions & 14 deletions src/execution/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export type ExecutionContext = {
* - `data` is the result of a successful execution of the query.
*/
export type ExecutionResult = {
errors?: Array<GraphQLError>,
errors?: $ReadOnlyArray<GraphQLError>,
data?: ObjMap<mixed>,
};

Expand Down Expand Up @@ -235,7 +235,7 @@ function buildResponse(
*/
export function responsePathAsArray(
path: ResponsePath,
): Array<string | number> {
): $ReadOnlyArray<string | number> {
const flattened = [];
let curr = path;
while (curr) {
Expand Down Expand Up @@ -663,7 +663,7 @@ function resolveField(
exeContext: ExecutionContext,
parentType: GraphQLObjectType,
source: mixed,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
path: ResponsePath,
): mixed {
const fieldNode = fieldNodes[0];
Expand Down Expand Up @@ -708,7 +708,7 @@ function resolveField(
export function buildResolveInfo(
exeContext: ExecutionContext,
fieldDef: GraphQLField<*, *>,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
parentType: GraphQLObjectType,
path: ResponsePath,
): GraphQLResolveInfo {
Expand All @@ -733,7 +733,7 @@ export function buildResolveInfo(
export function resolveFieldValueOrError<TSource>(
exeContext: ExecutionContext,
fieldDef: GraphQLField<TSource, *>,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
resolveFn: GraphQLFieldResolver<TSource, *>,
source: TSource,
info: GraphQLResolveInfo,
Expand Down Expand Up @@ -766,7 +766,7 @@ export function resolveFieldValueOrError<TSource>(
function completeValueCatchingError(
exeContext: ExecutionContext,
returnType: GraphQLType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -820,7 +820,7 @@ function completeValueCatchingError(
function completeValueWithLocatedError(
exeContext: ExecutionContext,
returnType: GraphQLType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -872,7 +872,7 @@ function completeValueWithLocatedError(
function completeValue(
exeContext: ExecutionContext,
returnType: GraphQLType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -972,7 +972,7 @@ function completeValue(
function completeListValue(
exeContext: ExecutionContext,
returnType: GraphQLList<*>,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -1034,7 +1034,7 @@ function completeLeafValue(returnType: GraphQLLeafType, result: mixed): mixed {
function completeAbstractValue(
exeContext: ExecutionContext,
returnType: GraphQLAbstractType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -1085,7 +1085,7 @@ function ensureValidRuntimeType(
runtimeTypeOrName: ?GraphQLObjectType | string,
exeContext: ExecutionContext,
returnType: GraphQLAbstractType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
result: mixed,
): GraphQLObjectType {
Expand Down Expand Up @@ -1123,7 +1123,7 @@ function ensureValidRuntimeType(
function completeObjectValue(
exeContext: ExecutionContext,
returnType: GraphQLObjectType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down Expand Up @@ -1169,7 +1169,7 @@ function completeObjectValue(
function invalidReturnTypeError(
returnType: GraphQLObjectType,
result: mixed,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
): GraphQLError {
return new GraphQLError(
`Expected value of type "${returnType.name}" but got: ${String(result)}.`,
Expand All @@ -1180,7 +1180,7 @@ function invalidReturnTypeError(
function collectAndExecuteSubfields(
exeContext: ExecutionContext,
returnType: GraphQLObjectType,
fieldNodes: Array<FieldNode>,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
path: ResponsePath,
result: mixed,
Expand Down
31 changes: 17 additions & 14 deletions src/type/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -619,20 +619,23 @@ export type GraphQLFieldResolver<TSource, TContext> = (
info: GraphQLResolveInfo,
) => mixed;

export type GraphQLResolveInfo = {
fieldName: string,
fieldNodes: Array<FieldNode>,
returnType: GraphQLOutputType,
parentType: GraphQLObjectType,
path: ResponsePath,
schema: GraphQLSchema,
fragments: ObjMap<FragmentDefinitionNode>,
rootValue: mixed,
operation: OperationDefinitionNode,
variableValues: { [variable: string]: mixed },
};

export type ResponsePath = { prev: ResponsePath | void, key: string | number };
export type GraphQLResolveInfo = {|
+fieldName: string,
+fieldNodes: $ReadOnlyArray<FieldNode>,
+returnType: GraphQLOutputType,
+parentType: GraphQLObjectType,
+path: ResponsePath,
+schema: GraphQLSchema,
+fragments: ObjMap<FragmentDefinitionNode>,
+rootValue: mixed,
+operation: OperationDefinitionNode,
+variableValues: { [variable: string]: mixed },
|};

export type ResponsePath = {|
+prev: ResponsePath | void,
+key: string | number,
|};

export type GraphQLFieldConfig<TSource, TContext> = {
type: GraphQLOutputType,
Expand Down
7 changes: 4 additions & 3 deletions src/validation/rules/ScalarLeafs.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ export function ScalarLeafs(context: ValidationContext): any {
return {
Field(node: FieldNode) {
const type = context.getType();
const selectionSet = node.selectionSet;
if (type) {
if (isLeafType(getNamedType(type))) {
if (node.selectionSet) {
if (selectionSet) {
context.reportError(
new GraphQLError(
noSubselectionAllowedMessage(node.name.value, type),
[node.selectionSet],
[selectionSet],
),
);
}
} else if (!node.selectionSet) {
} else if (!selectionSet) {
context.reportError(
new GraphQLError(
requiredSubselectionMessage(node.name.value, type),
Expand Down