ata-validator
1.61.3 · 29 Oct 2026MIT21.8k / weekRepositoryHomepagenpmAtom feed
Upgrading ata-validator from 1.7.0 to 1.7.1
1 release in betweenevery note read
Reading releases, release notes and advisories…
- 0
- changes to make
- 0
- advisories fixed
- 1
- new
- 0
- fixes
Release by release
- new
A closure-tree compiler for the interpreted engine. A schema the code generator declines is compiled into a tree of plain closures, one per schema node, with every keyword branch decided at compile time and
$reftargets resolved once; no source generation and nonew Function, so it works under a CSP and on Workers. Scope: schemas withoutunevaluatedProperties/unevaluatedItems, and$dynamicRefonly in single-resource schemas; everything else keeps the generic evaluator.tests/test_plan_compiler.jsholds the compiled tree to byte-identical verdicts and errors against the evaluator over 2,864 suite cases.
- new
5 other lines we could not sort, mostly version bumps
- 1.7.1
Plans that check only value-level keywords (most leaves of any schema) skip the evaluator's prologue entirely;
$refresolutions are cached with their planned target on the plan itself; the dynamic scope is pushed and popped in place instead of copied per resource. Rejection results are a small class with theerrorsaccessor on the prototype, since defining a getter inside an object literal builds a closure and an accessor property on every rejection, which was the single largest cost on the rejection path. - 1.7.1
The interpreted engine gained a verdict-only mode:
isValidObject()and the internal fast checks walk the schema without constructing a single error object, message string or scratch array. On an interpreter-routed schema the boolean check dropped from 894 ns to 70 ns. - 1.7.1
Object validation for
$dynamicRefschemas no longer routes to the native engine. The interpreted engine has scored the same on every$dynamicRefcase of the suite since the dynamic-scope fix in 1.7.0, needs no addon, and carries the verdict-only mode; the suite's$dynamicRefrejects dropped from about 1.7 µs to the interpreter's cost. - 1.7.1
String length bounds decide from the UTF-16 length where possible: a string's code point count always sits between half its length and its length, so
minLength/maxLengthonly count code points inside the narrow band where the answer is genuinely uncertain. The surrogate test is a single wraparound compare. The code generator already worked this way; the interpreter and the closure path now match it. - 1.7.1
Errors are paid for when read, not when produced.
validate()answers the verdict from the fastest engine for the schema and materializeserrorsthrough a cached getter on first access; declaration-order sorting and enrichment (received value, suggestions, source frames) moved with it into one presentation layer. A caller that only reads.valid, which is every gateway check, no longer pays for error construction at all. The output of.errorsis byte-for-byte what it was. Measured on a suite-shaped benchmark of prebuilt validators over 1,052 mixed valid and invalid cases,validate().validwent from 778 ns to about 150 ns per call, ahead of every error-capable validator we measured, and a rejection that never has its errors read now costs less thanabortEarlymode used to. One observable edge: mutating the data betweenvalidate()and the first read of.errorsnow reflects the mutated data in the errors, and if the mutation makes the data valid the errors fall back to a single generic entry.