@@ -36,7 +36,8 @@ export function findNonSerializableValue(
36
36
path : string = '' ,
37
37
isSerializable : ( value : unknown ) => boolean = isPlain ,
38
38
getEntries ?: ( value : unknown ) => [ string , any ] [ ] ,
39
- ignoredPaths : readonly string [ ] = [ ]
39
+ ignoredPaths : readonly string [ ] = [ ] ,
40
+ cache ?: WeakSet < object >
40
41
) : NonSerializableValue | false {
41
42
let foundNestedSerializable : NonSerializableValue | false
42
43
@@ -51,6 +52,8 @@ export function findNonSerializableValue(
51
52
return false
52
53
}
53
54
55
+ if ( cache ?. has ( value ) ) return false
56
+
54
57
const entries = getEntries != null ? getEntries ( value ) : Object . entries ( value )
55
58
56
59
const hasIgnoredPaths = ignoredPaths . length > 0
@@ -75,7 +78,8 @@ export function findNonSerializableValue(
75
78
nestedPath ,
76
79
isSerializable ,
77
80
getEntries ,
78
- ignoredPaths
81
+ ignoredPaths ,
82
+ cache
79
83
)
80
84
81
85
if ( foundNestedSerializable ) {
@@ -84,9 +88,23 @@ export function findNonSerializableValue(
84
88
}
85
89
}
86
90
91
+ if ( cache && isNestedFrozen ( value ) ) cache . add ( value )
92
+
87
93
return false
88
94
}
89
95
96
+ export function isNestedFrozen ( value : object ) {
97
+ if ( ! Object . isFrozen ( value ) ) return false
98
+
99
+ for ( const nestedValue of Object . values ( value ) ) {
100
+ if ( typeof nestedValue !== 'object' || nestedValue === null ) continue
101
+
102
+ if ( ! isNestedFrozen ( nestedValue ) ) return false
103
+ }
104
+
105
+ return true
106
+ }
107
+
90
108
/**
91
109
* Options for `createSerializableStateInvariantMiddleware()`.
92
110
*
@@ -139,6 +157,12 @@ export interface SerializableStateInvariantMiddlewareOptions {
139
157
* Opt out of checking actions. When set to `true`, other action-related params will be ignored.
140
158
*/
141
159
ignoreActions ?: boolean
160
+
161
+ /**
162
+ * Opt out of caching the results. The cache uses a WeakSet and speeds up repeated checking processes.
163
+ * The cache is automatically disabled if no browser support for WeakSet is present.
164
+ */
165
+ disableCache ?: boolean
142
166
}
143
167
144
168
/**
@@ -165,8 +189,12 @@ export function createSerializableStateInvariantMiddleware(
165
189
warnAfter = 32 ,
166
190
ignoreState = false ,
167
191
ignoreActions = false ,
192
+ disableCache = false ,
168
193
} = options
169
194
195
+ const cache : WeakSet < object > | undefined =
196
+ ! disableCache && WeakSet ? new WeakSet ( ) : undefined
197
+
170
198
return ( storeAPI ) => ( next ) => ( action ) => {
171
199
const result = next ( action )
172
200
@@ -185,7 +213,8 @@ export function createSerializableStateInvariantMiddleware(
185
213
'' ,
186
214
isSerializable ,
187
215
getEntries ,
188
- ignoredActionPaths
216
+ ignoredActionPaths ,
217
+ cache
189
218
)
190
219
191
220
if ( foundActionNonSerializableValue ) {
@@ -212,7 +241,8 @@ export function createSerializableStateInvariantMiddleware(
212
241
'' ,
213
242
isSerializable ,
214
243
getEntries ,
215
- ignoredPaths
244
+ ignoredPaths ,
245
+ cache
216
246
)
217
247
218
248
if ( foundStateNonSerializableValue ) {
0 commit comments