tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d9b7fbd90f416e903952c672dadc103333f02d3a
parent 0aa4fc38d85850757efb61a0c6c9a2e0b2c36dce
Author: Mark Banner <standard8@mozilla.com>
Date:   Thu, 18 Dec 2025 10:36:42 +0000

Bug 2006388 - Improve JSDoc for JsonSchemaValidator.sys.mjs. r=firefox-desktop-core-reviewers ,mconley

Differential Revision: https://phabricator.services.mozilla.com/D276703

Diffstat:
Mtoolkit/components/utils/JsonSchemaValidator.sys.mjs | 175++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mtoolkit/components/utils/test/unit/test_JsonSchemaValidator.js | 9+++++----
2 files changed, 103 insertions(+), 81 deletions(-)

diff --git a/toolkit/components/utils/JsonSchemaValidator.sys.mjs b/toolkit/components/utils/JsonSchemaValidator.sys.mjs @@ -28,6 +28,22 @@ ChromeUtils.defineLazyGetter(lazy, "log", () => { }); /** + * @typedef {object} JsonSchemaValidatorResult + * @property {boolean} valid + * True if validation is successful, false if not. + * @property {any} parsedValue + * If validation is successful, this is the validated value. It can + * differ from the passed-in value in the following ways: + * + * - If a type in the schema is "URL" or "URLorEmpty", the passed-in value can + * use a string instead and it will be converted into a `URL` object in + * parsedValue. + * - Some of the `allow*` parameters control the properties that appear. + * {@link JsonSchemaValidator.validate()}. + * @property {JsonSchemaValidatorError} error + */ + +/** * To validate a single value, use the static `JsonSchemaValidator.validate` * method. If you need to validate multiple values, you instead might want to * make a JsonSchemaValidator instance with the options you need and then call @@ -37,30 +53,31 @@ export class JsonSchemaValidator { /** * Validates a value against a schema. * - * @param {*} value + * @param {any} value * The value to validate. * @param {object} schema * The schema to validate against. - * @param {boolean} allowArrayNonMatchingItems + * @param {object} [options] + * @param {boolean} [options.allowArrayNonMatchingItems] * When true: * Invalid items in arrays will be ignored, and they won't be included in * result.parsedValue. * When false: * Invalid items in arrays will cause validation to fail. - * @param {boolean} allowExplicitUndefinedProperties + * @param {boolean} [options.allowExplicitUndefinedProperties] * When true: * `someProperty: undefined` will be allowed for non-required properties. * When false: * `someProperty: undefined` will cause validation to fail even for * properties that are not required. - * @param {boolean} allowNullAsUndefinedProperties + * @param {boolean} [options.allowNullAsUndefinedProperties] * When true: * `someProperty: null` will be allowed for non-required properties whose * expected types are non-null. * When false: * `someProperty: null` will cause validation to fail for non-required * properties, except for properties whose expected types are null. - * @param {boolean} allowAdditionalProperties + * @param {boolean} [options.allowAdditionalProperties] * When true: * Properties that are not defined in the schema will be ignored, and they * won't be included in result.parsedValue. @@ -75,54 +92,7 @@ export class JsonSchemaValidator { * `result.parsedValue`. (The inverse is not true: If a schema object * defines `additionalProperties: false` but `allowAdditionalProperties` * is true, extra properties will be allowed.) - * @return {object} - * The result of the validation, an object that looks like this: - * - * { - * valid, - * parsedValue, - * error: { - * message, - * rootValue, - * rootSchema, - * invalidValue, - * invalidPropertyNameComponents, - * } - * } - * - * {boolean} valid - * True if validation is successful, false if not. - * {*} parsedValue - * If validation is successful, this is the validated value. It can - * differ from the passed-in value in the following ways: - * * If a type in the schema is "URL" or "URLorEmpty", the passed-in - * value can use a string instead and it will be converted into a - * `URL` object in parsedValue. - * * Some of the `allow*` parameters control the properties that appear. - * See above. - * {Error} error - * If validation fails, `error` will be present. It contains a number of - * properties useful for understanding the validation failure. - * {string} error.message - * The validation failure message. - * {*} error.rootValue - * The passed-in value. - * {object} error.rootSchema - * The passed-in schema. - * {*} invalidValue - * The value that caused validation to fail. If the passed-in value is a - * scalar type, this will be the value itself. If the value is an object - * or array, it will be the specific nested value in the object or array - * that caused validation to fail. - * {array} invalidPropertyNameComponents - * If the passed-in value is an object or array, this will contain the - * names of the object properties or array indexes where invalidValue can - * be found. For example, assume the passed-in value is: - * { foo: { bar: { baz: 123 }}} - * And assume `baz` should be a string instead of a number. Then - * invalidValue will be 123, and invalidPropertyNameComponents will be - * ["foo", "bar", "baz"], indicating that the erroneous property in the - * passed-in object is `foo.bar.baz`. + * @returns {JsonSchemaValidatorResult} */ static validate( value, @@ -146,13 +116,14 @@ export class JsonSchemaValidator { /** * Constructor. * - * @param {boolean} allowArrayNonMatchingItems + * @param {object} [options] + * @param {boolean} [options.allowArrayNonMatchingItems] * See the static `validate` method above. - * @param {boolean} allowExplicitUndefinedProperties + * @param {boolean} [options.allowExplicitUndefinedProperties] * See the static `validate` method above. - * @param {boolean} allowNullAsUndefinedProperties + * @param {boolean} [options.allowNullAsUndefinedProperties] * See the static `validate` method above. - * @param {boolean} allowAdditionalProperties + * @param {boolean} [options.allowAdditionalProperties] * See the static `validate` method above. */ constructor({ @@ -214,7 +185,7 @@ export class JsonSchemaValidator { message: `The value '${valueToString(param)}' does not match any type in ` + valueToString(properties.type), - value: param, + invalidValue: param, keyPath, state, }), @@ -247,7 +218,7 @@ export class JsonSchemaValidator { message: `The value '${valueToString(param)}' is not one of the ` + `enumerated values ${valueToString(properties.enum)}`, - value: param, + invalidValue: param, keyPath, state, }), @@ -265,7 +236,7 @@ export class JsonSchemaValidator { message: `The value '${valueToString(param)}' does not match the ` + `expected type 'array'`, - value: param, + invalidValue: param, keyPath, state, }), @@ -308,7 +279,7 @@ export class JsonSchemaValidator { message: `The value '${valueToString(param)}' does not match the ` + `expected type 'object'`, - value: param, + invalidValue: param, keyPath, state, }), @@ -342,7 +313,7 @@ export class JsonSchemaValidator { valid: false, error: new JsonSchemaValidatorError({ message: `Object is missing required property '${required}'`, - value: param, + invalidValue: param, keyPath, state, }), @@ -377,7 +348,7 @@ export class JsonSchemaValidator { valid: false, error: new JsonSchemaValidatorError({ message: `Object has unexpected property '${item}'`, - value: param, + invalidValue: param, keyPath, state, }), @@ -419,7 +390,7 @@ export class JsonSchemaValidator { valid: false, error: new JsonSchemaValidatorError({ message: `JSON was not an object: ${valueToString(param)}`, - value: param, + invalidValue: param, keyPath, state, }), @@ -434,7 +405,7 @@ export class JsonSchemaValidator { message: `JSON string could not be parsed: ${valueToString( param )}`, - value: param, + invalidValue: param, keyPath, state, }), @@ -448,7 +419,7 @@ export class JsonSchemaValidator { message: `Invalid schema property type: ${valueToString( properties.type )}`, - value: param, + invalidValue: param, keyPath, state, }), @@ -546,7 +517,7 @@ export class JsonSchemaValidator { message: `The value '${valueToString(param)}' does not match the expected ` + `type '${type}'`, - value: param, + invalidValue: param, keyPath, state, }); @@ -563,26 +534,76 @@ export class JsonSchemaValidator { } } +function valueToString(value) { + try { + return JSON.stringify(value); + } catch (ex) {} + return String(value); +} + +/** + * Class to describe an error in the JSON Schema Validator. + */ class JsonSchemaValidatorError extends Error { - constructor({ message, value, keyPath, state } = {}, ...args) { + /** + * @type {any} + * The value being validated. + */ + rootValue; + + /** + * @type {any} + * The schema being checked against. + */ + rootSchema; + + /** + * @type {any} + * The value that caused validation to fail. If the passed-in value is a + * scalar type, this will be the value itself. If the value is an object + * or array, it will be the specific nested value in the object or array + * that caused validation to fail. + */ + invalidValue; + + /** + * @type {(string|number)[]} + * If the passed-in value is an object or array, this will contain the + * names of the object properties or array indexes where invalidValue can + * be found. For example, assume the passed-in value is: + * { foo: { bar: { baz: 123 }}} + * And assume `baz` should be a string instead of a number. Then + * invalidValue will be 123, and invalidPropertyNameComponents will be + * ["foo", "bar", "baz"], indicating that the erroneous property in the + * passed-in object is `foo.bar.baz`. + */ + invalidPropertyNameComponents; + + /** + * @param {object} details + * @param {string} details.message + * The validation failure message. + * @param {any} details.invalidValue + * The value that caused validation to fail. If the passed-in value is a + * scalar type, this will be the value itself. If the value is an object + * or array, it will be the specific nested value in the object or array + * that caused validation to fail. + * @param {(string|number)[]} details.keyPath + * @param {object} details.state + * The root value and schema of the validation. + */ + constructor({ message, invalidValue, keyPath, state }) { if (keyPath.length) { message += ". " + `The invalid value is property '${keyPath.join(".")}' in ` + JSON.stringify(state.rootValue); } - super(message, ...args); + super(message); this.name = "JsonSchemaValidatorError"; this.rootValue = state.rootValue; this.rootSchema = state.rootSchema; this.invalidPropertyNameComponents = keyPath; - this.invalidValue = value; + this.invalidValue = invalidValue; } } - -function valueToString(value) { - try { - return JSON.stringify(value); - } catch (ex) {} - return String(value); -} diff --git a/toolkit/components/utils/test/unit/test_JsonSchemaValidator.js b/toolkit/components/utils/test/unit/test_JsonSchemaValidator.js @@ -1914,17 +1914,18 @@ add_task(async function test_boolint_enum() { * Validates a value against a schema and asserts that the result is as * expected. * - * @param {*} value + * @param {object} params + * @param {*} params.value * The value to validate. - * @param {object} schema + * @param {object} params.schema * The schema to validate against. - * @param {object} expectedResult + * @param {object} params.expectedResult * The expected result. See JsonSchemaValidator.validate for what this object * should look like. If the expected result is invalid, then this object * should have an `error` property with all the properties of validation * errors, including `message`, except that `rootValue` and `rootSchema` are * unnecessary because this function will add them for you. - * @param {object} options + * @param {object} [params.options] * Options to pass to JsonSchemaValidator.validate. * @return {object} The return value of JsonSchemaValidator.validate, which is * a result.