@@ -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' ;
@@ -813,7 +814,10 @@ function defineFieldMap<TSource, TContext>(
813814 name : argName ,
814815 description : argConfig . description ,
815816 type : argConfig . type ,
816- defaultValue : argConfig . defaultValue ,
817+ defaultValue : uncoerceDefaultValue (
818+ argConfig . defaultValue ,
819+ argConfig . type ,
820+ ) ,
817821 deprecationReason : argConfig . deprecationReason ,
818822 extensions : argConfig . extensions && toObjMap ( argConfig . extensions ) ,
819823 astNode : argConfig . astNode ,
@@ -1479,7 +1483,10 @@ export class GraphQLInputObjectType {
14791483
14801484 getFields ( ) : GraphQLInputFieldMap {
14811485 if ( typeof this . _fields === 'function' ) {
1482- this . _fields = this . _fields ( ) ;
1486+ const _fields = this . _fields ;
1487+ // Assign before call to avoid potential infinite recursion.
1488+ this . _fields = { } ;
1489+ this . _fields = _fields ( ) ;
14831490 }
14841491 return this . _fields ;
14851492 }
@@ -1535,7 +1542,10 @@ function defineInputFieldMap(
15351542 name : fieldName ,
15361543 description : fieldConfig . description ,
15371544 type : fieldConfig . type ,
1538- defaultValue : fieldConfig . defaultValue ,
1545+ defaultValue : uncoerceDefaultValue (
1546+ fieldConfig . defaultValue ,
1547+ fieldConfig . type ,
1548+ ) ,
15391549 deprecationReason : fieldConfig . deprecationReason ,
15401550 extensions : fieldConfig . extensions && toObjMap ( fieldConfig . extensions ) ,
15411551 astNode : fieldConfig . astNode ,
@@ -1587,3 +1597,61 @@ export function isRequiredInputField(
15871597}
15881598
15891599export type GraphQLInputFieldMap = ObjMap < GraphQLInputField > ;
1600+
1601+ /**
1602+ * Historically GraphQL.js allowed default values to be provided as
1603+ * assumed-coerced "internal" values, however default values should be provided
1604+ * as "external" pre-coerced values. `uncoerceDefaultValue()` will convert such
1605+ * "internal" values to "external" values to avoid breaking existing clients.
1606+ *
1607+ * This performs the opposite of `coerceInputValue()`. Given an "internal"
1608+ * coerced value, reverse the process to provide an "external" uncoerced value.
1609+ *
1610+ * This function should not throw Errors on incorrectly shaped input. Instead
1611+ * it will simply pass through such values directly.
1612+ *
1613+ */
1614+ function uncoerceDefaultValue ( value : mixed , type : GraphQLInputType ) : mixed {
1615+ // Explicitly return the value null.
1616+ if ( value === null ) {
1617+ return null ;
1618+ }
1619+
1620+ // Unwrap type
1621+ const namedType = getNamedType ( type ) ;
1622+
1623+ if ( isIterableObject ( value ) ) {
1624+ return Array . from ( value , ( itemValue ) =>
1625+ uncoerceDefaultValue ( itemValue , namedType ) ,
1626+ ) ;
1627+ }
1628+
1629+ if ( isInputObjectType ( namedType ) ) {
1630+ if ( ! isObjectLike ( value ) ) {
1631+ return value ;
1632+ }
1633+
1634+ const fieldDefs = namedType . getFields ( ) ;
1635+ return mapValue ( value , ( fieldValue , fieldName ) =>
1636+ fieldName in fieldDefs
1637+ ? uncoerceDefaultValue ( fieldValue , fieldDefs [ fieldName ] . type )
1638+ : fieldValue ,
1639+ ) ;
1640+ }
1641+
1642+ if ( isLeafType ( namedType ) ) {
1643+ try {
1644+ // For leaf types (Scalars, Enums), serialize is the oppose of coercion
1645+ // (parseValue) and will produce an "external" value.
1646+ return namedType . serialize ( value ) ;
1647+ } catch ( error ) {
1648+ // Ingore any invalid data errors.
1649+ // istanbul ignore next - serialize should only throw GraphQLError
1650+ if ( ! ( error instanceof GraphQLError ) ) {
1651+ throw error ;
1652+ }
1653+ }
1654+ }
1655+
1656+ return value ;
1657+ }
0 commit comments