diff --git a/README.md b/README.md index 5526d4c637..38487b4583 100644 --- a/README.md +++ b/README.md @@ -1189,7 +1189,6 @@ Defaults: - `false` (default) - do not use defaults - `true` - insert defaults by value (object literal is used). - `"empty"` - in addition to missing or undefined, use defaults for properties and items that are equal to `null` or `""` (an empty string). - - `"shared"` (deprecated) - insert defaults by reference. If the default is an object, it will be shared by all instances of validated data. If you modify the inserted default in the validated data, it will be modified in the schema as well. - _coerceTypes_: change data type of data to match `type` keyword. See the example in [Coercing data types](#coercing-data-types) and [coercion rules](https://github.com/ajv-validator/ajv/blob/master/COERCION.md). Option values: - `false` (default) - no type coercion. - `true` - coerce scalar data types. diff --git a/lib/ajv.ts b/lib/ajv.ts index 60f65f76d5..aa860eef7c 100644 --- a/lib/ajv.ts +++ b/lib/ajv.ts @@ -68,7 +68,7 @@ export default function Ajv(opts: Options): void { this._compilations = [] this.RULES = rules() if (opts.schemaId !== undefined && opts.schemaId !== "$id") { - throw new Error("option schemaId is not supported from v7") + throw new Error("option schemaId is not supported in v7") } opts.loopRequired = opts.loopRequired || Infinity diff --git a/lib/compile/index.ts b/lib/compile/index.ts index 1d22447ed4..2504b61899 100644 --- a/lib/compile/index.ts +++ b/lib/compile/index.ts @@ -6,8 +6,7 @@ import N from "./names" const equal = require("fast-deep-equal") const ucs2length = require("./ucs2length") -var resolve = require("./resolve"), - stableStringify = require("fast-json-stable-stringify") +const resolve = require("./resolve") /** * Functions below are used inside compiled validations function @@ -51,7 +50,6 @@ function compile(schema, root, localRefs, baseId) { patterns: string[] = [], patternsHash = {}, defaults: any[] = [], - defaultsHash = {}, customRules: KeywordCompilationResult[] = [] root = root || {schema: schema, refVal: refVal, refs: refs} @@ -129,8 +127,7 @@ function compile(schema, root, localRefs, baseId) { RULES, // TODO refactor - it is available on the instance resolveRef, // TODO remove to imports usePattern, // TODO remove to imports - useDefault, // TODO remove to imports - customRules, // TODO add to types + customRules, opts, formats, logger: self.logger, @@ -264,26 +261,6 @@ function compile(schema, root, localRefs, baseId) { } return "pattern" + index } - - function useDefault(value: any): Expression { - switch (typeof value) { - case "boolean": - case "number": - case "string": - return _`${value}` - case "object": - if (value === null) return "null" - var valueStr = stableStringify(value) - var index = defaultsHash[valueStr] - if (index === undefined) { - index = defaultsHash[valueStr] = defaults.length - defaults[index] = value - } - return "default" + index - default: - throw new Error(`unsupported default type "${typeof value}"`) - } - } } /** diff --git a/lib/compile/validate/defaults.ts b/lib/compile/validate/defaults.ts index 2b1307350e..e5e630f4b6 100644 --- a/lib/compile/validate/defaults.ts +++ b/lib/compile/validate/defaults.ts @@ -13,7 +13,7 @@ export function assignDefaults(it: CompilationContext, ty?: string): void { } function assignDefault( - {gen, compositeRule, data, useDefault, opts, logger}: CompilationContext, + {gen, compositeRule, data, opts, logger}: CompilationContext, prop: string | number, defaultValue: any ): void { @@ -31,7 +31,5 @@ function assignDefault( const condition = `${childData} === undefined` + (opts.useDefaults === "empty" ? ` || ${childData} === null || ${childData} === ""` : "") - // TODO remove option `useDefaults === "shared"` - const defaultExpr = opts.useDefaults === "shared" ? useDefault : JSON.stringify - gen.if(condition, `${childData} = ${defaultExpr(defaultValue)}`) + gen.if(condition, `${childData} = ${JSON.stringify(defaultValue)}`) } diff --git a/lib/types.ts b/lib/types.ts index 3eec2d7242..d08e3beca0 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -23,7 +23,7 @@ export interface Options { cb?: (err: Error, schema: object) => void ) => PromiseLike removeAdditional?: boolean | "all" | "failing" - useDefaults?: boolean | "empty" | "shared" + useDefaults?: boolean | "empty" coerceTypes?: boolean | "array" strictDefaults?: boolean | "log" strictKeywords?: boolean | "log" @@ -130,7 +130,6 @@ export interface CompilationContext { // } compositeRule?: boolean usePattern: (str: string) => string - useDefault: (value: any) => Expression customRules: KeywordCompilationResult[] self: any // TODO RULES: ValidationRules diff --git a/spec/options/useDefaults.spec.js b/spec/options/useDefaults.spec.js index 3c56dd9c30..53d70bd0cc 100644 --- a/spec/options/useDefaults.spec.js +++ b/spec/options/useDefaults.spec.js @@ -118,22 +118,15 @@ describe("useDefaults option", () => { } }) - describe("useDefaults: by value / by reference", () => { - describe("using by value", () => { - it("should NOT modify underlying defaults when modifying validated data", () => { - test("value", new Ajv({useDefaults: true})) - test("value", new Ajv({useDefaults: true, allErrors: true})) - }) - }) - - describe("using by reference", () => { - it("should modify underlying defaults when modifying validated data", () => { - test("reference", new Ajv({useDefaults: "shared"})) - test("reference", new Ajv({useDefaults: "shared", allErrors: true})) - }) + describe("useDefaults: defaults are always passed by value", () => { + it("should NOT modify underlying defaults when modifying validated data", () => { + test(new Ajv({useDefaults: true})) + test(new Ajv({useDefaults: true, allErrors: true})) + test(new Ajv({useDefaults: "shared"})) + test(new Ajv({useDefaults: "shared", allErrors: true})) }) - function test(useDefaultsMode, ajv) { + function test(ajv) { var schema = { properties: { items: { @@ -155,13 +148,7 @@ describe("useDefaults option", () => { var data2 = {} validate(data2).should.equal(true) - if (useDefaultsMode === "reference") { - data2.items.should.eql(["a-default", "another-value"]) - } else if (useDefaultsMode === "value") { - data2.items.should.eql(["a-default"]) - } else { - throw new Error("unknown useDefaults mode") - } + data2.items.should.eql(["a-default"]) } })