Skip to content

Commit

Permalink
feat: add pattern and path to regexp create errors #2477
Browse files Browse the repository at this point in the history
  • Loading branch information
jasoniangreen committed Aug 4, 2024
1 parent 9050ba1 commit d33a36d
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 5 deletions.
13 changes: 10 additions & 3 deletions lib/vocabularies/code.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {AnySchema, SchemaMap} from "../types"
import type {AnySchema, RegExpLike, SchemaMap} from "../types"
import type {SchemaCxt} from "../compile"
import type {KeywordCxt} from "../compile/validate"
import {CodeGen, _, and, or, not, nil, strConcat, getProperty, Code, Name} from "../compile/codegen"
Expand Down Expand Up @@ -92,10 +92,17 @@ export function callValidateCode(

const newRegExp = _`new RegExp`

export function usePattern({gen, it: {opts}}: KeywordCxt, pattern: string): Name {
export function usePattern({gen, it: {opts, errSchemaPath}}: KeywordCxt, pattern: string): Name {
const u = opts.unicodeRegExp ? "u" : ""
const {regExp} = opts.code
const rx = regExp(pattern, u)

let rx: RegExpLike
try {
rx = new RegExp(pattern, u)
} catch (e) {
throw new Error(`Invalid regular expression: ${pattern} at ${errSchemaPath}`)
}
rx = regExp(pattern, u)

return gen.scopeValue("pattern", {
key: rx.toString(),
Expand Down
11 changes: 9 additions & 2 deletions lib/vocabularies/validation/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ const def: CodeKeywordDefinition = {
error,
code(cxt: KeywordCxt) {
const {data, $data, schema, schemaCode, it} = cxt
// TODO regexp should be wrapped in try/catchs
const u = it.opts.unicodeRegExp ? "u" : ""
const regExp = $data ? _`(new RegExp(${schemaCode}, ${u}))` : usePattern(cxt, schema)
const regExp = $data
? _`(function() {
try {
return new RegExp(${schemaCode}, ${u})
} catch (e) {
throw new Error('Invalid regular expression: ' + ${schemaCode} + ' at ' + ${it.errSchemaPath})
}
})()`
: usePattern(cxt, schema)
cxt.fail$data(_`!${regExp}.test(${data})`)
},
}
Expand Down
61 changes: 61 additions & 0 deletions spec/issues/2477_informative_pattern_errors.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import _Ajv from "../ajv2020"
import * as assert from "assert"

describe("Invalid regexp patterns should throw more informative errors (issue #2477)", () => {
it("throws with pattern and schema path", () => {
const ajv = new _Ajv()

const rootSchema = {
type: "string",
pattern: "^[0-9]{2-4}",
}

assert.throws(
() => ajv.compile(rootSchema),
(thrown: unknown) => {
assert.equal((thrown as Error).message, "Invalid regular expression: ^[0-9]{2-4} at #")
return true
}
)

const pathSchema = {
type: "object",
properties: {
foo: rootSchema,
},
}

assert.throws(
() => ajv.compile(pathSchema),
(thrown: unknown) => {
assert.equal(
(thrown as Error).message,
"Invalid regular expression: ^[0-9]{2-4} at #/properties/foo"
)
return true
}
)
})
it("throws with pattern and schema path with $data", () => {
const ajv = new _Ajv({$data: true})

const schema = {
properties: {
shouldMatch: {},
string: {pattern: {$data: "1/shouldMatch"}},
},
}
const validate = ajv.compile(schema)

assert.throws(
() => ajv.compile(validate({shouldMatch: "^[0-9]{2-4}", string: "123"})),
(thrown: unknown) => {
assert.equal(
(thrown as Error).message,
"Invalid regular expression: ^[0-9]{2-4} at #/properties/string"
)
return true
}
)
})
})

0 comments on commit d33a36d

Please sign in to comment.