1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * A facade around @cfworker/json-schema that provides additional formats and
7 * convenience methods whil executing inside a sandbox.
10 const sandbox = new Cu.Sandbox(null, {
11 wantComponents: false,
12 wantGlobalProperties: ["URL"],
15 Services.scriptloader.loadSubScript(
16 "chrome://global/content/third_party/cfworker/json-schema.js",
21 * A JSON Schema string format for URLs intended to go through Services.urlFormatter.
24 function validateMozUrlFormat(input) {
26 const formatted = Services.urlFormatter.formatURL(input);
27 return Cu.waiveXrays(sandbox.fastFormat).uri(formatted);
33 { defineAs: "moz-url-format" }
36 // initialBaseURI defaults to github.com/cfworker, which will be confusing.
38 `this.initialBaseURI = initialBaseURI = new URL("http://mozilla.org");`,
43 * A JSONSchema validator that performs validation inside a sandbox.
50 * Create a new validator.
52 * @param {object} schema The schema to validate with.
53 * @param {object} options Options for the validator.
54 * @param {string} options.draft The draft to validate against. Should be one
55 * of "4", "6", "7", "2019-09", or "2020-12".
57 * If the |$schema| key is present in the
58 * |schema|, it will be used to auto-detect the
59 * correct version. Otherwise, 2019-09 will be
61 * @param {boolean} options.shortCircuit Whether or not the validator should
62 * return after a single error occurs.
66 { draft = detectSchemaDraft(schema), shortCircuit = true } = {}
69 this.#inner = Cu.waiveXrays(
70 new sandbox.Validator(Cu.cloneInto(schema, sandbox), draft, shortCircuit)
75 * Validate the instance against the known schemas.
77 * @param {object} instance The instance to validate.
79 * @return {object} An object with |valid| and |errors| keys that indicates
80 * the success of validation.
83 return this.#inner.validate(Cu.cloneInto(instance, sandbox));
87 * Add a schema to the validator.
89 * @param {object} schema A JSON schema object.
90 * @param {string} id An optional ID to identify the schema if it does not
91 * provide an |$id| field.
93 addSchema(schema, id) {
94 const draft = detectSchemaDraft(schema, undefined);
95 if (draft && this.#draft != draft) {
97 `Adding a draft "${draft}" schema to a draft "${
102 this.#inner.addSchema(Cu.cloneInto(schema, sandbox), id);
107 * A wrapper around validate that provides some options as an object
108 * instead of positional arguments.
110 * @param {object} instance The instance to validate.
111 * @param {object} schema The JSON schema to validate against.
112 * @param {object} options Options for the validator.
113 * @param {string} options.draft The draft to validate against. Should
114 * be one of "4", "6", "7", "2019-09", or "2020-12".
116 * If the |$schema| key is present in the |schema|, it
117 * will be used to auto-detect the correct version.
118 * Otherwise, 2019-09 will be used.
119 * @param {boolean} options.shortCircuit Whether or not the validator should
120 * return after a single error occurs.
122 * @returns {object} An object with |valid| and |errors| keys that indicates the
123 * success of validation.
128 { draft = detectSchemaDraft(schema), shortCircuit = true } = {}
130 const clonedSchema = Cu.cloneInto(schema, sandbox);
132 return sandbox.validate(
133 Cu.cloneInto(instance, sandbox),
136 sandbox.dereference(clonedSchema),
141 function detectSchemaDraft(schema, defaultDraft = "2019-09") {
142 const { $schema } = schema;
144 if (typeof $schema === "undefined") {
149 case "http://json-schema.org/draft-04/schema#":
152 case "http://json-schema.org/draft-06/schema#":
155 case "http://json-schema.org/draft-07/schema#":
158 case "https://json-schema.org/draft/2019-09/schema":
161 case "https://json-schema.org/draft/2020-12/schema":
166 `Unexpected $schema "${$schema}", defaulting to ${defaultDraft}.`
172 export const JsonSchema = {