ata-validator
1.61.3 · 29 Oct 2026MIT21.8k / weekRepositoryHomepagenpmAtom feed
1.61.3 is the newest release of 1.x.
In short
8 changed
Release note
Changed
In the browser build, a page's first check no longer pays for V8 compiling the engine, nor for building the schema's engine. Both move to when the page is idle (
requestIdleCallback, or 200 ms later where there is none, as in Safari and in workers): the first validator a page builds schedules one check of a small schema of ata's own, once per page, and then the engine for each validator built since, at most eight, which a validator adopts at its first check only if every input is still the same, its schema text included.addSchema()or a change to the schema object between construction and the first check is honored as before, a schema with custom keywords is left to its first check, since their compile functions are the caller's code, and nothing on a validator changes until it is used. The warm-up is dropped when a validator has compiled before the page is idle. Measured in Chrome with@hookform/resolverson an eight-field form, the first submit 300 ms after the form was built went from 6.43 to 0.88 ms, and from 18.56 to 2.48 ms with the CPU slowed 4x as Lighthouse does for mobile. A submit before the page has been idle went from 3.97 to 3.66 ms, and from 18.93 to 17.20 ms with the CPU slowed. Node, lite and edge do not carry the idle work.tests/test_browser_warmup.jscovers the warm-up, the adoption and each case where an engine built while idle must not be used.The interpreted engine gives a pattern to the platform RegExp when it has no group or alternation, few bounded choices in all, and at most one unbounded repeat, on one character or class and only when the pattern starts with
^: such a pattern runs in linear time on a backtracking engine, as the code generator already decided for these patterns (lib/regex-linear.js). The linear engine took 40 to 100 us to build a pattern's automaton, a RegExp about one. On lite, a form's first check went from 3.83 to 3.49 ms and a valid document from 205.8 to 193.0 ns.tests/test_regex_plain_linear.jsholds that every pattern taking the RegExp gets one from the code generator too, so both engines answer with the same matcher, and that the answers equal the linear engine's on generated strings.lib/rejections.jsand the schema order and diagnostic modules it brings load at the first compile, where they are first used, rather than when the package loads. Importing the browser build went from 4.41 to 4.36 ms in Node.A module written by
toStandaloneModule,ata compileorata buildexportsapplyDefaults(data)when its schema declares adefault: the runtime's defaults pass (preprocessSourceinlib/codegen-engine.js), which fills whatnew Validator(schema).validate()fills before it checks.validate()does not call it, so a module answers as before, andfromCompiledkeepsuseDefaults: false. The generated.d.mtsdeclares it. Over SchemaStore, 278 of 854 modules gain it and the other 576 are byte for byte what they were.toStandaloneModule(schema, { order: true }),ata compile --orderandata build --orderwrite a module that hands out its errors in the runtime's order, schema declaration order, instead of the order its collector found them in, which put a field'sformaterror before itspatternerror and, behind a$ref, a definition'srequiredbefore itsproperties, so a reader taking the first error of a field could show another message than the runtime. Without a$refthe collector writes each error site's ordinal and the module sorts by it; with one the module ranks paths withlib/schema-order.js's own functions, embedded as their text bylib/aot-order.js, over the schema's key skeleton. Off by default, since it costs bytes: 225 more gzipped, minified, for an eight-field form, about 1 KB for a small schema with references, 12.6% over 267 SchemaStore schemas. WithorderandapplyDefaults, modules matched the runtime's verdict, filled data and error list in order on every case of the official suites they compile (1,500 groups, 5,324 cases across six dialects) and on 1,952 SchemaStore sample documents. Modules that share the error runtime were in this order already.compiledModuleFor(schema, { order: true })passes it on, for a bundler plugin writing a module a form resolver reads directly.tests/test_aot_order_defaults.jscovers both.
Size
The browser build's first load is 1,095 bytes larger gzipped (57,059 to 58,154), for the idle work and the pattern check. With the CPU slowed 4x and a 1.6 Mbps link, the time from navigation until the form's resolver was ready did not move beyond noise (1,664.8 ms before, 1,666.7 after, against 1,658.9 for a second copy of the old build).
The package is 453.2 KB packed, for
lib/aot-order.jsand the emitter changes.ata-validator/liteis 56,167 bytes gzipped, up 419, and the Workers bundle 57,564, up 413, for the pattern check, the core's hook for the idle work and the core's internals the module emitters read.