@@ -16,6 +16,7 @@ import type {PayloadData, PayloadError} from '../network/RelayNetworkTypes';
1616import type {
1717 NormalizationActorChange ,
1818 NormalizationDefer ,
19+ NormalizationInlineFragment ,
1920 NormalizationLinkedField ,
2021 NormalizationLiveResolverField ,
2122 NormalizationModuleImport ,
@@ -54,6 +55,7 @@ const RelayModernRecord = require('./RelayModernRecord');
5455const { createNormalizationSelector} = require ( './RelayModernSelector' ) ;
5556const {
5657 ROOT_ID ,
58+ ROOT_TYPE ,
5759 TYPENAME_KEY ,
5860 getArgumentValues,
5961 getHandleStorageKey,
@@ -243,34 +245,7 @@ class RelayResponseNormalizer {
243245 break ;
244246 }
245247 case 'InlineFragment' : {
246- const { abstractKey} = selection ;
247- if ( abstractKey == null ) {
248- const typeName = RelayModernRecord . getType ( record ) ;
249- if ( typeName === selection . type ) {
250- this . _traverseSelections ( selection , record , data ) ;
251- }
252- } else {
253- // $FlowFixMe[method-unbinding] - data could be prototype less
254- const implementsInterface = Object . prototype . hasOwnProperty . call (
255- data ,
256- abstractKey ,
257- ) ;
258- const typeName = RelayModernRecord . getType ( record ) ;
259- const typeID = generateTypeID ( typeName ) ;
260- let typeRecord = this . _recordSource . get ( typeID ) ;
261- if ( typeRecord == null ) {
262- typeRecord = RelayModernRecord . create ( typeID , TYPE_SCHEMA_TYPE ) ;
263- this . _recordSource . set ( typeID , typeRecord ) ;
264- }
265- RelayModernRecord . setValue (
266- typeRecord ,
267- abstractKey ,
268- implementsInterface ,
269- ) ;
270- if ( implementsInterface ) {
271- this . _traverseSelections ( selection , record , data ) ;
272- }
273- }
248+ this . _normalizeInlineFragment ( selection , record , data ) ;
274249 break ;
275250 }
276251 case 'TypeDiscriminator' : {
@@ -358,13 +333,55 @@ class RelayResponseNormalizer {
358333 }
359334 }
360335
336+ _normalizeInlineFragment (
337+ selection : NormalizationInlineFragment ,
338+ record : Record ,
339+ data : PayloadData ,
340+ ) {
341+ const { abstractKey} = selection ;
342+ if ( abstractKey == null ) {
343+ const typeName = RelayModernRecord . getType ( record ) ;
344+ if (
345+ typeName === selection . type ||
346+ // The root record type is a special `__Root` type and may not match the
347+ // type on the ast, so ignore type mismatches at the root. We currently
348+ // detect whether we're at the root by checking against ROOT_ID, but this
349+ // does not work for mutations/subscriptions which generate unique root
350+ // ids. This is acceptable in practice as we don't read data for
351+ // mutations/subscriptions in a situation where we would use
352+ // isMissingData to decide whether to suspend or not.
353+ // TODO T96653810: Correctly detect reading from root of mutation/subscription
354+ typeName === ROOT_TYPE
355+ ) {
356+ this . _traverseSelections ( selection , record , data ) ;
357+ }
358+ } else {
359+ // $FlowFixMe[method-unbinding] - data could be prototype less
360+ const implementsInterface = Object . prototype . hasOwnProperty . call (
361+ data ,
362+ abstractKey ,
363+ ) ;
364+ const typeName = RelayModernRecord . getType ( record ) ;
365+ const typeID = generateTypeID ( typeName ) ;
366+ let typeRecord = this . _recordSource . get ( typeID ) ;
367+ if ( typeRecord == null ) {
368+ typeRecord = RelayModernRecord . create ( typeID , TYPE_SCHEMA_TYPE ) ;
369+ this . _recordSource . set ( typeID , typeRecord ) ;
370+ }
371+ RelayModernRecord . setValue ( typeRecord , abstractKey , implementsInterface ) ;
372+ if ( implementsInterface ) {
373+ this . _traverseSelections ( selection , record , data ) ;
374+ }
375+ }
376+ }
377+
361378 _normalizeResolver (
362379 resolver : NormalizationResolverField | NormalizationLiveResolverField ,
363380 record : Record ,
364381 data : PayloadData ,
365382 ) {
366383 if ( resolver . fragment != null ) {
367- this . _traverseSelections ( resolver . fragment , record , data ) ;
384+ this . _normalizeInlineFragment ( resolver . fragment , record , data ) ;
368385 }
369386 }
370387
0 commit comments