@@ -13,6 +13,7 @@ import { devAssert } from '../jsutils/devAssert';
1313import { keyValMap } from '../jsutils/keyValMap' ;
1414import { instanceOf } from '../jsutils/instanceOf' ;
1515import { didYouMean } from '../jsutils/didYouMean' ;
16+ import { isIterableObject } from '../jsutils/isIterableObject' ;
1617import { isObjectLike } from '../jsutils/isObjectLike' ;
1718import { identityFunc } from '../jsutils/identityFunc' ;
1819import { suggestionList } from '../jsutils/suggestionList' ;
@@ -830,7 +831,10 @@ export function defineArguments(
830831 name : argName ,
831832 description : argConfig . description ,
832833 type : argConfig . type ,
833- defaultValue : argConfig . defaultValue ,
834+ defaultValue : uncoerceDefaultValue (
835+ argConfig . defaultValue ,
836+ argConfig . type ,
837+ ) ,
834838 deprecationReason : argConfig . deprecationReason ,
835839 extensions : argConfig . extensions && toObjMap ( argConfig . extensions ) ,
836840 astNode : argConfig . astNode ,
@@ -1483,7 +1487,10 @@ export class GraphQLInputObjectType {
14831487
14841488 getFields ( ) : GraphQLInputFieldMap {
14851489 if ( typeof this . _fields === 'function' ) {
1486- this . _fields = this . _fields ( ) ;
1490+ const _fields = this . _fields ;
1491+ // Assign before call to avoid potential infinite recursion.
1492+ this . _fields = { } ;
1493+ this . _fields = _fields ( ) ;
14871494 }
14881495 return this . _fields ;
14891496 }
@@ -1539,7 +1546,10 @@ function defineInputFieldMap(
15391546 name : fieldName ,
15401547 description : fieldConfig . description ,
15411548 type : fieldConfig . type ,
1542- defaultValue : fieldConfig . defaultValue ,
1549+ defaultValue : uncoerceDefaultValue (
1550+ fieldConfig . defaultValue ,
1551+ fieldConfig . type ,
1552+ ) ,
15431553 deprecationReason : fieldConfig . deprecationReason ,
15441554 extensions : fieldConfig . extensions && toObjMap ( fieldConfig . extensions ) ,
15451555 astNode : fieldConfig . astNode ,
@@ -1591,3 +1601,61 @@ export function isRequiredInputField(
15911601}
15921602
15931603export type GraphQLInputFieldMap = ObjMap < GraphQLInputField > ;
1604+
1605+ /**
1606+ * Historically GraphQL.js allowed default values to be provided as
1607+ * assumed-coerced "internal" values, however default values should be provided
1608+ * as "external" pre-coerced values. `uncoerceDefaultValue()` will convert such
1609+ * "internal" values to "external" values to avoid breaking existing clients.
1610+ *
1611+ * This performs the opposite of `coerceInputValue()`. Given an "internal"
1612+ * coerced value, reverse the process to provide an "external" uncoerced value.
1613+ *
1614+ * This function should not throw Errors on incorrectly shaped input. Instead
1615+ * it will simply pass through such values directly.
1616+ *
1617+ */
1618+ function uncoerceDefaultValue ( value : mixed , type : GraphQLInputType ) : mixed {
1619+ // Explicitly return the value null.
1620+ if ( value === null ) {
1621+ return null ;
1622+ }
1623+
1624+ // Unwrap type
1625+ const namedType = getNamedType ( type ) ;
1626+
1627+ if ( isIterableObject ( value ) ) {
1628+ return Array . from ( value , ( itemValue ) =>
1629+ uncoerceDefaultValue ( itemValue , namedType ) ,
1630+ ) ;
1631+ }
1632+
1633+ if ( isInputObjectType ( namedType ) ) {
1634+ if ( ! isObjectLike ( value ) ) {
1635+ return value ;
1636+ }
1637+
1638+ const fieldDefs = namedType . getFields ( ) ;
1639+ return mapValue ( value , ( fieldValue , fieldName ) =>
1640+ fieldName in fieldDefs
1641+ ? uncoerceDefaultValue ( fieldValue , fieldDefs [ fieldName ] . type )
1642+ : fieldValue ,
1643+ ) ;
1644+ }
1645+
1646+ if ( isLeafType ( namedType ) ) {
1647+ try {
1648+ // For leaf types (Scalars, Enums), serialize is the oppose of coercion
1649+ // (parseValue) and will produce an "external" value.
1650+ return namedType . serialize ( value ) ;
1651+ } catch ( error ) {
1652+ // Ingore any invalid data errors.
1653+ // istanbul ignore next - serialize should only throw GraphQLError
1654+ if ( ! ( error instanceof GraphQLError ) ) {
1655+ throw error ;
1656+ }
1657+ }
1658+ }
1659+
1660+ return value ;
1661+ }
0 commit comments