From a211e8dcf26a2c1f6722d1d44419287256a9a726 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Mon, 2 Jan 2023 22:39:22 +0000 Subject: [PATCH] JTD empty values schema, fixes #1949 (#2191) --- lib/vocabularies/jtd/values.ts | 17 ++++++----- spec/issues/1949_jtd_empty_values.spec.ts | 28 +++++++++++++++++++ .../2001_jtd_only_optional_properties.spec.ts | 2 +- 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 spec/issues/1949_jtd_empty_values.spec.ts diff --git a/lib/vocabularies/jtd/values.ts b/lib/vocabularies/jtd/values.ts index 86091b8ce..e64945077 100644 --- a/lib/vocabularies/jtd/values.ts +++ b/lib/vocabularies/jtd/values.ts @@ -1,7 +1,7 @@ import type {CodeKeywordDefinition, SchemaObject} from "../../types" import type {KeywordCxt} from "../../compile/validate" import {alwaysValidSchema, Type} from "../../compile/util" -import {not, Name} from "../../compile/codegen" +import {not, or, Name} from "../../compile/codegen" import {checkMetadata} from "./metadata" import {checkNullableObject} from "./nullable" import {typeError, _JTDTypeError} from "./error" @@ -15,13 +15,16 @@ const def: CodeKeywordDefinition = { code(cxt: KeywordCxt) { checkMetadata(cxt) const {gen, data, schema, it} = cxt - if (alwaysValidSchema(it, schema)) return const [valid, cond] = checkNullableObject(cxt, data) - gen.if(cond) - gen.assign(valid, validateMap()) - gen.elseIf(not(valid)) - cxt.error() - gen.endIf() + if (alwaysValidSchema(it, schema)) { + gen.if(not(or(cond, valid)), () => cxt.error()) + } else { + gen.if(cond) + gen.assign(valid, validateMap()) + gen.elseIf(not(valid)) + cxt.error() + gen.endIf() + } cxt.ok(valid) function validateMap(): Name | boolean { diff --git a/spec/issues/1949_jtd_empty_values.spec.ts b/spec/issues/1949_jtd_empty_values.spec.ts new file mode 100644 index 000000000..d1ccd7f8f --- /dev/null +++ b/spec/issues/1949_jtd_empty_values.spec.ts @@ -0,0 +1,28 @@ +import _Ajv from "../ajv_jtd" +import * as assert from "assert" + +describe("JTD values with empty schema (issue #1949)", () => { + const ajv = new _Ajv() + + it("should correctly validate empty values form", () => { + const schema = {values: {}} + const validate = ajv.compile(schema) + assert.strictEqual(validate({prop1: 1, prop2: 2}), true) + assert.strictEqual(validate({}), true) + assert.strictEqual(validate(null), false) + assert.strictEqual(validate(1), false) + assert.strictEqual(validate("foo"), false) + assert.strictEqual(validate(undefined), false) + }) + + it("should correctly validate nullable empty values form", () => { + const schema = {values: {}, nullable: true} + const validate = ajv.compile(schema) + assert.strictEqual(validate({prop1: 1, prop2: 2}), true) + assert.strictEqual(validate({}), true) + assert.strictEqual(validate(null), true) + assert.strictEqual(validate(1), false) + assert.strictEqual(validate("foo"), false) + assert.strictEqual(validate(undefined), false) + }) +}) diff --git a/spec/issues/2001_jtd_only_optional_properties.spec.ts b/spec/issues/2001_jtd_only_optional_properties.spec.ts index 55efcc562..cc7dcfce1 100644 --- a/spec/issues/2001_jtd_only_optional_properties.spec.ts +++ b/spec/issues/2001_jtd_only_optional_properties.spec.ts @@ -1,7 +1,7 @@ import _Ajv from "../ajv_jtd" import * as assert from "assert" -describe("schema with optional/additional properties only", () => { +describe("JTD schema with optional/additional properties only (issue #2001)", () => { const ajv = new _Ajv() it("should correctly serialize optional properties", () => {