Skip to content

Commit a9b2fd6

Browse files
Change fast-deep-equal to fast-equals
1 parent be3b6b4 commit a9b2fd6

File tree

16 files changed

+74
-49
lines changed

16 files changed

+74
-49
lines changed

package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,8 @@
8080
"packages/validator-ajv8",
8181
"packages/snapshot-tests"
8282
],
83-
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
83+
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
84+
"dependencies": {
85+
"fast-equals": "^5.0.1"
86+
}
8487
}

packages/core/src/components/Form.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import _get from 'lodash/get';
3939
import _isEmpty from 'lodash/isEmpty';
4040
import _pick from 'lodash/pick';
4141
import _toPath from 'lodash/toPath';
42-
import fastDeepEqual from 'fast-deep-equal';
4342

4443
import getDefaultRegistry from '../getDefaultRegistry';
4544

@@ -283,7 +282,7 @@ export default class Form<
283282
}
284283

285284
this.state = this.getStateFromProps(props, props.formData);
286-
if (this.props.onChange && !fastDeepEqual(this.state.formData, this.props.formData)) {
285+
if (this.props.onChange && !deepEquals(this.state.formData, this.props.formData)) {
287286
this.props.onChange(this.state);
288287
}
289288
this.formElement = createRef();
@@ -316,8 +315,8 @@ export default class Form<
316315
shouldUpdate: false;
317316
} {
318317
if (!deepEquals(this.props, prevProps)) {
319-
const isSchemaChanged = !fastDeepEqual(prevProps.schema, this.props.schema);
320-
const isFormDataChanged = !fastDeepEqual(prevProps.formData, this.props.formData);
318+
const isSchemaChanged = !deepEquals(prevProps.schema, this.props.schema);
319+
const isFormDataChanged = !deepEquals(prevProps.formData, this.props.formData);
321320
const nextState = this.getStateFromProps(
322321
this.props,
323322
this.props.formData,
@@ -361,8 +360,8 @@ export default class Form<
361360
const { nextState } = snapshot;
362361

363362
if (
364-
!fastDeepEqual(nextState.formData, this.props.formData) &&
365-
!fastDeepEqual(nextState.formData, prevState.formData) &&
363+
!deepEquals(nextState.formData, this.props.formData) &&
364+
!deepEquals(nextState.formData, prevState.formData) &&
366365
this.props.onChange
367366
) {
368367
this.props.onChange(nextState);

packages/core/src/components/fields/MultiSchemaField.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import isEmpty from 'lodash/isEmpty';
44
import omit from 'lodash/omit';
55
import {
66
ANY_OF_KEY,
7+
deepEquals,
78
ERRORS_KEY,
89
FieldProps,
910
FormContextType,
@@ -17,7 +18,6 @@ import {
1718
TranslatableString,
1819
UiSchema,
1920
} from '@rjsf/utils';
20-
import fastDeepEqual from 'fast-deep-equal';
2121

2222
/** Type used for the state of the `AnyOfField` component */
2323
type AnyOfFieldState<S extends StrictRJSFSchema = RJSFSchema> = {
@@ -67,15 +67,15 @@ class AnyOfField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends For
6767
const { formData, options, idSchema } = this.props;
6868
const { selectedOption } = this.state;
6969
let newState = this.state;
70-
if (!fastDeepEqual(prevProps.options, options)) {
70+
if (!deepEquals(prevProps.options, options)) {
7171
const {
7272
registry: { schemaUtils },
7373
} = this.props;
7474
// re-cache the retrieved options in state in case they have $refs to save doing it later
7575
const retrievedOptions = options.map((opt: S) => schemaUtils.retrieveSchema(opt, formData));
7676
newState = { selectedOption, retrievedOptions };
7777
}
78-
if (!fastDeepEqual(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
78+
if (!deepEquals(formData, prevProps.formData) && idSchema.$id === prevProps.idSchema.$id) {
7979
const { retrievedOptions } = newState;
8080
const matchingOption = this.getMatchingOption(selectedOption, formData, retrievedOptions);
8181

packages/utils/src/createSchemaUtils.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import fastDeepEqual from 'fast-deep-equal';
2-
31
import {
42
ErrorSchema,
53
Experimental_DefaultFormStateBehavior,
@@ -29,6 +27,7 @@ import {
2927
toIdSchema,
3028
toPathSchema,
3129
} from './schema';
30+
import deepEquals from './deepEquals';
3231

3332
/** The `SchemaUtils` class provides a wrapper around the publicly exported APIs in the `utils/schema` directory such
3433
* that one does not have to explicitly pass the `validator`, `rootSchema`, or `experimental_defaultFormStateBehavior` to each method.
@@ -85,8 +84,8 @@ class SchemaUtils<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends Fo
8584
}
8685
return (
8786
this.validator !== validator ||
88-
!fastDeepEqual(this.rootSchema, rootSchema) ||
89-
!fastDeepEqual(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior)
87+
!deepEquals(this.rootSchema, rootSchema) ||
88+
!deepEquals(this.experimental_defaultFormStateBehavior, experimental_defaultFormStateBehavior)
9089
);
9190
}
9291

packages/utils/src/deepEquals.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
1-
import isEqualWith from 'lodash/isEqualWith';
1+
import { createCustomEqual, State } from 'fast-equals';
2+
3+
function isFunctions(a: any, b: any) {
4+
return typeof a === 'function' && typeof b === 'function';
5+
}
6+
7+
const customDeepEqual = createCustomEqual({
8+
createInternalComparator: (comparator: (a: any, b: any, state: State<any>) => boolean) => {
9+
return (a: any, b: any, _idxA: any, _idxB: any, _parentA: any, _parentB: any, state: State<any>) => {
10+
if (isFunctions(a, b)) {
11+
// Assume all functions are equivalent
12+
// see https://github.com/rjsf-team/react-jsonschema-form/issues/255
13+
return true;
14+
}
15+
16+
return comparator(a, b, state);
17+
};
18+
},
19+
});
220

321
/** Implements a deep equals using the `lodash.isEqualWith` function, that provides a customized comparator that
422
* assumes all functions are equivalent.
@@ -8,12 +26,8 @@ import isEqualWith from 'lodash/isEqualWith';
826
* @returns - True if the `a` and `b` are deeply equal, false otherwise
927
*/
1028
export default function deepEquals(a: any, b: any): boolean {
11-
return isEqualWith(a, b, (obj: any, other: any) => {
12-
if (typeof obj === 'function' && typeof other === 'function') {
13-
// Assume all functions are equivalent
14-
// see https://github.com/rjsf-team/react-jsonschema-form/issues/255
15-
return true;
16-
}
17-
return undefined; // fallback to default isEquals behavior
18-
});
29+
if (isFunctions(a, b)) {
30+
return true;
31+
}
32+
return customDeepEqual(a, b);
1933
}

packages/utils/src/enumOptionsDeselectValue.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import fastDeepEqual from 'fast-deep-equal';
2-
31
import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
42
import enumOptionsValueForIndex from './enumOptionsValueForIndex';
3+
import deepEquals from './deepEquals';
54

65
/** Removes the enum option value at the `valueIndex` from the currently `selected` (list of) value(s). If `selected` is
76
* a list, then that list is updated to remove the enum option value with the `valueIndex` in `allEnumOptions`. If it is
@@ -22,7 +21,7 @@ export default function enumOptionsDeselectValue<S extends StrictRJSFSchema = RJ
2221
): EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][] | undefined {
2322
const value = enumOptionsValueForIndex<S>(valueIndex, allEnumOptions);
2423
if (Array.isArray(selected)) {
25-
return selected.filter((v) => !fastDeepEqual(v, value));
24+
return selected.filter((v) => !deepEquals(v, value));
2625
}
27-
return fastDeepEqual(value, selected) ? undefined : selected;
26+
return deepEquals(value, selected) ? undefined : selected;
2827
}

packages/utils/src/enumOptionsIsSelected.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import fastDeepEqual from 'fast-deep-equal';
2-
1+
import deepEquals from './deepEquals';
32
import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types';
43

54
/** Determines whether the given `value` is (one of) the `selected` value(s).
@@ -13,7 +12,7 @@ export default function enumOptionsIsSelected<S extends StrictRJSFSchema = RJSFS
1312
selected: EnumOptionsType<S>['value'] | EnumOptionsType<S>['value'][]
1413
) {
1514
if (Array.isArray(selected)) {
16-
return selected.some((sel) => fastDeepEqual(sel, value));
15+
return selected.some((sel) => deepEquals(sel, value));
1716
}
18-
return fastDeepEqual(selected, value);
17+
return deepEquals(selected, value);
1918
}

packages/utils/src/parser/ParserValidator.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import get from 'lodash/get';
2-
import fastDeepEqual from 'fast-deep-equal';
32

43
import { ID_KEY } from '../constants';
54
import hashForSchema from '../hashForSchema';
@@ -15,6 +14,7 @@ import {
1514
ValidationData,
1615
ValidatorType,
1716
} from '../types';
17+
import deepEquals from '../deepEquals';
1818

1919
/** The type of the map of schema hash to schema
2020
*/
@@ -67,7 +67,7 @@ export default class ParserValidator<T = any, S extends StrictRJSFSchema = RJSFS
6767
const existing = this.schemaMap[key];
6868
if (!existing) {
6969
this.schemaMap[key] = identifiedSchema;
70-
} else if (!fastDeepEqual(existing, identifiedSchema)) {
70+
} else if (!deepEquals(existing, identifiedSchema)) {
7171
console.error('existing schema:', JSON.stringify(existing, null, 2));
7272
console.error('new schema:', JSON.stringify(identifiedSchema, null, 2));
7373
throw new Error(
@@ -91,7 +91,7 @@ export default class ParserValidator<T = any, S extends StrictRJSFSchema = RJSFS
9191
* @throws - Error when the given `rootSchema` differs from the root schema provided during construction
9292
*/
9393
isValid(schema: S, _formData: T, rootSchema: S): boolean {
94-
if (!fastDeepEqual(rootSchema, this.rootSchema)) {
94+
if (!deepEquals(rootSchema, this.rootSchema)) {
9595
throw new Error('Unexpectedly calling isValid() with a rootSchema that differs from the construction rootSchema');
9696
}
9797
this.addSchema(schema, hashForSchema<S>(schema));

packages/utils/src/parser/schemaParser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import forEach from 'lodash/forEach';
2-
import fastDeepEqual from 'fast-deep-equal';
32

43
import { FormContextType, RJSFSchema, StrictRJSFSchema } from '../types';
54
import { ITEMS_KEY, PROPERTIES_KEY } from '../constants';
65
import ParserValidator, { SchemaMap } from './ParserValidator';
76
import { resolveAnyOrOneOfSchemas, retrieveSchemaInternal } from '../schema/retrieveSchema';
7+
import deepEquals from '../deepEquals';
88

99
/** Recursive function used to parse the given `schema` belonging to the `rootSchema`. The `validator` is used to
1010
* capture the sub-schemas that the `isValid()` function is called with. For each schema returned by the
@@ -24,7 +24,7 @@ function parseSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends
2424
) {
2525
const schemas = retrieveSchemaInternal<T, S, F>(validator, schema, rootSchema, undefined, true);
2626
schemas.forEach((schema) => {
27-
const sameSchemaIndex = recurseList.findIndex((item) => fastDeepEqual(item, schema));
27+
const sameSchemaIndex = recurseList.findIndex((item) => deepEquals(item, schema));
2828
if (sameSchemaIndex === -1) {
2929
recurseList.push(schema);
3030
const allOptions = resolveAnyOrOneOfSchemas<T, S, F>(validator, schema, rootSchema, true);

0 commit comments

Comments
 (0)