diff --git a/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue b/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue index eade49467..83bae23e6 100644 --- a/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue +++ b/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue @@ -109,6 +109,7 @@ import { import { DispatchRenderer, JsonForms, + useAjv, useJsonForms, useJsonFormsControlWithDetail, useTranslator, @@ -410,8 +411,8 @@ export default defineComponent({ validationMode: parentValidationMode, i18n, middleware, - ajv, } = useJsonForms(); + const ajv = useAjv(); // if the new property name is not specified then hide any errors const validationMode = computed(() => diff --git a/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts b/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts new file mode 100644 index 000000000..d99ae5a5e --- /dev/null +++ b/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts @@ -0,0 +1,43 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { clearAllIds, createAjv } from '@jsonforms/core'; +import { markRaw } from 'vue'; +import { extendedVuetifyRenderers } from '../../../src'; +import { mountJsonForms } from '../util/util'; + +// Check that `additionalProperties` reuses the parent form's AJV +describe('AdditionalProperties nested AJV', () => { + // A map whose key `pattern` is legal only without the `u` flag + const schema = { + type: 'object' as const, + properties: { + secretFiles: { + type: 'object' as const, + additionalProperties: { type: 'string' as const }, + propertyNames: { + pattern: '^"([^"$\\\\]|\\$(?!{)|\\\\.)*"$', + }, + }, + }, + }; + const uischema = { type: 'Control' as const, scope: '#' }; + + beforeEach(() => { + clearAllIds(); + }); + + it('mounts a map whose key pattern is only valid without the `u` flag', () => { + // A parent form configured with `unicodeRegExp: false` + const ajv = markRaw(createAjv({ unicodeRegExp: false })); + expect(() => + mountJsonForms( + { secretFiles: {} }, + schema, + extendedVuetifyRenderers, + uischema, + undefined, + undefined, + ajv, + ), + ).not.toThrow(); + }); +}); diff --git a/packages/vue-vuetify/tests/unit/util/TestComponent.vue b/packages/vue-vuetify/tests/unit/util/TestComponent.vue index eda1f44f1..4f62fbdea 100644 --- a/packages/vue-vuetify/tests/unit/util/TestComponent.vue +++ b/packages/vue-vuetify/tests/unit/util/TestComponent.vue @@ -6,6 +6,7 @@ :uischema="uischema" :renderers="renderers" :config="config" + :ajv="ajv" :i18n="i18n" @change="onChange" /> diff --git a/packages/vue-vuetify/tests/unit/util/util.ts b/packages/vue-vuetify/tests/unit/util/util.ts index a5c677035..00c63a83f 100644 --- a/packages/vue-vuetify/tests/unit/util/util.ts +++ b/packages/vue-vuetify/tests/unit/util/util.ts @@ -4,6 +4,7 @@ import type { JsonSchema, UISchemaElement, } from '@jsonforms/core'; +import type Ajv from 'ajv'; import { mount } from '@vue/test-utils'; import TestComponent from './TestComponent.vue'; import { createVuetify } from 'vuetify'; @@ -25,6 +26,7 @@ export const mountJsonForms = ( uischema?: UISchemaElement, config?: any, i18n?: JsonFormsI18nState, + ajv?: Ajv, ) => { return mount(TestComponent, { global: { @@ -37,6 +39,7 @@ export const mountJsonForms = ( config, renderers: markRaw(renderers), i18n, + ajv, }, attachTo: document.body, });