Skip to content

Commit de0c12f

Browse files
captbaritonefacebook-github-bot
authored andcommitted
Process abstract type key on resolver fragments
Reviewed By: josephsavona Differential Revision: D80972077
1 parent 0fc3699 commit de0c12f

File tree

2 files changed

+55
-40
lines changed

2 files changed

+55
-40
lines changed

packages/react-relay/__tests__/RelayResolvers-abstractTypeRootFragment-test.js

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,6 @@ test('Can read a resolver with a rootFragment on an abstract type', async () =>
8888
jest.runAllImmediates();
8989
});
9090

91-
// Incorrect! We provided `__isNode`!
92-
expect(logEvents).toEqual([
93-
{
94-
fieldPath: '<abstract-type-hint>',
95-
kind: 'missing_expected_data.log',
96-
owner: 'NodeResolversGreeting',
97-
uiContext: undefined,
98-
},
99-
]);
100-
// Incorrect! Should be the greeting.
101-
expect(renderer?.toJSON()).toEqual(null);
91+
expect(logEvents).toEqual([]);
92+
expect(renderer?.toJSON()).toEqual('Hello Node with id 4!');
10293
});

packages/relay-runtime/store/RelayResponseNormalizer.js

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {PayloadData, PayloadError} from '../network/RelayNetworkTypes';
1616
import type {
1717
NormalizationActorChange,
1818
NormalizationDefer,
19+
NormalizationInlineFragment,
1920
NormalizationLinkedField,
2021
NormalizationLiveResolverField,
2122
NormalizationModuleImport,
@@ -54,6 +55,7 @@ const RelayModernRecord = require('./RelayModernRecord');
5455
const {createNormalizationSelector} = require('./RelayModernSelector');
5556
const {
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,62 @@ 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+
!RelayFeatureFlags.DISABLE_RESOLVER_ROOT_FRAGMENT_NORMALIZATION_BUG_FIX)
356+
) {
357+
this._traverseSelections(selection, record, data);
358+
}
359+
} else {
360+
// $FlowFixMe[method-unbinding] - data could be prototype less
361+
const implementsInterface = Object.prototype.hasOwnProperty.call(
362+
data,
363+
abstractKey,
364+
);
365+
const typeName = RelayModernRecord.getType(record);
366+
const typeID = generateTypeID(typeName);
367+
let typeRecord = this._recordSource.get(typeID);
368+
if (typeRecord == null) {
369+
typeRecord = RelayModernRecord.create(typeID, TYPE_SCHEMA_TYPE);
370+
this._recordSource.set(typeID, typeRecord);
371+
}
372+
RelayModernRecord.setValue(typeRecord, abstractKey, implementsInterface);
373+
if (implementsInterface) {
374+
this._traverseSelections(selection, record, data);
375+
}
376+
}
377+
}
378+
361379
_normalizeResolver(
362380
resolver: NormalizationResolverField | NormalizationLiveResolverField,
363381
record: Record,
364382
data: PayloadData,
365383
) {
366384
if (resolver.fragment != null) {
367-
this._traverseSelections(resolver.fragment, record, data);
385+
if (
386+
RelayFeatureFlags.DISABLE_RESOLVER_ROOT_FRAGMENT_NORMALIZATION_BUG_FIX
387+
) {
388+
this._traverseSelections(resolver.fragment, record, data);
389+
} else {
390+
this._normalizeInlineFragment(resolver.fragment, record, data);
391+
}
368392
}
369393
}
370394

0 commit comments

Comments
 (0)