Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ajv-validator/ajv
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v8.5.0
Choose a base ref
...
head repository: ajv-validator/ajv
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v8.6.0
Choose a head ref
  • 16 commits
  • 13 files changed
  • 6 contributors

Commits on May 23, 2021

  1. docs: draft-04 support

    epoberezkin committed May 23, 2021
    Copy the full SHA
    0786271 View commit details

Commits on May 25, 2021

  1. Unverified

    The email in this signature doesn’t match the committer email.
    Copy the full SHA
    73bf4b4 View commit details

Commits on May 26, 2021

  1. error in the text

    vendeza authored May 26, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9b0ef91 View commit details

Commits on May 29, 2021

  1. Remove incorrect example for prefixItems (#1631)

    `prefixItems` first example was an incorrect copy-paste of previous `items` examples.
    wyfo authored May 29, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5378ab9 View commit details

Commits on Jun 6, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    279b191 View commit details
  2. Copy the full SHA
    f5bbd23 View commit details
  3. option int32range to disable range checking for int32 and uint32 types (

    #1639)
    
    * option int32range to disable range checking for int32 and uint32 types
    
    * fix prettier
    
    * enable all tests
    epoberezkin authored Jun 6, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e73bc75 View commit details
  4. Copy the full SHA
    b706405 View commit details
  5. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    cbe945a View commit details
  6. build(deps-dev): bump ts-node from 9.1.1 to 10.0.0 (#1621)

    Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 9.1.1 to 10.0.0.
    - [Release notes](https://github.com/TypeStrong/ts-node/releases)
    - [Commits](TypeStrong/ts-node@v9.1.1...v10.0.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    
    Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
    Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
    dependabot-preview[bot] and epoberezkin authored Jun 6, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9e49401 View commit details
  7. build(deps-dev): bump lint-staged from 10.5.4 to 11.0.0 (#1601)

    Bumps [lint-staged](https://github.com/okonet/lint-staged) from 10.5.4 to 11.0.0.
    - [Release notes](https://github.com/okonet/lint-staged/releases)
    - [Commits](lint-staged/lint-staged@v10.5.4...v11.0.0)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    
    Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
    dependabot-preview[bot] authored Jun 6, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0a0eb0e View commit details
  8. build(deps-dev): bump @rollup/plugin-commonjs from 18.1.0 to 19.0.0 (#…

    …1602)
    
    Bumps [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/HEAD/packages/commonjs) from 18.1.0 to 19.0.0.
    - [Release notes](https://github.com/rollup/plugins/releases)
    - [Changelog](https://github.com/rollup/plugins/blob/master/packages/commonjs/CHANGELOG.md)
    - [Commits](https://github.com/rollup/plugins/commits/commonjs-v19.0.0/packages/commonjs)
    
    Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
    
    Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
    dependabot-preview[bot] authored Jun 6, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    85ae956 View commit details
  9. Merge branch 'fix/track-pattern-properties-evaluation' of https://git…

    …hub.com/stoplightio/ajv into stoplightio-fix/track-pattern-properties-evaluation
    epoberezkin committed Jun 6, 2021
    Copy the full SHA
    3e285b0 View commit details
  10. Copy the full SHA
    795a8f8 View commit details
  11. Copy the full SHA
    2f950e6 View commit details
  12. 8.6.0

    epoberezkin committed Jun 6, 2021
    Copy the full SHA
    f870838 View commit details
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

The fastest JSON validator for Node.js and browser.

Supports JSON Schema draft-06/07/2019-09/2020-12 (draft-04 is supported in [version 6](https://github.com/ajv-validator/ajv/tree/v6)) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).
Supports JSON Schema draft-04/06/07/2019-09/2020-12 ([draft-04 support](https://ajv.js.org/json-schema.html#draft-04) requires ajv-draft-04 package) and JSON Type Definition [RFC8927](https://datatracker.ietf.org/doc/rfc8927/).

[![build](https://github.com/ajv-validator/ajv/workflows/build/badge.svg)](https://github.com/ajv-validator/ajv/actions?query=workflow%3Abuild)
[![npm](https://img.shields.io/npm/v/ajv.svg)](https://www.npmjs.com/package/ajv)
2 changes: 1 addition & 1 deletion docs/guide/getting-started.md
Original file line number Diff line number Diff line change
@@ -107,7 +107,7 @@ Ajv can compile efficient parsers and serializers from [JSON Type Definition](..

Serializing the data with a function specialized to your data shape can be more than 10x compared with `JSON.stringify`.

Parsing the data replaces the need for a separate validation after generic parsing with `JSON.parse` (although validation itself is usually much faster than parsing). In case your JSON string is valid specialized parsing is as approximately fast as JSON.parse, but in case your JSON is invalid, specialized parsing would fail much faster - so it can be very efficient in some scenarios.
Parsing the data replaces the need for a separate validation after generic parsing with `JSON.parse` (although validation itself is usually much faster than parsing). In case your JSON string is valid specialized parsing is approximately as fast as JSON.parse, but in case your JSON is invalid, specialized parsing would fail much faster - so it can be very efficient in some scenarios.

For the same data structure, you can compile parser and serializer in this way:

2 changes: 1 addition & 1 deletion docs/guide/managing-schemas.md
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ You can load all schemas and add them to Ajv instance in a single `validation` m
<code-group>
<code-block title="validation.js">
```javascript
const Ajv = require("ajv").defalt
const Ajv = require("ajv")
const schema_user = require("./schema_user.json")
const schema_document = require("./schema_document.json")
const ajv = exports.ajv = new Ajv()
39 changes: 11 additions & 28 deletions docs/json-schema.md
Original file line number Diff line number Diff line change
@@ -135,40 +135,29 @@ ajv.addMetaSchema(draft6MetaSchema)
</code-block>
</code-group>

### draft-04 <Badge text="v6" />
### draft-04

You can use JSON Schema draft-06 schemas with Ajv v6.

::: warning Only compatible with Ajv v6
The code example below will not work in the most recent version of Ajv, it requires Ajv v6. While no longer actively developed it continues to receive critical security updates.
:::
You can use JSON Schema draft-04 schemas with Ajv from v8.5.0 and the additional package [ajv-draft-04](https://github.com/ajv-validator/ajv-draft-04) (both ajv and ajv-draft-04 should be installed).

<code-group>
<code-block title="JavaScript">
```javascript
const Ajv = require("ajv")
const draft4MetaSchema = require("ajv/lib/refs/json-schema-draft-04.json")

const ajv = new Ajv({schemaId: "id"}) // or "auto" if you use both draft-04 and draft-06/07 schemas
ajv.addMetaSchema(draft4MetaSchema)
const Ajv = require("ajv-draft-04")
const ajv = new Ajv()
```
</code-block>

<code-block title="TypeScript">
```typescript
import Ajv from "ajv"
import * as draft4MetaSchema from "ajv/lib/refs/json-schema-draft-04.json"

const ajv = new Ajv({schemaId: "id"}) // or "auto" if you use both draft-04 and draft-06/07 schemas
ajv.addMetaSchema(draft4MetaSchema)
import Ajv from "ajv-draft-04"
const ajv = new Ajv()
```
</code-block>
</code-group>

var ajv = new Ajv({schemaId: 'id'});
// If you want to use both draft-04 and draft-06/07 schemas:
// var ajv = new Ajv({schemaId: 'auto'});
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'));
::: warning Ajv cannot combine multiple JSON Schema versions
You can only use this import with JSON Schema draft-04, you cannot combine multiple JSON Schema versions in this ajv instance.
:::

## OpenAPI support

@@ -462,13 +451,7 @@ For the data array to be valid, the items with indices less than the number of s

**Examples**

1. _schema_: `{type: "array", prefixItems: {type: "integer"}}`

_valid_: `[1,2,3]`, `[]`

_invalid_: `[1,"abc"]`

2. _schema_:
_schema_:

```javascript
{
@@ -481,7 +464,7 @@ For the data array to be valid, the items with indices less than the number of s

_invalid_: `["abc", 1]`, `["abc"]`

The schema in example 2 will log warning by default (see `strictTuples` option), because it defines unconstrained tuple. To define a tuple with exactly 2 elements use [minItems](#minitems) and [items](#items-in-draft-2020-12) keywords (see example 2 in [items](#items-in-draft-2020-12)).
The schema in example will log warning by default (see `strictTuples` option), because it defines unconstrained tuple. To define a tuple with exactly 2 elements use [minItems](#minitems) and [items](#items-in-draft-2020-12) keywords (see example 2 in [items](#items-in-draft-2020-12)).

### `additionalItems`

13 changes: 13 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ const defaultOptions = {
timestamp: undefined // **
parseDate: false // **
allowDate: false // **
int32range: true // **
$comment: false, // *
formats: {},
keywords: {},
@@ -200,6 +201,18 @@ Defines how date-time strings are parsed and validated. By default Ajv only allo
This option makes JTD validation and parsing more permissive and non-standard. The date strings without time part will be accepted by Ajv, but will be rejected by other JTD validators.
:::

### int32range <Badge text="JTD only">

Can be used to disable range checking for `int32` and `uint32` types.

By default Ajv limits the range of these types to `[-2**31, 2**31 - 1]` for `int32` and to `[0, 2**32-1]` for `uint32` when validating and parsing.

With option `int32range: false` Ajv only requires that `uint32` is non-negative, otherwise does not check the range. Parser will limit the number size to 16 digits (approx. `2**53` - safe integer range).

::: warning Option int32range is not portable
This option makes JTD validation and parsing more permissive and non-standard. The integers within a wider range will be accepted by Ajv, but will be rejected by other JTD validators.
:::

### $comment

Log or pass the value of `$comment` keyword to a function.
18 changes: 13 additions & 5 deletions lib/compile/jtd/parse.ts
Original file line number Diff line number Diff line change
@@ -277,11 +277,19 @@ function parseType(cxt: ParseCxt): void {
parseNumber(cxt)
break
default: {
const [min, max, maxDigits] = intRange[schema.type as IntType]
parseNumber(cxt, maxDigits)
gen.if(_`${data} < ${min} || ${data} > ${max}`, () =>
parsingError(cxt, str`integer out of range`)
)
const t = schema.type as IntType
if (!self.opts.int32range && (t === "int32" || t === "uint32")) {
parseNumber(cxt, 16) // 2 ** 53 - max safe integer
if (t === "uint32") {
gen.if(_`${data} < 0`, () => parsingError(cxt, str`integer out of range`))
}
} else {
const [min, max, maxDigits] = intRange[t]
parseNumber(cxt, maxDigits)
gen.if(_`${data} < ${min} || ${data} > ${max}`, () =>
parsingError(cxt, str`integer out of range`)
)
}
}
}
}
3 changes: 3 additions & 0 deletions lib/core.ts
Original file line number Diff line number Diff line change
@@ -129,6 +129,7 @@ export interface CurrentOptions {
loopEnum?: number // NEW
ownProperties?: boolean
multipleOfPrecision?: number
int32range?: boolean // JTD only
messages?: boolean
code?: CodeOptions // NEW
}
@@ -217,6 +218,7 @@ type RequiredInstanceOptions = {
| "addUsedSchema"
| "validateSchema"
| "validateFormats"
| "int32range"
| "unicodeRegExp"]: NonNullable<Options[K]>
} & {code: InstanceCodeOptions}

@@ -246,6 +248,7 @@ function requiredOptions(o: Options): RequiredInstanceOptions {
validateSchema: o.validateSchema ?? true,
validateFormats: o.validateFormats ?? true,
unicodeRegExp: o.unicodeRegExp ?? true,
int32range: o.int32range ?? true,
}
}

45 changes: 30 additions & 15 deletions lib/vocabularies/applicator/patternProperties.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type {CodeKeywordDefinition} from "../../types"
import type {KeywordCxt} from "../../compile/validate"
import {schemaProperties, usePattern} from "../code"
import {allSchemaProperties, usePattern} from "../code"
import {_, not, Name} from "../../compile/codegen"
import {checkStrictMode} from "../../compile/util"
import {alwaysValidSchema, checkStrictMode} from "../../compile/util"
import {evaluatedPropsToName, Type} from "../../compile/util"
import {AnySchema} from "../../types"

const def: CodeKeywordDefinition = {
keyword: "patternProperties",
@@ -12,9 +13,19 @@ const def: CodeKeywordDefinition = {
code(cxt: KeywordCxt) {
const {gen, schema, data, parentSchema, it} = cxt
const {opts} = it
const patterns = schemaProperties(it, schema)
// TODO mark properties matching patterns with always valid schemas as evaluated
if (patterns.length === 0) return
const patterns = allSchemaProperties(schema)
const alwaysValidPatterns = patterns.filter((p) =>
alwaysValidSchema(it, schema[p] as AnySchema)
)

if (
patterns.length === 0 ||
(alwaysValidPatterns.length === patterns.length &&
(!it.opts.unevaluated || it.props === true))
) {
return
}

const checkProperties =
opts.strictSchema && !opts.allowMatchingProperties && parentSchema.properties
const valid = gen.name("valid")
@@ -51,18 +62,22 @@ const def: CodeKeywordDefinition = {
function validateProperties(pat: string): void {
gen.forIn("key", data, (key) => {
gen.if(_`${usePattern(cxt, pat)}.test(${key})`, () => {
cxt.subschema(
{
keyword: "patternProperties",
schemaProp: pat,
dataProp: key,
dataPropType: Type.Str,
},
valid
)
const alwaysValid = alwaysValidPatterns.includes(pat)
if (!alwaysValid) {
cxt.subschema(
{
keyword: "patternProperties",
schemaProp: pat,
dataProp: key,
dataPropType: Type.Str,
},
valid
)
}

if (it.opts.unevaluated && props !== true) {
gen.assign(_`${props}[${key}]`, true)
} else if (!it.allErrors) {
} else if (!alwaysValid && !it.allErrors) {
// can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
// or if all properties were evaluated (props === true)
gen.if(not(valid), () => gen.break())
12 changes: 9 additions & 3 deletions lib/vocabularies/jtd/type.ts
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ const def: CodeKeywordDefinition = {
error,
code(cxt: KeywordCxt) {
checkMetadata(cxt)
const {data, schema, parentSchema} = cxt
const {data, schema, parentSchema, it} = cxt
let cond: Code
switch (schema) {
case "boolean":
@@ -58,8 +58,14 @@ const def: CodeKeywordDefinition = {
cond = _`typeof ${data} == "number"`
break
default: {
const [min, max] = intRange[schema as IntType]
cond = _`typeof ${data} == "number" && isFinite(${data}) && ${data} >= ${min} && ${data} <= ${max} && !(${data} % 1)`
const sch = schema as IntType
cond = _`typeof ${data} == "number" && isFinite(${data}) && !(${data} % 1)`
if (!it.opts.int32range && (sch === "int32" || sch === "uint32")) {
if (sch === "uint32") cond = _`${cond} && ${data} >= 0`
} else {
const [min, max] = intRange[sch]
cond = _`${cond} && ${data} >= ${min} && ${data} <= ${max}`
}
}
}
cxt.pass(parentSchema.nullable ? or(_`${data} === null`, cond) : cond)
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ajv",
"version": "8.5.0",
"version": "8.6.0",
"description": "Another JSON Schema Validator",
"main": "dist/ajv.js",
"types": "dist/ajv.d.ts",
@@ -64,7 +64,7 @@
},
"devDependencies": {
"@ajv-validator/config": "^0.3.0",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-typescript": "^8.2.1",
@@ -91,14 +91,14 @@
"karma": "^6.0.0",
"karma-chrome-launcher": "^3.0.0",
"karma-mocha": "^2.0.0",
"lint-staged": "^10.2.11",
"lint-staged": "^11.0.0",
"mocha": "^8.0.1",
"node-fetch": "^2.6.1",
"nyc": "^15.0.0",
"prettier": "^2.0.5",
"prettier": "^2.3.1",
"rollup": "^2.44.0",
"rollup-plugin-terser": "^7.0.2",
"ts-node": "^9.0.0",
"ts-node": "^10.0.0",
"tsify": "^5.0.2",
"typescript": "^4.2.0",
"vuepress": "^1.8.2"
20 changes: 20 additions & 0 deletions spec/issues/1625_evaluated_truthy_pattern_properties.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import _Ajv from "../ajv2020"
import * as assert from "assert"

describe("tracking evaluated properties with pattern properties of schema = true", () => {
it("should initialize evaluated properties", () => {
const ajv = new _Ajv()

const schema = {
type: "object",
patternProperties: {
"^x-": true,
},
unevaluatedProperties: false,
}

const validate = ajv.compile(schema)
assert.strictEqual(validate({bar: 1}), false)
assert.strictEqual(validate({"x-bar": false}), true)
})
})
Loading