diff --git a/ext/bg/js/json-schema.js b/ext/bg/js/json-schema.js index 4d77f0db..adb71fa3 100644 --- a/ext/bg/js/json-schema.js +++ b/ext/bg/js/json-schema.js @@ -147,34 +147,8 @@ class JsonSchemaValidator { } getValidValueOrDefault(schema, value) { - let type = this._getValueType(value); - const schemaType = schema.type; - if (typeof value === 'undefined' || !this._isValueTypeAny(value, type, schemaType)) { - let assignDefault = true; - - const schemaDefault = schema.default; - if (typeof schemaDefault !== 'undefined') { - value = clone(schemaDefault); - type = this._getValueType(value); - assignDefault = !this._isValueTypeAny(value, type, schemaType); - } - - if (assignDefault) { - value = this._getDefaultTypeValue(schemaType); - type = this._getValueType(value); - } - } - - switch (type) { - case 'object': - value = this._populateObjectDefaults(value, schema); - break; - case 'array': - value = this._populateArrayDefaults(value, schema); - break; - } - - return value; + const info = new JsonSchemaTraversalInfo(value, schema); + return this._getValidValueOrDefault(schema, value, info); } getPropertySchema(schema, property, value) { @@ -620,7 +594,38 @@ class JsonSchemaValidator { return null; } - _populateObjectDefaults(value, schema) { + _getValidValueOrDefault(schema, value, info) { + let type = this._getValueType(value); + const schemaType = schema.type; + if (typeof value === 'undefined' || !this._isValueTypeAny(value, type, schemaType)) { + let assignDefault = true; + + const schemaDefault = schema.default; + if (typeof schemaDefault !== 'undefined') { + value = clone(schemaDefault); + type = this._getValueType(value); + assignDefault = !this._isValueTypeAny(value, type, schemaType); + } + + if (assignDefault) { + value = this._getDefaultTypeValue(schemaType); + type = this._getValueType(value); + } + } + + switch (type) { + case 'object': + value = this._populateObjectDefaults(value, schema, info); + break; + case 'array': + value = this._populateArrayDefaults(value, schema, info); + break; + } + + return value; + } + + _populateObjectDefaults(value, schema, info) { const properties = new Set(Object.getOwnPropertyNames(value)); const required = schema.required; @@ -630,7 +635,11 @@ class JsonSchemaValidator { const propertySchema = this._getPropertySchema(schema, property, value, null); if (propertySchema === null) { continue; } - value[property] = this.getValidValueOrDefault(propertySchema, value[property]); + info.valuePush(property, value); + info.schemaPush(property, propertySchema); + value[property] = this._getValidValueOrDefault(propertySchema, value[property], info); + info.schemaPop(); + info.valuePop(); } } @@ -639,18 +648,26 @@ class JsonSchemaValidator { if (propertySchema === null) { Reflect.deleteProperty(value, property); } else { - value[property] = this.getValidValueOrDefault(propertySchema, value[property]); + info.valuePush(property, value); + info.schemaPush(property, propertySchema); + value[property] = this._getValidValueOrDefault(propertySchema, value[property], info); + info.schemaPop(); + info.valuePop(); } } return value; } - _populateArrayDefaults(value, schema) { + _populateArrayDefaults(value, schema, info) { for (let i = 0, ii = value.length; i < ii; ++i) { const propertySchema = this._getPropertySchema(schema, i, value, null); if (propertySchema === null) { continue; } - value[i] = this.getValidValueOrDefault(propertySchema, value[i]); + info.valuePush(i, value); + info.schemaPush(i, propertySchema); + value[i] = this._getValidValueOrDefault(propertySchema, value[i], info); + info.schemaPop(); + info.valuePop(); } const minItems = schema.minItems; @@ -658,7 +675,11 @@ class JsonSchemaValidator { for (let i = value.length; i < minItems; ++i) { const propertySchema = this._getPropertySchema(schema, i, value, null); if (propertySchema === null) { break; } - const item = this.getValidValueOrDefault(propertySchema); + info.valuePush(i, value); + info.schemaPush(i, propertySchema); + const item = this._getValidValueOrDefault(propertySchema, void 0, info); + info.schemaPop(); + info.valuePop(); value.push(item); } }