File tree 5 files changed +42
-4
lines changed
experimental-live-resolvers
5 files changed +42
-4
lines changed Original file line number Diff line number Diff line change @@ -58,13 +58,15 @@ function logFn(event: LogEvent): void {
58
58
beforeEach ( ( ) => {
59
59
RelayFeatureFlags . ENABLE_RELAY_RESOLVERS = true ;
60
60
RelayFeatureFlags . ENABLE_CLIENT_EDGES = true ;
61
+ RelayFeatureFlags . ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES = true ;
61
62
logEvents = [ ] ;
62
63
resetStore ( logFn ) ;
63
64
} ) ;
64
65
65
66
afterEach ( ( ) => {
66
67
RelayFeatureFlags . ENABLE_RELAY_RESOLVERS = false ;
67
68
RelayFeatureFlags . ENABLE_CLIENT_EDGES = false ;
69
+ RelayFeatureFlags . ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES = false ;
68
70
} ) ;
69
71
70
72
function createEnvironment ( ) {
@@ -539,8 +541,7 @@ describe.each([
539
541
setIsHuman ( true ) ;
540
542
jest . runAllImmediates ( ) ;
541
543
} ) ;
542
- // TODO: Should be 0. Relay should not mutate the value here.
543
- expect ( renderer . toJSON ( ) ) . toEqual ( 'human:100' ) ;
544
+ expect ( renderer . toJSON ( ) ) . toEqual ( 'human:0' ) ;
544
545
545
546
TestRenderer . act ( ( ) => {
546
547
renderer . unmount ( ) ;
@@ -568,10 +569,9 @@ describe.each([
568
569
) ;
569
570
expect ( renderer . toJSON ( ) ) . toEqual ( 'robot:0' ) ;
570
571
571
- // TODO: should not throw on mutating the inner of the resolver value
572
572
expect ( ( ) => {
573
573
chargeBattery ( ) ;
574
- } ) . toThrow ( ) ;
574
+ } ) . not . toThrow ( ) ;
575
575
576
576
TestRenderer . act ( ( ) => {
577
577
renderer . unmount ( ) ;
Original file line number Diff line number Diff line change @@ -26,6 +26,8 @@ import type {
26
26
27
27
const recycleNodesInto = require ( '../util/recycleNodesInto' ) ;
28
28
const { RELAY_LIVE_RESOLVER } = require ( '../util/RelayConcreteNode' ) ;
29
+ const RelayFeatureFlags = require ( '../util/RelayFeatureFlags' ) ;
30
+ const shallowFreeze = require ( '../util/shallowFreeze' ) ;
29
31
const { generateClientID} = require ( './ClientID' ) ;
30
32
const RelayModernRecord = require ( './RelayModernRecord' ) ;
31
33
const {
@@ -172,6 +174,9 @@ class RecordResolverCache implements ResolverCache {
172
174
linkedRecord = RelayModernRecord . create ( linkedID , '__RELAY_RESOLVER__' ) ;
173
175
174
176
const evaluationResult = evaluate ( ) ;
177
+ if ( RelayFeatureFlags . ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES ) {
178
+ shallowFreeze ( evaluationResult . resolverResult ) ;
179
+ }
175
180
RelayModernRecord . setValue (
176
181
linkedRecord ,
177
182
RELAY_RESOLVER_VALUE_KEY ,
Original file line number Diff line number Diff line change @@ -36,6 +36,8 @@ import type {LiveState} from 'relay-runtime';
36
36
37
37
const recycleNodesInto = require ( '../../util/recycleNodesInto' ) ;
38
38
const { RELAY_LIVE_RESOLVER } = require ( '../../util/RelayConcreteNode' ) ;
39
+ const RelayFeatureFlags = require ( '../../util/RelayFeatureFlags' ) ;
40
+ const shallowFreeze = require ( '../../util/shallowFreeze' ) ;
39
41
const { generateClientID, generateClientObjectClientID} = require ( '../ClientID' ) ;
40
42
const RelayModernRecord = require ( '../RelayModernRecord' ) ;
41
43
const { createNormalizationSelector} = require ( '../RelayModernSelector' ) ;
@@ -620,12 +622,18 @@ class LiveResolverCache implements ResolverCache {
620
622
nextOutputTypeRecordIDs ,
621
623
) ;
622
624
625
+ if ( RelayFeatureFlags . ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES ) {
626
+ shallowFreeze ( resolverValue ) ;
627
+ }
623
628
RelayModernRecord . setValue (
624
629
resolverRecord ,
625
630
RELAY_RESOLVER_VALUE_KEY ,
626
631
resolverValue ,
627
632
) ;
628
633
} else {
634
+ if ( RelayFeatureFlags . ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES ) {
635
+ shallowFreeze ( value ) ;
636
+ }
629
637
// For "classic" resolvers (or if the value is nullish), we are just setting their
630
638
// value as is.
631
639
RelayModernRecord . setValue (
Original file line number Diff line number Diff line change @@ -28,6 +28,7 @@ export type FeatureFlags = {
28
28
STRING_INTERN_LEVEL : number ,
29
29
LOG_MISSING_RECORDS_IN_PROD : boolean ,
30
30
ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE : boolean ,
31
+ ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES : boolean ,
31
32
32
33
// Configure RelayStoreSubscriptions to mark a subscription as affected by an
33
34
// update if there are any overlapping IDs other than ROOT_ID or VIWER_ID,
@@ -63,6 +64,7 @@ const RelayFeatureFlags: FeatureFlags = {
63
64
ENABLE_OPERATION_TRACKER_OPTIMISTIC_UPDATES : false ,
64
65
ENABLE_RELAY_OPERATION_TRACKER_SUSPENSE : false ,
65
66
ENABLE_FIELD_ERROR_HANDLING : false ,
67
+ ENABLE_SHALLOW_FREEZE_RESOLVER_VALUES : false ,
66
68
} ;
67
69
68
70
module . exports = RelayFeatureFlags ;
Original file line number Diff line number Diff line change
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict
8
+ * @format
9
+ * @oncall relay
10
+ */
11
+
12
+ 'use strict' ;
13
+
14
+ // Shallow freeze to prevent Relay from mutating the value in recycleNodesInto or deepFreezing the value
15
+ module . exports = function shallowFreeze ( value : mixed ) {
16
+ if (
17
+ typeof value === 'object' &&
18
+ value != null &&
19
+ ( Array . isArray ( value ) || value . constructor === Object )
20
+ ) {
21
+ Object . freeze ( value ) ;
22
+ }
23
+ } ;
You can’t perform that action at this time.
0 commit comments