ata-validator
1.61.3 · 29 Oct 2026MIT21.8k / weekRepositoryHomepagenpmAtom feed
1.61.3 is the newest release of 1.x.
In short
2 fixed7 changed2 internal
Release note
Fixed
A schema that names something
"__proto__"could accept documents it rejects. Several places copied a schema, or a map keyed by property names, by assignment, and assigning the key"__proto__"sets the copy's prototype instead of creating the property, so the constraint on it was gone from the copy. It happened for a property named"__proto__"next to a$refthat is resolved at compile time (one relative to a nested$id, for example), for a$refpointing at such a property, and for draft-07dependencieson such a property, which affected every engine. For example{"$id": "http://e.x/root", "$defs": {"S": {"$id": "s", "type": "string"}}, "properties": {"__proto__": {"type": "number"}, "r": {"$ref": "s"}}}accepted{"__proto__": "s"}. A schema that lists"__proto__": falseto keep that key out of documents was affected the same way. Affected: measured on 1.40.1, 1.41.0 and 1.43.0; earlier versions were not checked. Every copy now writes such a key as an own property.tests/test_proto_name_rename_invariance.jschecks that a schema and a document using the name answer exactly as the same pair with the name renamed, on every engine and every read, ahead-of-time modules included: 3328 documents, none different.validateJSON()withrichErrors: falsereturned the errors of a rejected document in the order generated code found them, wherevalidate()returns them in schema order, so one document could list its errors in two orders. Both now give the same list. Reading those errors costs about 50 ns more per rejection on a small schema.
Changed
Faster from process start to the first answer. Measured on 20 SchemaStore schemas as API routes and on the SARIF schema as a command line tool, each run in a fresh process, median of 11, against 1.43.0 (milliseconds, an empty Node process included):
1.43.0 1.44.0 20 routes, first valid requests 47.9 40.7 20 routes, first errors read 67.7 60.2 SARIF, one rejection with its errors read 90.9 33.4 5 MB SARIF log through validateJSON(), valid89.1 57.5 5 MB SARIF log through validateJSON(), invalid, errors read135.8 82.4 Where it comes from:
The first 64 calls of a large schema (over about 16K characters with its references followed) are answered by the interpreted engine, which the test suite holds to the same answers and errors, and the schema is compiled if the validator is still in use after that. A short-lived process never pays to generate and compile the code for it.
A schema that would expand past about 400K characters gets its verdict function with shared definitions from the start, instead of expanded first and thrown away.
The vendored meta-schemas load only for a schema that references one, not for every schema that names its dialect in
$schema, which made each compile's cache key a 30 KB string.The errorMessage module loads only for a schema that uses the keyword.
validateJSON()parses the text once when its errors are read, and on a large ASCII document finds the positions of the failing values through the native addon (simdjson), 3.1 ms instead of 8.3 on 5 MB. Without the addon, or with an older one, it works as before.
More schemas run on generated code:
propertyNameswith any subschema (each key is checked as a value), a property named$ref, and properties named afterObject.prototypemembers such asconstructorand__proto__. Of the 980 SchemaStore schemas, 869 run on generated code where 840 did.Cost: The browser runtime bundle is 115.8 KB gzipped, up from 114.1 KB. Requiring the package, compiling a schema and validating once takes the same time within noise. Modules from
ata buildare byte for byte the same size.