diff --git a/CHANGELOG.md b/CHANGELOG.md index 64fea9c27e..f0655f95d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,10 +29,12 @@ should change the heading of the (upcoming) version to include a major version b - Fixed issue with assigning default values to formData with deeply nested required properties, fixing [#4399](/~https://github.com/rjsf-team/react-jsonschema-form/issues/4399) - Fixed issue error message will not be cleared after the controlled Form formData is changed. Fixes [#4426](/~https://github.com/rjsf-team/react-jsonschema-form/issues/4426) - Fix for AJV [$data](https://ajv.js.org/guide/combining-schemas.html#data-reference) reference in const property in schema treated as default/const value. The issue is mentioned in [#4361](/~https://github.com/rjsf-team/react-jsonschema-form/issues/4361). +- Switched uses of `lodash.isEqual()` to `@rjsf/utils.deepEquals`. ## @rjsf/validator-ajv8 - Partially fixed issue where dependency errors do not show `title` or `ui:title`. This fix only applicable if we use an ajv-i18n localizer. Ref. [#4402](/~https://github.com/rjsf-team/react-jsonschema-form/issues/4402). +- Switched uses of `lodash.isEqual()` to `@rjsf/utils.deepEquals` at precompiledValidator. # 5.23.2 diff --git a/packages/utils/src/enumOptionsDeselectValue.ts b/packages/utils/src/enumOptionsDeselectValue.ts index 1dde198c32..88384321e5 100644 --- a/packages/utils/src/enumOptionsDeselectValue.ts +++ b/packages/utils/src/enumOptionsDeselectValue.ts @@ -1,7 +1,6 @@ -import isEqual from 'lodash/isEqual'; - import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types'; import enumOptionsValueForIndex from './enumOptionsValueForIndex'; +import deepEquals from './deepEquals'; /** Removes the enum option value at the `valueIndex` from the currently `selected` (list of) value(s). If `selected` is * 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['value'] | EnumOptionsType['value'][] | undefined { const value = enumOptionsValueForIndex(valueIndex, allEnumOptions); if (Array.isArray(selected)) { - return selected.filter((v) => !isEqual(v, value)); + return selected.filter((v) => !deepEquals(v, value)); } - return isEqual(value, selected) ? undefined : selected; + return deepEquals(value, selected) ? undefined : selected; } diff --git a/packages/utils/src/enumOptionsIsSelected.ts b/packages/utils/src/enumOptionsIsSelected.ts index a1c9fed1dd..1b555e1126 100644 --- a/packages/utils/src/enumOptionsIsSelected.ts +++ b/packages/utils/src/enumOptionsIsSelected.ts @@ -1,6 +1,5 @@ -import isEqual from 'lodash/isEqual'; - import { EnumOptionsType, RJSFSchema, StrictRJSFSchema } from './types'; +import deepEquals from './deepEquals'; /** Determines whether the given `value` is (one of) the `selected` value(s). * @@ -13,7 +12,7 @@ export default function enumOptionsIsSelected['value'] | EnumOptionsType['value'][] ) { if (Array.isArray(selected)) { - return selected.some((sel) => isEqual(sel, value)); + return selected.some((sel) => deepEquals(sel, value)); } - return isEqual(selected, value); + return deepEquals(selected, value); } diff --git a/packages/utils/src/parser/ParserValidator.ts b/packages/utils/src/parser/ParserValidator.ts index f1b771fc39..d6411a85f7 100644 --- a/packages/utils/src/parser/ParserValidator.ts +++ b/packages/utils/src/parser/ParserValidator.ts @@ -1,5 +1,4 @@ import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; import { ID_KEY } from '../constants'; import hashForSchema from '../hashForSchema'; @@ -15,6 +14,7 @@ import { ValidationData, ValidatorType, } from '../types'; +import deepEquals from '../deepEquals'; /** The type of the map of schema hash to schema */ @@ -67,7 +67,7 @@ export default class ParserValidator(schema)); diff --git a/packages/utils/src/parser/schemaParser.ts b/packages/utils/src/parser/schemaParser.ts index 70151f06a0..f7e8ffa538 100644 --- a/packages/utils/src/parser/schemaParser.ts +++ b/packages/utils/src/parser/schemaParser.ts @@ -1,10 +1,10 @@ import forEach from 'lodash/forEach'; -import isEqual from 'lodash/isEqual'; import { FormContextType, RJSFSchema, StrictRJSFSchema } from '../types'; -import { PROPERTIES_KEY, ITEMS_KEY } from '../constants'; +import { ITEMS_KEY, PROPERTIES_KEY } from '../constants'; import ParserValidator, { SchemaMap } from './ParserValidator'; -import { retrieveSchemaInternal, resolveAnyOrOneOfSchemas } from '../schema/retrieveSchema'; +import { resolveAnyOrOneOfSchemas, retrieveSchemaInternal } from '../schema/retrieveSchema'; +import deepEquals from '../deepEquals'; /** Recursive function used to parse the given `schema` belonging to the `rootSchema`. The `validator` is used to * capture the sub-schemas that the `isValid()` function is called with. For each schema returned by the @@ -24,7 +24,7 @@ function parseSchema(validator, schema, rootSchema, undefined, true); schemas.forEach((schema) => { - const sameSchemaIndex = recurseList.findIndex((item) => isEqual(item, schema)); + const sameSchemaIndex = recurseList.findIndex((item) => deepEquals(item, schema)); if (sameSchemaIndex === -1) { recurseList.push(schema); const allOptions = resolveAnyOrOneOfSchemas(validator, schema, rootSchema, true); diff --git a/packages/utils/src/schema/getDefaultFormState.ts b/packages/utils/src/schema/getDefaultFormState.ts index 7974e1b07d..e3f480cae2 100644 --- a/packages/utils/src/schema/getDefaultFormState.ts +++ b/packages/utils/src/schema/getDefaultFormState.ts @@ -1,15 +1,16 @@ import get from 'lodash/get'; import isEmpty from 'lodash/isEmpty'; +import { JSONSchema7Object } from 'json-schema'; import { + ALL_OF_KEY, ANY_OF_KEY, CONST_KEY, DEFAULT_KEY, DEPENDENCIES_KEY, - PROPERTIES_KEY, ONE_OF_KEY, + PROPERTIES_KEY, REF_KEY, - ALL_OF_KEY, } from '../constants'; import findSchemaDefinition from '../findSchemaDefinition'; import getClosestMatchingOption from './getClosestMatchingOption'; @@ -33,10 +34,9 @@ import isMultiSelect from './isMultiSelect'; import isSelect from './isSelect'; import retrieveSchema, { resolveDependencies } from './retrieveSchema'; import isConstant from '../isConstant'; -import { JSONSchema7Object } from 'json-schema'; import constIsAjvDataReference from '../constIsAjvDataReference'; -import isEqual from 'lodash/isEqual'; import optionsList from '../optionsList'; +import deepEquals from '../deepEquals'; const PRIMITIVE_TYPES = ['string', 'number', 'integer', 'boolean', 'null']; @@ -130,8 +130,7 @@ function maybeAddDefaultToObject( if (!isEmpty(computedDefault)) { obj[key] = computedDefault; } - } - // Else store computedDefault if it's a non-empty object(e.g. not {}) and satisfies certain conditions + } // Else store computedDefault if it's a non-empty object(e.g. not {}) and satisfies certain conditions // Condition 1: If computedDefault is not empty or if the key is a required field // Condition 2: If the parent object is required or emptyObjectFields is not 'populateRequiredDefaults' else if ( @@ -276,7 +275,10 @@ export function computeDefaults( @@ -382,7 +384,7 @@ export function ensureFormDataMatchingSchema< let validFormData: T | T[] | undefined = formData; if (isSelectField) { const getOptionsList = optionsList(schema); - const isValid = getOptionsList?.some((option) => isEqual(option.value, formData)); + const isValid = getOptionsList?.some((option) => deepEquals(option.value, formData)); validFormData = isValid ? formData : undefined; } diff --git a/packages/utils/src/schema/retrieveSchema.ts b/packages/utils/src/schema/retrieveSchema.ts index 17439cf396..86a0853c5f 100644 --- a/packages/utils/src/schema/retrieveSchema.ts +++ b/packages/utils/src/schema/retrieveSchema.ts @@ -1,5 +1,4 @@ import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; import set from 'lodash/set'; import times from 'lodash/times'; import transform from 'lodash/transform'; @@ -15,10 +14,10 @@ import { ANY_OF_KEY, DEPENDENCIES_KEY, IF_KEY, + ITEMS_KEY, ONE_OF_KEY, - REF_KEY, PROPERTIES_KEY, - ITEMS_KEY, + REF_KEY, } from '../constants'; import findSchemaDefinition, { splitKeyElementFromObject } from '../findSchemaDefinition'; import getDiscriminatorFieldFromSchema from '../getDiscriminatorFieldFromSchema'; @@ -34,6 +33,7 @@ import { ValidatorType, } from '../types'; import getFirstMatchingOption from './getFirstMatchingOption'; +import deepEquals from '../deepEquals'; /** Retrieves an expanded schema that has had all of its conditions, additional properties, references and dependencies * resolved and merged into the `schema` given a `validator`, `rootSchema` and `rawFormData` that is used to do the @@ -256,7 +256,10 @@ export function resolveSchema(allOfSchemaElements); - return allPermutations.map((permutation) => ({ ...schema, allOf: permutation })); + return allPermutations.map((permutation) => ({ + ...schema, + allOf: permutation, + })); } // No $ref or dependencies or allOf attribute was found, returning the original schema. return [schema]; @@ -356,7 +359,7 @@ export function resolveAllReferences( }; } - return isEqual(schema, resolvedSchema) ? schema : resolvedSchema; + return deepEquals(schema, resolvedSchema) ? schema : resolvedSchema; } /** Creates new 'properties' items for each key in the `formData` diff --git a/packages/utils/src/schema/toIdSchema.ts b/packages/utils/src/schema/toIdSchema.ts index 21cb334517..4e034a5de3 100644 --- a/packages/utils/src/schema/toIdSchema.ts +++ b/packages/utils/src/schema/toIdSchema.ts @@ -1,5 +1,4 @@ import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; import { ALL_OF_KEY, DEPENDENCIES_KEY, ID_KEY, ITEMS_KEY, PROPERTIES_KEY, REF_KEY } from '../constants'; import isObject from '../isObject'; @@ -14,6 +13,7 @@ import { } from '../types'; import retrieveSchema from './retrieveSchema'; import getSchemaType from '../getSchemaType'; +import deepEquals from '../deepEquals'; /** An internal helper that generates an `IdSchema` object for the `schema`, recursively with protection against * infinite recursion @@ -42,7 +42,7 @@ function toIdSchemaInternal { if (REF_KEY in schema || DEPENDENCIES_KEY in schema || ALL_OF_KEY in schema) { const _schema = retrieveSchema(validator, schema, rootSchema, formData, experimental_customMergeAllOf); - const sameSchemaIndex = _recurseList.findIndex((item) => isEqual(item, _schema)); + const sameSchemaIndex = _recurseList.findIndex((item) => deepEquals(item, _schema)); if (sameSchemaIndex === -1) { return toIdSchemaInternal( validator, diff --git a/packages/utils/src/schema/toPathSchema.ts b/packages/utils/src/schema/toPathSchema.ts index d29f225e5a..638b7126ce 100644 --- a/packages/utils/src/schema/toPathSchema.ts +++ b/packages/utils/src/schema/toPathSchema.ts @@ -1,11 +1,10 @@ import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; import set from 'lodash/set'; import { + ADDITIONAL_PROPERTIES_KEY, ALL_OF_KEY, ANY_OF_KEY, - ADDITIONAL_PROPERTIES_KEY, DEPENDENCIES_KEY, ITEMS_KEY, NAME_KEY, @@ -26,6 +25,7 @@ import { } from '../types'; import getClosestMatchingOption from './getClosestMatchingOption'; import retrieveSchema from './retrieveSchema'; +import deepEquals from '../deepEquals'; /** An internal helper that generates an `PathSchema` object for the `schema`, recursively with protection against * infinite recursion @@ -50,7 +50,7 @@ function toPathSchemaInternal { if (REF_KEY in schema || DEPENDENCIES_KEY in schema || ALL_OF_KEY in schema) { const _schema = retrieveSchema(validator, schema, rootSchema, formData, experimental_customMergeAllOf); - const sameSchemaIndex = _recurseList.findIndex((item) => isEqual(item, _schema)); + const sameSchemaIndex = _recurseList.findIndex((item) => deepEquals(item, _schema)); if (sameSchemaIndex === -1) { return toPathSchemaInternal( validator, diff --git a/packages/validator-ajv8/src/precompiledValidator.ts b/packages/validator-ajv8/src/precompiledValidator.ts index 3b201b9a90..a79c079dcd 100644 --- a/packages/validator-ajv8/src/precompiledValidator.ts +++ b/packages/validator-ajv8/src/precompiledValidator.ts @@ -1,21 +1,22 @@ import { ErrorObject } from 'ajv'; import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; + import { CustomValidator, + deepEquals, ErrorSchema, ErrorTransformer, FormContextType, hashForSchema, ID_KEY, JUNK_OPTION_ID, + retrieveSchema, RJSFSchema, StrictRJSFSchema, toErrorList, UiSchema, ValidationData, ValidatorType, - retrieveSchema, } from '@rjsf/utils'; import { CompiledValidateFunction, Localizer, ValidatorFunctions } from './types'; @@ -92,10 +93,10 @@ export default class AJV8PrecompiledValidator< * @param [formData] - The form data to validate if any */ ensureSameRootSchema(schema: S, formData?: T) { - if (!isEqual(schema, this.rootSchema)) { + if (!deepEquals(schema, this.rootSchema)) { // Resolve the root schema with the passed in form data since that may affect the resolution const resolvedRootSchema = retrieveSchema(this, this.rootSchema, this.rootSchema, formData); - if (!isEqual(schema, resolvedRootSchema)) { + if (!deepEquals(schema, resolvedRootSchema)) { throw new Error( 'The schema associated with the precompiled validator differs from the rootSchema provided for validation' );