diff --git a/resources/inline-invariant.js b/resources/inline-invariant.js index 3cacdcc8f6..f2d0134caa 100644 --- a/resources/inline-invariant.js +++ b/resources/inline-invariant.js @@ -21,6 +21,7 @@ module.exports = function inlineInvariant(context) { (%%cond%%) || devAssert(0, %%args%%) `); + const t = context.types; return { visitor: { CallExpression(path) { @@ -38,13 +39,35 @@ module.exports = function inlineInvariant(context) { const calleeName = node.callee.name; if (calleeName === 'invariant') { const [cond, args] = node.arguments; - path.addComment('leading', ' istanbul ignore next '); - path.replaceWith(invariantTemplate({ cond, args })); + + // Check if it is unreachable invariant: "invariant(false, ...)" + if (cond.type === 'BooleanLiteral' && cond.value === false) { + addIstanbulIgnoreElse(path); + } else { + path.replaceWith(invariantTemplate({ cond, args })); + } } else if (calleeName === 'devAssert') { const [cond, args] = node.arguments; path.replaceWith(assertTemplate({ cond, args })); } + + path.addComment('leading', ' istanbul ignore next '); }, }, }; + + function addIstanbulIgnoreElse(path) { + const parentStatement = path.getStatementParent(); + const previousStatement = + parentStatement.container[parentStatement.key - 1]; + if (previousStatement.type === 'IfStatement') { + let lastIf = previousStatement; + while (lastIf.alternate && lastIf.alternate.type === 'IfStatement') { + lastIf = lastIf.alternate; + } + if (lastIf.alternate == null) { + t.addComment(lastIf, 'leading', ' istanbul ignore else '); + } + } + } }; diff --git a/src/execution/execute.js b/src/execution/execute.js index 121e4e1d45..93e9d76fc1 100644 --- a/src/execution/execute.js +++ b/src/execution/execute.js @@ -4,6 +4,7 @@ import { forEach, isCollection } from 'iterall'; import inspect from '../jsutils/inspect'; import memoize3 from '../jsutils/memoize3'; +import invariant from '../jsutils/invariant'; import devAssert from '../jsutils/devAssert'; import isInvalid from '../jsutils/isInvalid'; import isNullish from '../jsutils/isNullish'; @@ -872,11 +873,10 @@ function completeValue( } // Not reachable. All possible output types have been considered. - /* istanbul ignore next */ - throw new Error( - `Cannot complete value of unexpected output type: "${inspect( - (returnType: empty), - )}".`, + invariant( + false, + 'Cannot complete value of unexpected output type: ' + + inspect((returnType: empty)), ); } diff --git a/src/type/introspection.js b/src/type/introspection.js index bc5821cacf..eff1e0c42e 100644 --- a/src/type/introspection.js +++ b/src/type/introspection.js @@ -3,6 +3,7 @@ import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import { print } from '../language/printer'; import { DirectiveLocation } from '../language/directiveLocation'; @@ -208,8 +209,7 @@ export const __Type = new GraphQLObjectType({ } // Not reachable. All possible types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected type: "${inspect((type: empty))}".`); + invariant(false, `Unexpected type: "${inspect((type: empty))}".`); }, }, name: { diff --git a/src/utilities/astFromValue.js b/src/utilities/astFromValue.js index 82f47c7005..0b48e3ee12 100644 --- a/src/utilities/astFromValue.js +++ b/src/utilities/astFromValue.js @@ -5,6 +5,7 @@ import { forEach, isCollection } from 'iterall'; import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import isNullish from '../jsutils/isNullish'; import isInvalid from '../jsutils/isInvalid'; import isObjectLike from '../jsutils/isObjectLike'; @@ -137,8 +138,7 @@ export function astFromValue(value: mixed, type: GraphQLInputType): ?ValueNode { } // Not reachable. All possible input types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected input type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected input type: ' + inspect((type: empty))); } /** diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 9c8d0794b4..c3d4b350d8 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -4,6 +4,7 @@ import objectValues from '../polyfills/objectValues'; import keyMap from '../jsutils/keyMap'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import devAssert from '../jsutils/devAssert'; import keyValMap from '../jsutils/keyValMap'; import { type ObjMap } from '../jsutils/ObjMap'; @@ -313,9 +314,9 @@ export class ASTDefinitionBuilder { } // Not reachable. All possible type definition nodes have been considered. - /* istanbul ignore next */ - throw new Error( - `Unexpected type definition node: "${inspect((astNode: empty))}".`, + invariant( + false, + 'Unexpected type definition node: ' + inspect((astNode: empty)), ); } diff --git a/src/utilities/coerceValue.js b/src/utilities/coerceValue.js index 08a0b92c65..e2fecfd5dd 100644 --- a/src/utilities/coerceValue.js +++ b/src/utilities/coerceValue.js @@ -5,6 +5,7 @@ import { forEach, isCollection } from 'iterall'; import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import didYouMean from '../jsutils/didYouMean'; import isObjectLike from '../jsutils/isObjectLike'; import suggestionList from '../jsutils/suggestionList'; @@ -195,8 +196,7 @@ export function coerceValue( } // Not reachable. All possible input types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected input type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected input type: ' + inspect((type: empty))); } function ofValue(value) { diff --git a/src/utilities/extendSchema.js b/src/utilities/extendSchema.js index bbdd9011a9..4d1778e87c 100644 --- a/src/utilities/extendSchema.js +++ b/src/utilities/extendSchema.js @@ -5,6 +5,7 @@ import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; import mapValue from '../jsutils/mapValue'; +import invariant from '../jsutils/invariant'; import devAssert from '../jsutils/devAssert'; import keyValMap from '../jsutils/keyValMap'; @@ -258,8 +259,7 @@ export function extendSchema( } // Not reachable. All possible types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected type: ' + inspect((type: empty))); } function extendDirective(directive: GraphQLDirective): GraphQLDirective { diff --git a/src/utilities/findBreakingChanges.js b/src/utilities/findBreakingChanges.js index f3cb01dfe7..3d48314c50 100644 --- a/src/utilities/findBreakingChanges.js +++ b/src/utilities/findBreakingChanges.js @@ -512,8 +512,7 @@ function typeKindName(type: GraphQLNamedType): string { } // Not reachable. All possible named types have been considered. - /* istanbul ignore next */ - throw new TypeError(`Unexpected type: ${inspect((type: empty))}.`); + invariant(false, 'Unexpected type: ' + inspect((type: empty))); } function stringifyValue(value: mixed, type: GraphQLInputType): string { diff --git a/src/utilities/lexicographicSortSchema.js b/src/utilities/lexicographicSortSchema.js index 67b31f281c..16723a86ca 100644 --- a/src/utilities/lexicographicSortSchema.js +++ b/src/utilities/lexicographicSortSchema.js @@ -3,6 +3,7 @@ import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import keyValMap from '../jsutils/keyValMap'; import { type ObjMap } from '../jsutils/ObjMap'; @@ -137,8 +138,7 @@ export function lexicographicSortSchema(schema: GraphQLSchema): GraphQLSchema { } // Not reachable. All possible types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected type: ' + inspect((type: empty))); } } diff --git a/src/utilities/schemaPrinter.js b/src/utilities/schemaPrinter.js index 437737cb93..3f35e96623 100644 --- a/src/utilities/schemaPrinter.js +++ b/src/utilities/schemaPrinter.js @@ -4,6 +4,7 @@ import flatMap from '../polyfills/flatMap'; import objectValues from '../polyfills/objectValues'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import { print } from '../language/printer'; import { printBlockString } from '../language/blockString'; @@ -173,8 +174,7 @@ export function printType(type: GraphQLNamedType, options?: Options): string { } // Not reachable. All possible types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected type: ' + inspect((type: empty))); } function printScalar(type: GraphQLScalarType, options): string { diff --git a/src/utilities/typeFromAST.js b/src/utilities/typeFromAST.js index 30a2dbea45..c418511dae 100644 --- a/src/utilities/typeFromAST.js +++ b/src/utilities/typeFromAST.js @@ -1,6 +1,7 @@ // @flow strict import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import { Kind } from '../language/kinds'; import { @@ -52,6 +53,5 @@ export function typeFromAST(schema, typeNode) { } // Not reachable. All possible type nodes have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected type node: "${inspect((typeNode: empty))}".`); + invariant(false, 'Unexpected type node: ' + inspect((typeNode: empty))); } diff --git a/src/utilities/valueFromAST.js b/src/utilities/valueFromAST.js index 402a9c676e..71f10c595a 100644 --- a/src/utilities/valueFromAST.js +++ b/src/utilities/valueFromAST.js @@ -4,6 +4,7 @@ import objectValues from '../polyfills/objectValues'; import keyMap from '../jsutils/keyMap'; import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import isInvalid from '../jsutils/isInvalid'; import { type ObjMap } from '../jsutils/ObjMap'; @@ -160,8 +161,7 @@ export function valueFromAST( } // Not reachable. All possible input types have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected input type: "${inspect((type: empty))}".`); + invariant(false, 'Unexpected input type: ' + inspect((type: empty))); } // Returns true if the provided valueNode is a variable which is not defined diff --git a/src/utilities/valueFromASTUntyped.js b/src/utilities/valueFromASTUntyped.js index 52b824c9ae..9109d75208 100644 --- a/src/utilities/valueFromASTUntyped.js +++ b/src/utilities/valueFromASTUntyped.js @@ -1,6 +1,7 @@ // @flow strict import inspect from '../jsutils/inspect'; +import invariant from '../jsutils/invariant'; import keyValMap from '../jsutils/keyValMap'; import isInvalid from '../jsutils/isInvalid'; import { type ObjMap } from '../jsutils/ObjMap'; @@ -56,6 +57,5 @@ export function valueFromASTUntyped( } // Not reachable. All possible value nodes have been considered. - /* istanbul ignore next */ - throw new Error(`Unexpected value node: "${inspect((valueNode: empty))}".`); + invariant(false, 'Unexpected value node: ' + inspect((valueNode: empty))); }