Skip to content

Commit d55d3be

Browse files
ivan-tymoshenkomcollina
authored andcommitted
fix: merged schemas caching
1 parent 1af56e3 commit d55d3be

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

index.js

+16-16
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ const validLargeArrayMechanisms = [
2929

3030
let schemaIdCounter = 0
3131

32-
const mergedSchemaRef = Symbol('fjs-merged-schema-ref')
33-
3432
function isValidSchema (schema, name) {
3533
if (!validate(schema)) {
3634
if (name) {
@@ -93,7 +91,8 @@ function build (schema, options) {
9391
options,
9492
refResolver: new RefResolver(),
9593
rootSchemaId: schema.$id || `__fjs_root_${schemaIdCounter++}`,
96-
validatorSchemasIds: new Set()
94+
validatorSchemasIds: new Set(),
95+
mergedSchemasIds: new Map()
9796
}
9897

9998
const schemaId = getSchemaId(schema, context.rootSchemaId)
@@ -408,7 +407,7 @@ function mergeLocations (context, mergedSchemaId, mergedLocations) {
408407

409408
const mergedSchemas = []
410409
for (const location of mergedLocations) {
411-
const schema = cloneOriginSchema(location.schema, location.schemaId)
410+
const schema = cloneOriginSchema(context, location.schema, location.schemaId)
412411
delete schema.$id
413412

414413
mergedSchemas.push(schema)
@@ -421,7 +420,7 @@ function mergeLocations (context, mergedSchemaId, mergedLocations) {
421420
return mergedLocation
422421
}
423422

424-
function cloneOriginSchema (schema, schemaId) {
423+
function cloneOriginSchema (context, schema, schemaId) {
425424
const clonedSchema = Array.isArray(schema) ? [] : {}
426425

427426
if (
@@ -431,8 +430,9 @@ function cloneOriginSchema (schema, schemaId) {
431430
schemaId = schema.$id
432431
}
433432

434-
if (schema[mergedSchemaRef]) {
435-
clonedSchema[mergedSchemaRef] = schema[mergedSchemaRef]
433+
const mergedSchemaRef = context.mergedSchemasIds.get(schema)
434+
if (mergedSchemaRef) {
435+
context.mergedSchemasIds.set(clonedSchema, mergedSchemaRef)
436436
}
437437

438438
for (const key in schema) {
@@ -443,7 +443,7 @@ function cloneOriginSchema (schema, schemaId) {
443443
}
444444

445445
if (typeof value === 'object' && value !== null) {
446-
value = cloneOriginSchema(value, schemaId)
446+
value = cloneOriginSchema(context, value, schemaId)
447447
}
448448

449449
clonedSchema[key] = value
@@ -780,14 +780,14 @@ function buildConstSerializer (location, input) {
780780
function buildAllOf (context, location, input) {
781781
const schema = location.schema
782782

783-
let mergedSchemaId = schema[mergedSchemaRef]
783+
let mergedSchemaId = context.mergedSchemasIds.get(schema)
784784
if (mergedSchemaId) {
785785
const mergedLocation = getMergedLocation(context, mergedSchemaId)
786786
return buildValue(context, mergedLocation, input)
787787
}
788788

789789
mergedSchemaId = `__fjs_merged_${schemaIdCounter++}`
790-
schema[mergedSchemaRef] = mergedSchemaId
790+
context.mergedSchemasIds.set(schema, mergedSchemaId)
791791

792792
const { allOf, ...schemaWithoutAllOf } = location.schema
793793
const locations = [
@@ -828,13 +828,13 @@ function buildOneOf (context, location, input) {
828828
const optionLocation = oneOfsLocation.getPropertyLocation(index)
829829
const optionSchema = optionLocation.schema
830830

831-
let mergedSchemaId = optionSchema[mergedSchemaRef]
831+
let mergedSchemaId = context.mergedSchemasIds.get(optionSchema)
832832
let mergedLocation = null
833833
if (mergedSchemaId) {
834834
mergedLocation = getMergedLocation(context, mergedSchemaId)
835835
} else {
836836
mergedSchemaId = `__fjs_merged_${schemaIdCounter++}`
837-
optionSchema[mergedSchemaRef] = mergedSchemaId
837+
context.mergedSchemasIds.set(optionSchema, mergedSchemaId)
838838

839839
mergedLocation = mergeLocations(context, mergedSchemaId, [
840840
locationWithoutOneOf,
@@ -882,13 +882,13 @@ function buildIfThenElse (context, location, input) {
882882
const ifSchemaRef = ifLocation.getSchemaRef()
883883

884884
const thenLocation = location.getPropertyLocation('then')
885-
let thenMergedSchemaId = thenSchema[mergedSchemaRef]
885+
let thenMergedSchemaId = context.mergedSchemasIds.get(thenSchema)
886886
let thenMergedLocation = null
887887
if (thenMergedSchemaId) {
888888
thenMergedLocation = getMergedLocation(context, thenMergedSchemaId)
889889
} else {
890890
thenMergedSchemaId = `__fjs_merged_${schemaIdCounter++}`
891-
thenSchema[mergedSchemaRef] = thenMergedSchemaId
891+
context.mergedSchemasIds.set(thenSchema, thenMergedSchemaId)
892892

893893
thenMergedLocation = mergeLocations(context, thenMergedSchemaId, [
894894
rootLocation,
@@ -907,13 +907,13 @@ function buildIfThenElse (context, location, input) {
907907
}
908908

909909
const elseLocation = location.getPropertyLocation('else')
910-
let elseMergedSchemaId = elseSchema[mergedSchemaRef]
910+
let elseMergedSchemaId = context.mergedSchemasIds.get(elseSchema)
911911
let elseMergedLocation = null
912912
if (elseMergedSchemaId) {
913913
elseMergedLocation = getMergedLocation(context, elseMergedSchemaId)
914914
} else {
915915
elseMergedSchemaId = `__fjs_merged_${schemaIdCounter++}`
916-
elseSchema[mergedSchemaRef] = elseMergedSchemaId
916+
context.mergedSchemasIds.set(elseSchema, elseMergedSchemaId)
917917

918918
elseMergedLocation = mergeLocations(context, elseMergedSchemaId, [
919919
rootLocation,

test/anyof.test.js

+27
Original file line numberDiff line numberDiff line change
@@ -765,3 +765,30 @@ test('external recursive anyOfs', (t) => {
765765
const stringify = build(schema, { schema: { externalSchema } })
766766
t.equal(stringify(data), '{"a":{"bar":"42","foo":{}},"b":{"bar":"42","foo":{}}}')
767767
})
768+
769+
test('should build merged schemas twice', (t) => {
770+
t.plan(2)
771+
772+
const schema = {
773+
type: 'object',
774+
properties: {
775+
enums: {
776+
type: 'string',
777+
anyOf: [
778+
{ type: 'string', const: 'FOO' },
779+
{ type: 'string', const: 'BAR' }
780+
]
781+
}
782+
}
783+
}
784+
785+
{
786+
const stringify = build(schema)
787+
t.equal(stringify({ enums: 'FOO' }), '{"enums":"FOO"}')
788+
}
789+
790+
{
791+
const stringify = build(schema)
792+
t.equal(stringify({ enums: 'BAR' }), '{"enums":"BAR"}')
793+
}
794+
})

0 commit comments

Comments
 (0)