Skip to content

Commit dbe83fb

Browse files
authored
Merge pull request #3129 from reduxjs/feature/regexp-in-ignored-paths
2 parents 85ec86b + 0fab520 commit dbe83fb

9 files changed

+84
-31
lines changed

docs/api/immutabilityMiddleware.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ interface ImmutableStateInvariantMiddlewareOptions {
2929
*/
3030
isImmutable?: IsImmutableFunc
3131
/**
32-
An array of dot-separated path strings that match named nodes from
32+
An array of dot-separated path strings or RegExps that match named nodes from
3333
the root state to ignore when checking for immutability.
3434
Defaults to undefined
3535
*/
36-
ignoredPaths?: string[]
36+
ignoredPaths?: (string | RegExp)[]
3737
/** Print a warning if checks take longer than N ms. Default: 32ms */
3838
warnAfter?: number
3939
// @deprecated. Use ignoredPaths

docs/api/serializabilityMiddleware.mdx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,17 @@ interface SerializableStateInvariantMiddlewareOptions {
3939
ignoredActions?: string[]
4040

4141
/**
42-
* An array of dot-separated path strings to ignore when checking
43-
* for serializability, Defaults to ['meta.arg', 'meta.baseQueryMeta']
42+
* An array of dot-separated path strings or regular expressions to ignore
43+
* when checking for serializability, Defaults to
44+
* ['meta.arg', 'meta.baseQueryMeta']
4445
*/
45-
ignoredActionPaths?: string[]
46+
ignoredActionPaths?: (string | RegExp)[]
4647

4748
/**
48-
* An array of dot-separated path strings to ignore when checking
49-
* for serializability, Defaults to []
49+
* An array of dot-separated path strings or regular expressions to ignore
50+
* when checking for serializability, Defaults to []
5051
*/
51-
ignoredPaths?: string[]
52+
ignoredPaths?: (string | RegExp)[]
5253
/**
5354
* Execution time warning threshold. If the middleware takes longer
5455
* than `warnAfter` ms, a warning will be displayed in the console.

packages/rtk-codemods/bin/cli.js

100644100755
File mode changed.

packages/toolkit/etc/redux-toolkit.api.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ export function findNonSerializableValue(
511511
path?: string,
512512
isSerializable?: (value: unknown) => boolean,
513513
getEntries?: (value: unknown) => [string, any][],
514-
ignoredPaths?: readonly string[]
514+
ignoredPaths?: readonly (string | RegExp)[]
515515
): NonSerializableValue | false
516516

517517
export { freeze }
@@ -762,9 +762,9 @@ export { Selector }
762762
// @public
763763
export interface SerializableStateInvariantMiddlewareOptions {
764764
getEntries?: (value: any) => [string, any][]
765-
ignoredActionPaths?: string[]
765+
ignoredActionPaths?: (string | RegExp)[]
766766
ignoredActions?: string[]
767-
ignoredPaths?: string[]
767+
ignoredPaths?: (string | RegExp)[]
768768
ignoreState?: boolean
769769
isSerializable?: (value: any) => boolean
770770
warnAfter?: number

packages/toolkit/src/immutableStateInvariantMiddleware.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function isImmutableDefault(value: unknown): boolean {
7272

7373
export function trackForMutations(
7474
isImmutable: IsImmutableFunc,
75-
ignorePaths: string[] | undefined,
75+
ignorePaths: IgnorePaths | undefined,
7676
obj: any
7777
) {
7878
const trackedProperties = trackProperties(isImmutable, ignorePaths, obj)
@@ -116,11 +116,11 @@ function trackProperties(
116116
return tracked as TrackedProperty
117117
}
118118

119-
type IgnorePaths = readonly string[]
119+
type IgnorePaths = readonly (string | RegExp)[]
120120

121121
function detectMutations(
122122
isImmutable: IsImmutableFunc,
123-
ignorePaths: IgnorePaths = [],
123+
ignoredPaths: IgnorePaths = [],
124124
trackedProperty: TrackedProperty,
125125
obj: any,
126126
sameParentRef: boolean = false,
@@ -147,19 +147,30 @@ function detectMutations(
147147
keysToDetect[key] = true
148148
}
149149

150+
const hasIgnoredPaths = ignoredPaths.length > 0
151+
150152
for (let key in keysToDetect) {
151-
const childPath = path ? path + '.' + key : key
152-
if (ignorePaths.length && ignorePaths.indexOf(childPath) !== -1) {
153-
continue
153+
const nestedPath = path ? path + '.' + key : key
154+
155+
if (hasIgnoredPaths) {
156+
const hasMatches = ignoredPaths.some((ignored) => {
157+
if (ignored instanceof RegExp) {
158+
return ignored.test(nestedPath)
159+
}
160+
return nestedPath === ignored
161+
})
162+
if (hasMatches) {
163+
continue
164+
}
154165
}
155166

156167
const result = detectMutations(
157168
isImmutable,
158-
ignorePaths,
169+
ignoredPaths,
159170
trackedProperty.children[key],
160171
obj[key],
161172
sameRef,
162-
childPath
173+
nestedPath
163174
)
164175

165176
if (result.wasMutated) {
@@ -189,7 +200,7 @@ export interface ImmutableStateInvariantMiddlewareOptions {
189200
the root state to ignore when checking for immutability.
190201
Defaults to undefined
191202
*/
192-
ignoredPaths?: string[]
203+
ignoredPaths?: IgnorePaths
193204
/** Print a warning if checks take longer than N ms. Default: 32ms */
194205
warnAfter?: number
195206
// @deprecated. Use ignoredPaths

packages/toolkit/src/serializableStateInvariantMiddleware.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ interface NonSerializableValue {
2828
value: unknown
2929
}
3030

31+
type IgnorePaths = readonly (string | RegExp)[]
32+
3133
/**
3234
* @public
3335
*/
@@ -36,7 +38,7 @@ export function findNonSerializableValue(
3638
path: string = '',
3739
isSerializable: (value: unknown) => boolean = isPlain,
3840
getEntries?: (value: unknown) => [string, any][],
39-
ignoredPaths: readonly string[] = []
41+
ignoredPaths: IgnorePaths = []
4042
): NonSerializableValue | false {
4143
let foundNestedSerializable: NonSerializableValue | false
4244

@@ -58,8 +60,16 @@ export function findNonSerializableValue(
5860
for (const [key, nestedValue] of entries) {
5961
const nestedPath = path ? path + '.' + key : key
6062

61-
if (hasIgnoredPaths && ignoredPaths.indexOf(nestedPath) >= 0) {
62-
continue
63+
if (hasIgnoredPaths) {
64+
const hasMatches = ignoredPaths.some((ignored) => {
65+
if (ignored instanceof RegExp) {
66+
return ignored.test(nestedPath)
67+
}
68+
return nestedPath === ignored
69+
})
70+
if (hasMatches) {
71+
continue
72+
}
6373
}
6474

6575
if (!isSerializable(nestedValue)) {
@@ -113,16 +123,17 @@ export interface SerializableStateInvariantMiddlewareOptions {
113123
ignoredActions?: string[]
114124

115125
/**
116-
* An array of dot-separated path strings to ignore when checking
117-
* for serializability, Defaults to ['meta.arg', 'meta.baseQueryMeta']
126+
* An array of dot-separated path strings or regular expressions to ignore
127+
* when checking for serializability, Defaults to
128+
* ['meta.arg', 'meta.baseQueryMeta']
118129
*/
119-
ignoredActionPaths?: string[]
130+
ignoredActionPaths?: (string | RegExp)[]
120131

121132
/**
122-
* An array of dot-separated path strings to ignore when checking
123-
* for serializability, Defaults to []
133+
* An array of dot-separated path strings or regular expressions to ignore
134+
* when checking for serializability, Defaults to []
124135
*/
125-
ignoredPaths?: string[]
136+
ignoredPaths?: (string | RegExp)[]
126137
/**
127138
* Execution time warning threshold. If the middleware takes longer
128139
* than `warnAfter` ms, a warning will be displayed in the console.

packages/toolkit/src/tests/__snapshots__/serializableStateInvariantMiddleware.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Take a look at the reducer(s) handling this action type: TEST_ACTION.
3131

3232
exports[`serializableStateInvariantMiddleware ignored action paths can specify (multiple) different values 1`] = `""`;
3333

34+
exports[`serializableStateInvariantMiddleware ignored action paths can specify regexp 1`] = `""`;
35+
3436
exports[`serializableStateInvariantMiddleware ignored action paths default value can be overridden 1`] = `
3537
"A non-serializable value was detected in an action, in the path: \`meta.arg\`. Value: Map {}
3638
Take a look at the logic that dispatched this action: Object {

packages/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,16 @@ describe('createImmutableStateInvariantMiddleware', () => {
121121
return action
122122
}
123123

124-
const dispatch = middleware({ ignoredPaths: ['foo.bar'] })(next)
124+
const dispatch1 = middleware({ ignoredPaths: ['foo.bar'] })(next)
125125

126126
expect(() => {
127-
dispatch({ type: 'SOME_ACTION' })
127+
dispatch1({ type: 'SOME_ACTION' })
128+
}).not.toThrow()
129+
130+
const dispatch2 = middleware({ ignoredPaths: [/^foo/] })(next)
131+
132+
expect(() => {
133+
dispatch2({ type: 'SOME_ACTION' })
128134
}).not.toThrow()
129135
})
130136

packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,22 @@ describe('serializableStateInvariantMiddleware', () => {
389389

390390
expect(getLog().log).toMatchInlineSnapshot(`""`)
391391
})
392+
393+
it('can specify regexp', () => {
394+
configureStore({
395+
reducer,
396+
middleware: [
397+
createSerializableStateInvariantMiddleware({
398+
ignoredActionPaths: [/^payload\..*$/],
399+
}),
400+
],
401+
}).dispatch({
402+
type: 'test',
403+
payload: { arg: nonSerializableValue },
404+
})
405+
406+
expect(getLog().log).toMatchInlineSnapshot(`""`)
407+
})
392408
})
393409

394410
it('allows ignoring actions entirely', () => {
@@ -439,6 +455,10 @@ describe('serializableStateInvariantMiddleware', () => {
439455
d: badValue,
440456
},
441457
e: { f: badValue },
458+
g: {
459+
h: badValue,
460+
i: badValue,
461+
},
442462
}
443463
}
444464
default:
@@ -455,6 +475,8 @@ describe('serializableStateInvariantMiddleware', () => {
455475
'testSlice.b.c',
456476
// Test for ignoring an object and its children
457477
'testSlice.e',
478+
// Test for ignoring based on RegExp
479+
/^testSlice\.g\..*$/,
458480
],
459481
})
460482

0 commit comments

Comments
 (0)