@@ -38,7 +38,8 @@ export function findNonSerializableValue(
38
38
path : string = '' ,
39
39
isSerializable : ( value : unknown ) => boolean = isPlain ,
40
40
getEntries ?: ( value : unknown ) => [ string , any ] [ ] ,
41
- ignoredPaths : IgnorePaths = [ ]
41
+ ignoredPaths : IgnorePaths = [ ] ,
42
+ cache ?: WeakSet < object >
42
43
) : NonSerializableValue | false {
43
44
let foundNestedSerializable : NonSerializableValue | false
44
45
@@ -53,6 +54,8 @@ export function findNonSerializableValue(
53
54
return false
54
55
}
55
56
57
+ if ( cache ?. has ( value ) ) return false
58
+
56
59
const entries = getEntries != null ? getEntries ( value ) : Object . entries ( value )
57
60
58
61
const hasIgnoredPaths = ignoredPaths . length > 0
@@ -85,7 +88,8 @@ export function findNonSerializableValue(
85
88
nestedPath ,
86
89
isSerializable ,
87
90
getEntries ,
88
- ignoredPaths
91
+ ignoredPaths ,
92
+ cache
89
93
)
90
94
91
95
if ( foundNestedSerializable ) {
@@ -94,9 +98,23 @@ export function findNonSerializableValue(
94
98
}
95
99
}
96
100
101
+ if ( cache && isNestedFrozen ( value ) ) cache . add ( value )
102
+
97
103
return false
98
104
}
99
105
106
+ export function isNestedFrozen ( value : object ) {
107
+ if ( ! Object . isFrozen ( value ) ) return false
108
+
109
+ for ( const nestedValue of Object . values ( value ) ) {
110
+ if ( typeof nestedValue !== 'object' || nestedValue === null ) continue
111
+
112
+ if ( ! isNestedFrozen ( nestedValue ) ) return false
113
+ }
114
+
115
+ return true
116
+ }
117
+
100
118
/**
101
119
* Options for `createSerializableStateInvariantMiddleware()`.
102
120
*
@@ -150,6 +168,12 @@ export interface SerializableStateInvariantMiddlewareOptions {
150
168
* Opt out of checking actions. When set to `true`, other action-related params will be ignored.
151
169
*/
152
170
ignoreActions ?: boolean
171
+
172
+ /**
173
+ * Opt out of caching the results. The cache uses a WeakSet and speeds up repeated checking processes.
174
+ * The cache is automatically disabled if no browser support for WeakSet is present.
175
+ */
176
+ disableCache ?: boolean
153
177
}
154
178
155
179
/**
@@ -176,8 +200,12 @@ export function createSerializableStateInvariantMiddleware(
176
200
warnAfter = 32 ,
177
201
ignoreState = false ,
178
202
ignoreActions = false ,
203
+ disableCache = false ,
179
204
} = options
180
205
206
+ const cache : WeakSet < object > | undefined =
207
+ ! disableCache && WeakSet ? new WeakSet ( ) : undefined
208
+
181
209
return ( storeAPI ) => ( next ) => ( action ) => {
182
210
const result = next ( action )
183
211
@@ -196,7 +224,8 @@ export function createSerializableStateInvariantMiddleware(
196
224
'' ,
197
225
isSerializable ,
198
226
getEntries ,
199
- ignoredActionPaths
227
+ ignoredActionPaths ,
228
+ cache
200
229
)
201
230
202
231
if ( foundActionNonSerializableValue ) {
@@ -223,7 +252,8 @@ export function createSerializableStateInvariantMiddleware(
223
252
'' ,
224
253
isSerializable ,
225
254
getEntries ,
226
- ignoredPaths
255
+ ignoredPaths ,
256
+ cache
227
257
)
228
258
229
259
if ( foundStateNonSerializableValue ) {
0 commit comments