@@ -38,7 +38,8 @@ export function findNonSerializableValue(
3838 path : string = '' ,
3939 isSerializable : ( value : unknown ) => boolean = isPlain ,
4040 getEntries ?: ( value : unknown ) => [ string , any ] [ ] ,
41- ignoredPaths : IgnorePaths = [ ]
41+ ignoredPaths : IgnorePaths = [ ] ,
42+ cache ?: WeakSet < object >
4243) : NonSerializableValue | false {
4344 let foundNestedSerializable : NonSerializableValue | false
4445
@@ -53,6 +54,8 @@ export function findNonSerializableValue(
5354 return false
5455 }
5556
57+ if ( cache ?. has ( value ) ) return false
58+
5659 const entries = getEntries != null ? getEntries ( value ) : Object . entries ( value )
5760
5861 const hasIgnoredPaths = ignoredPaths . length > 0
@@ -85,7 +88,8 @@ export function findNonSerializableValue(
8588 nestedPath ,
8689 isSerializable ,
8790 getEntries ,
88- ignoredPaths
91+ ignoredPaths ,
92+ cache
8993 )
9094
9195 if ( foundNestedSerializable ) {
@@ -94,9 +98,23 @@ export function findNonSerializableValue(
9498 }
9599 }
96100
101+ if ( cache && isNestedFrozen ( value ) ) cache . add ( value )
102+
97103 return false
98104}
99105
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+
100118/**
101119 * Options for `createSerializableStateInvariantMiddleware()`.
102120 *
@@ -150,6 +168,12 @@ export interface SerializableStateInvariantMiddlewareOptions {
150168 * Opt out of checking actions. When set to `true`, other action-related params will be ignored.
151169 */
152170 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
153177}
154178
155179/**
@@ -176,8 +200,12 @@ export function createSerializableStateInvariantMiddleware(
176200 warnAfter = 32 ,
177201 ignoreState = false ,
178202 ignoreActions = false ,
203+ disableCache = false ,
179204 } = options
180205
206+ const cache : WeakSet < object > | undefined =
207+ ! disableCache && WeakSet ? new WeakSet ( ) : undefined
208+
181209 return ( storeAPI ) => ( next ) => ( action ) => {
182210 const result = next ( action )
183211
@@ -196,7 +224,8 @@ export function createSerializableStateInvariantMiddleware(
196224 '' ,
197225 isSerializable ,
198226 getEntries ,
199- ignoredActionPaths
227+ ignoredActionPaths ,
228+ cache
200229 )
201230
202231 if ( foundActionNonSerializableValue ) {
@@ -223,7 +252,8 @@ export function createSerializableStateInvariantMiddleware(
223252 '' ,
224253 isSerializable ,
225254 getEntries ,
226- ignoredPaths
255+ ignoredPaths ,
256+ cache
227257 )
228258
229259 if ( foundStateNonSerializableValue ) {
0 commit comments