ata-validator 1.16.1 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to ata-validator are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/), and this project adheres to semantic versioning.
4
4
 
5
+ ## 1.17.0 - 2026-09-13
6
+
7
+ ### Changed
8
+
9
+ - Errors are put in schema declaration order by an integer computed when the schema is compiled, not by walking each error's schemaPath at read time. The rank of a path is its pre-order position in the schema tree, which is exactly the order the old array-of-indexes comparison produced; the code generator now writes that position into each error literal (`_o`, an internal field), the reader compares integers, and a list that already arrives in order is returned without sorting or allocating. Errors without a position (an appended custom-keyword error, a path into another document) keep their place next to the error before them. The ordinal logic lives in `lib/schema-order.js`; `tests/test_error_order_ordinal.js` holds the ordinal to the array rank on a set of paths and holds the public error order unchanged.
10
+ - The Standard Schema bridge caches parsed issue paths per instancePath string (bounded, entries frozen), instead of splitting the string for every issue of every rejection.
11
+ - Measured on the schema-benchmarks harness locally, before and after on the same machine: standard invalid 3.57 to 2.83 µs (21 percent less); every other row within noise. On the raw error list of that schema, 15 errors: 1.88 to 1.50 µs; through the Standard Schema bridge 3.30 to 1.99 µs. Verdict paths are untouched.
12
+ - `richErrors: false` keeps the v0.14 key set: the ordering field is dropped from that shape.
13
+
14
+ ## 1.16.2 - 2026-09-12
15
+
16
+ ### Fixed
17
+
18
+ - A schema with `unevaluatedProperties` or `unevaluatedItems` reported every failure as one placeholder error, `{ code: 'unevaluated', message: 'unevaluated property or item' }`, with no `keyword` and no `instancePath`. The generated code answers the verdict for these schemas but the error generator declines them, and the error path then fell into a stub instead of the interpreted engine, which reports them correctly. A wrong type, a missing required property, a bad format or an enum miss under a root `unevaluatedProperties: false` all came back as that one line, so anything mapping errors by keyword and path saw nothing useful. Failing data is now re-validated by the interpreted engine on that path, as it already was without the native addon for other declined shapes. Verdicts were never affected. Found by a user comparing error output on a generated config schema. `tests/test_unevaluated_error_path.js` holds the generated-code path to the interpreter's errors on five shapes, in all three engine modes.
19
+
5
20
  ## 1.16.1 - 2026-09-12
6
21
 
7
22
  ### Fixed
package/index.js CHANGED
@@ -423,83 +423,64 @@ function resolveSchemaByPath(rootSchema, schemaPath) {
423
423
  // A failing route sees the same handful of schemaPaths over and over, which is
424
424
  // what makes the first one worth having.
425
425
  const _rankCache = new WeakMap();
426
- const _keyIndexCache = new WeakMap();
427
-
428
- function keyIndex(node, seg) {
429
- let index = _keyIndexCache.get(node);
430
- if (index === undefined) {
431
- index = new Map();
432
- const keys = Object.keys(node);
433
- for (let i = 0; i < keys.length; i++) index.set(keys[i], i);
434
- _keyIndexCache.set(node, index);
435
- }
436
- const at = index.get(seg);
437
- return at === undefined ? -1 : at;
438
- }
439
-
440
- // `~1` and `~0` are the only escapes a JSON pointer has, and almost no schema
441
- // key contains a tilde. Looking for one is far cheaper than two regex passes
442
- // over every segment of every path.
443
- function unescapePointerSegment(seg) {
444
- return seg.indexOf('~') < 0 ? seg : seg.replace(/~1/g, '/').replace(/~0/g, '~');
445
- }
446
-
447
- function schemaOrderRank(rootSchema, schemaPath) {
448
- if (!schemaPath || typeof schemaPath !== 'string' || !schemaPath.startsWith('#')) return null;
449
- if (rootSchema === null || typeof rootSchema !== 'object') return null;
426
+ const { rankFor: schemaOrderRank, ordinalFor: schemaOrdinal } = require('./lib/schema-order');
450
427
 
451
- let byPath = _rankCache.get(rootSchema);
452
- if (byPath === undefined) { byPath = new Map(); _rankCache.set(rootSchema, byPath); }
453
- const hit = byPath.get(schemaPath);
454
- if (hit !== undefined) return hit;
455
-
456
- const rank = _computeRank(rootSchema, schemaPath);
457
- byPath.set(schemaPath, rank);
458
- return rank;
428
+ // A raw error without the `_o` ordering key, for the legacy error shape.
429
+ function stripOrdinal(e) {
430
+ if (e === null || typeof e !== 'object' || e._o === undefined) return e;
431
+ const out = {};
432
+ for (const k in e) if (k !== '_o') out[k] = e[k];
433
+ return out;
459
434
  }
460
435
 
461
- function _computeRank(rootSchema, schemaPath) {
462
- const rank = [];
463
- let node = rootSchema;
464
- let start = 1;
465
- while (start <= schemaPath.length) {
466
- let end = schemaPath.indexOf('/', start);
467
- if (end < 0) end = schemaPath.length;
468
- if (end === start) { start = end + 1; continue; } // what filter(Boolean) dropped
469
- const seg = unescapePointerSegment(schemaPath.slice(start, end));
470
- start = end + 1;
471
-
472
- if (node == null || typeof node !== 'object') break;
473
- if (Array.isArray(node)) {
474
- const idx = Number(seg);
475
- if (!Number.isInteger(idx) || idx < 0 || idx >= node.length) break;
476
- rank.push(idx);
477
- node = node[idx];
478
- } else {
479
- const idx = keyIndex(node, seg);
480
- if (idx < 0) break;
481
- rank.push(idx);
482
- node = node[seg];
483
- }
436
+ // Errors in schema declaration order. Each error's key is its schemaPath's
437
+ // pre-order ordinal in the root schema: written into the literal by the code
438
+ // generator (`_o`), looked up once per path otherwise. Most rejections come
439
+ // out already ordered, and those return without sorting or allocating.
440
+ function sortErrorsBySchemaOrder(rootSchema, errors) {
441
+ const n = errors.length;
442
+ const keys = new Array(n);
443
+ let sorted = true;
444
+ let prev = -1;
445
+ for (let i = 0; i < n; i++) {
446
+ const e = errors[i];
447
+ let o = typeof e._o === 'number' ? e._o : schemaOrdinal(rootSchema, e.schemaPath);
448
+ // An error with no place in this document (an appended custom-keyword
449
+ // error, a path into another schema) stays next to the error before it,
450
+ // which is where the rank comparison left it too.
451
+ if (o === null) o = prev < 0 ? 0 : prev;
452
+ keys[i] = o;
453
+ if (o < prev) sorted = false;
454
+ prev = o;
484
455
  }
485
- return rank;
456
+ if (sorted) return errors;
457
+ const idx = new Array(n);
458
+ for (let i = 0; i < n; i++) idx[i] = i;
459
+ idx.sort((a, b) => keys[a] - keys[b] || a - b);
460
+ const out = new Array(n);
461
+ for (let i = 0; i < n; i++) out[i] = errors[idx[i]];
462
+ return out;
486
463
  }
487
464
 
488
- function sortErrorsBySchemaOrder(rootSchema, errors) {
489
- const ranked = errors.map((e, i) => ({ e, i, rank: schemaOrderRank(rootSchema, e.schemaPath) }));
490
- ranked.sort((a, b) => {
491
- if (!a.rank || !b.rank) return a.i - b.i;
492
- const n = Math.min(a.rank.length, b.rank.length);
493
- for (let k = 0; k < n; k++) {
494
- if (a.rank[k] !== b.rank[k]) return a.rank[k] - b.rank[k];
495
- }
496
- return a.i - b.i;
497
- });
498
- return ranked.map((r) => r.e);
499
- }
500
465
 
466
+ // Paths repeat across rejections of the same shape, so the parsed segment
467
+ // list is cached per path string. Entries are frozen: the same array is
468
+ // handed to every issue that names the path. The cache is bounded so a
469
+ // stream of array indexes cannot grow it without limit.
470
+ const _pathCache = new Map();
471
+ const PATH_CACHE_MAX = 4096;
501
472
  function parsePointerPath(path) {
502
- if (!path) return [];
473
+ if (!path) return EMPTY_PATH;
474
+ const hit = _pathCache.get(path);
475
+ if (hit !== undefined) return hit;
476
+ const segs = Object.freeze(parsePointerPathUncached(path));
477
+ if (_pathCache.size >= PATH_CACHE_MAX) _pathCache.clear();
478
+ _pathCache.set(path, segs);
479
+ return segs;
480
+ }
481
+ const EMPTY_PATH = Object.freeze([]);
482
+
483
+ function parsePointerPathUncached(path) {
503
484
  // One pass, no intermediate arrays. Per Standard Schema V1 an array index
504
485
  // is emitted as a number and an object key as a string; a segment is an
505
486
  // index when it is all digits with no leading zero.
@@ -1057,12 +1038,14 @@ class Validator {
1057
1038
  }]
1058
1039
  };
1059
1040
  };
1041
+ // The error generator declines unevaluated*; the interpreted engine
1042
+ // reports those schemas correctly, so failing data is re-validated
1043
+ // there. This used to be a placeholder error with no keyword and no
1044
+ // path, which hid whatever had actually failed.
1060
1045
  const errFn =
1061
1046
  safeErrFn ||
1062
- (hasUnevaluated
1063
- ? (d) => ({ valid: jsFn(d), errors: jsFn(d) ? [] : [{ code: 'unevaluated', path: '', message: 'unevaluated property or item' }] })
1064
- : !native
1065
- ? jsOnlyFallback
1047
+ (hasUnevaluated || !native
1048
+ ? jsOnlyFallback
1066
1049
  : hasDynRef
1067
1050
  ? (d) => {
1068
1051
  this._ensureNative();
@@ -1461,7 +1444,9 @@ class Validator {
1461
1444
  schemaPositions: self._schemaPositions,
1462
1445
  schemaFile: self._source ? self._source.path : undefined,
1463
1446
  }))
1464
- : raw;
1447
+ // The v0.14 shape is a fixed key set; the ordering key the
1448
+ // generated code carries is dropped from it here.
1449
+ : raw.map(stripOrdinal);
1465
1450
  // Correlation is published, never applied. Both halves of a
1466
1451
  // typo pair stay in the array; `related` only says they are
1467
1452
  // one mistake, so a wrong pairing costs a sentence rather
@@ -73,6 +73,7 @@ function enumCondition(ctx, vals, v) {
73
73
 
74
74
 
75
75
  const { codeFor } = require('./error-codes')
76
+ const { ordinalFor } = require('./schema-order')
76
77
  const { compileSafe, patternIsSafe } = require('./safe-regex')
77
78
 
78
79
  // Closure value for a patternProperties/propertyNames regex: the linear-time
@@ -94,6 +95,14 @@ const DOC_BASE = 'https://ata-validator.com/e/'
94
95
  // like ",schemaSource:Object.freeze({...})" or "" if no source map hit.
95
96
  // The fragment always starts with a leading comma when non-empty so callers
96
97
  // can splice it inside an existing object literal.
98
+ // The error's position in schema declaration order, as a literal field the
99
+ // reader sorts by without deriving it from the path. Empty when the path is
100
+ // not into the root document.
101
+ function ordinalField (ctx, schemaPath) {
102
+ const o = ctx && ctx.rootSchema ? ordinalFor(ctx.rootSchema, schemaPath) : null
103
+ return o === null ? '' : `,_o:${o}`
104
+ }
105
+
97
106
  function buildErrorLiteral (opts) {
98
107
  const { keyword, format, schemaPath, sourceMap } = opts
99
108
  let code = (keyword === 'format' && format) ? codeFor('format', format) : codeFor(keyword)
@@ -3213,7 +3222,7 @@ function compileToJSCodegenWithErrors(schema, schemaMap, userFormats, sourceOpts
3213
3222
  // AOT output small for schemas that don't compose. Standalone modules can't
3214
3223
  // require('./branch-collapse'), so the helper body is embedded verbatim.
3215
3224
  if (ctx.usesBranchCollapse) {
3216
- ctx.helperCode.push("const __ATA_SEVERITY={type:10,const:8,enum:8,required:5,format:3,minLength:3,maxLength:3,minimum:3,maximum:3,pattern:3,additionalProperties:2,unevaluatedProperties:2,unevaluatedItems:2};function __ataScore(errs){if(!errs||!errs.length)return 0;let s=0;for(const e of errs)s+=__ATA_SEVERITY[e.keyword]||4;return errs.length*100+s}function __ataCollapse(kw,br,pp,sp){const pass=br.filter(b=>b.valid);if(kw==='oneOf'){if(pass.length===1)return null;if(pass.length>1)return{code:'ATA4002',keyword:'oneOf',instancePath:pp||'',path:pp||'',schemaPath:sp,message:'value matched '+pass.length+' of '+br.length+' oneOf variants, expected exactly one',params:{matched:pass.length,total:br.length}}}else{if(pass.length>=1)return null}let bi=0,bs=Infinity;for(let i=0;i<br.length;i++){const s=__ataScore(br[i].errors);if(s<bs){bs=s;bi=i}}const code=kw==='oneOf'?'ATA4001':'ATA4003';const best=br[bi];return{code,keyword:kw,instancePath:pp||'',path:pp||'',schemaPath:sp,message:'value matched 0 of '+br.length+' '+kw+' variants',params:{variants:br.length,closest:bi,closestName:best.title||('variant '+(bi+1))},branchErrors:best.errors}}")
3225
+ ctx.helperCode.push("const __ATA_SEVERITY={type:10,const:8,enum:8,required:5,format:3,minLength:3,maxLength:3,minimum:3,maximum:3,pattern:3,additionalProperties:2,unevaluatedProperties:2,unevaluatedItems:2};function __ataScore(errs){if(!errs||!errs.length)return 0;let s=0;for(const e of errs)s+=__ATA_SEVERITY[e.keyword]||4;return errs.length*100+s}function __ataCollapse(kw,br,pp,sp,o){const pass=br.filter(b=>b.valid);if(kw==='oneOf'){if(pass.length===1)return null;if(pass.length>1)return{code:'ATA4002',keyword:'oneOf',instancePath:pp||'',path:pp||'',schemaPath:sp,_o:o,message:'value matched '+pass.length+' of '+br.length+' oneOf variants, expected exactly one',params:{matched:pass.length,total:br.length}}}else{if(pass.length>=1)return null}let bi=0,bs=Infinity;for(let i=0;i<br.length;i++){const s=__ataScore(br[i].errors);if(s<bs){bs=s;bi=i}}const code=kw==='oneOf'?'ATA4001':'ATA4003';const best=br[bi];return{code,keyword:kw,instancePath:pp||'',path:pp||'',schemaPath:sp,_o:o,message:'value matched 0 of '+br.length+' '+kw+' variants',params:{variants:br.length,closest:bi,closestName:best.title||('variant '+(bi+1))},branchErrors:best.errors}}")
3217
3226
  }
3218
3227
  if (lines.length === 0) return (d) => ({ valid: true, errors: [] })
3219
3228
 
@@ -3299,7 +3308,7 @@ function emitBranchCollapse (branches, keyword, v, pathExpr, lines, ctx, schemaP
3299
3308
  } else if (sub === false) {
3300
3309
  // A false branch never matches; it reports the same error the
3301
3310
  // interpreter attaches to a false schema.
3302
- subLines.push(`_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${subSp}',params:{},message:'boolean schema is false'})`)
3311
+ subLines.push(`_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${subSp}'${ordinalField(ctx, `${subSp}`)},params:{},message:'boolean schema is false'})`)
3303
3312
  }
3304
3313
  const title = (sub && typeof sub === 'object' && typeof sub.title === 'string') ? sub.title : ''
3305
3314
  titles.push(title)
@@ -3313,7 +3322,7 @@ function emitBranchCollapse (branches, keyword, v, pathExpr, lines, ctx, schemaP
3313
3322
  const titleArr = JSON.stringify(titles)
3314
3323
  const collapsed = `_brc${fi}`
3315
3324
  const pp = pathExpr || '""'
3316
- lines.push(`{const ${fnArr}=[${fns.join(',')}];const _bt${fi}=${titleArr};const ${resArr}=[];for(let _bi=0;_bi<${fnArr}.length;_bi++){const _br=${fnArr}[_bi](${v});${resArr}.push({valid:_br.valid,errors:_br.errors,title:_bt${fi}[_bi]})}const ${collapsed}=__ataCollapse('${branchKw}',${resArr},${pp},'${branchSp}');if(${collapsed}){_e.push(${collapsed});if(!_all)return{valid:false,errors:_e}}}`)
3325
+ lines.push(`{const ${fnArr}=[${fns.join(',')}];const _bt${fi}=${titleArr};const ${resArr}=[];for(let _bi=0;_bi<${fnArr}.length;_bi++){const _br=${fnArr}[_bi](${v});${resArr}.push({valid:_br.valid,errors:_br.errors,title:_bt${fi}[_bi]})}const ${collapsed}=__ataCollapse('${branchKw}',${resArr},${pp},'${branchSp}',${(() => { const o = ordinalFor(ctx.rootSchema, branchSp); return o === null ? 'null' : o })()});if(${collapsed}){_e.push(${collapsed});if(!_all)return{valid:false,errors:_e}}}`)
3317
3326
  }
3318
3327
 
3319
3328
  // Error-collecting code generator.
@@ -3327,7 +3336,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3327
3336
  // name this keyword `false schema`; changing it here would change output
3328
3337
  // the interpreter path already produces, so both engines say `not`.
3329
3338
  if (schema === false) {
3330
- lines.push(`;_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}',params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}`)
3339
+ lines.push(`;_e.push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}'${ordinalField(ctx, `${schemaPrefix}`)},params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}`)
3331
3340
  return
3332
3341
  }
3333
3342
  if (schema === true) return
@@ -3442,7 +3451,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3442
3451
  {
3443
3452
  const typeSp = `${schemaPrefix}/type`
3444
3453
  const lit = buildErrorLiteral({ keyword: 'type', schemaPath: typeSp, sourceMap: ctx.sourceMap })
3445
- lines.push(`if(!(${conds.join('||')})){_e.push({code:'${lit.codeStr}',keyword:'type',instancePath:${pathExpr||'""'},schemaPath:'${typeSp}',params:{type:'${expected}'},message:'must be ${expected}',docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3454
+ lines.push(`if(!(${conds.join('||')})){_e.push({code:'${lit.codeStr}',keyword:'type',instancePath:${pathExpr||'""'},schemaPath:'${typeSp}'${ordinalField(ctx, `${typeSp}`)},params:{type:'${expected}'},message:'must be ${expected}',docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3446
3455
  }
3447
3456
  }
3448
3457
 
@@ -3455,7 +3464,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3455
3464
  const fail = (keyword, schemaSuffix, paramsCode, msgCode, fmt) => {
3456
3465
  const sp = schemaPrefix + '/' + schemaSuffix
3457
3466
  const lit = buildErrorLiteral({ keyword, format: fmt, schemaPath: sp, sourceMap: ctx.sourceMap })
3458
- return `_e.push({code:'${lit.codeStr}',keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode},docUrl:'${lit.docUrl}'${lit.frame}});if(!_all)return{valid:false,errors:_e}`
3467
+ return `_e.push({code:'${lit.codeStr}',keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode},docUrl:'${lit.docUrl}'${lit.frame}${ordinalField(ctx, sp)}});if(!_all)return{valid:false,errors:_e}`
3459
3468
  }
3460
3469
 
3461
3470
  // enum
@@ -3480,7 +3489,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3480
3489
  const reqSp = `${schemaPrefix}/required`
3481
3490
  const reqLit = buildErrorLiteral({ keyword: 'required', schemaPath: reqSp, sourceMap: ctx.sourceMap })
3482
3491
  for (const key of schema.required) {
3483
- lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){_e.push({code:'${reqLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${reqSp}',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'",docUrl:'${reqLit.docUrl}'${reqLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3492
+ lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){_e.push({code:'${reqLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${reqSp}'${ordinalField(ctx, `${reqSp}`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'",docUrl:'${reqLit.docUrl}'${reqLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3484
3493
  }
3485
3494
  }
3486
3495
 
@@ -3550,7 +3559,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3550
3559
  const fc = FORMAT_CODEGEN[schema.format]
3551
3560
  const fmtSp = `${schemaPrefix}/format`
3552
3561
  const fmtLit = buildErrorLiteral({ keyword: 'format', format: schema.format, schemaPath: fmtSp, sourceMap: ctx.sourceMap })
3553
- const failPush = `_e.push({code:'${fmtLit.codeStr}',keyword:'format',instancePath:${pathExpr||'""'},schemaPath:'${fmtSp}',params:{format:'${esc(schema.format)}'},message:'must match format "${esc(schema.format)}"',docUrl:'${fmtLit.docUrl}'${fmtLit.frame}});if(!_all)return{valid:false,errors:_e}`
3562
+ const failPush = `_e.push({code:'${fmtLit.codeStr}',keyword:'format',instancePath:${pathExpr||'""'},schemaPath:'${fmtSp}'${ordinalField(ctx, `${fmtSp}`)},params:{format:'${esc(schema.format)}'},message:'must match format "${esc(schema.format)}"',docUrl:'${fmtLit.docUrl}'${fmtLit.frame}});if(!_all)return{valid:false,errors:_e}`
3554
3563
  // Format errors use the boolean codegen, each `return false` becoming an
3555
3564
  // error push. One violation reports once: the first failing statement
3556
3565
  // pushes and leaves the labeled block, where it used to fall through and
@@ -3634,7 +3643,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3634
3643
  patChecks.push(`_re${ctx.regExpMap.get(pattern)}.test(_k${ci}[_i])`)
3635
3644
  }
3636
3645
  const isAdditional = patChecks.length ? `!_a${ci}.has(_k${ci}[_i])&&!(${patChecks.join('||')})` : `!_a${ci}.has(_k${ci}[_i])`
3637
- const inner = `const _k${ci}=Object.keys(${v});const _a${ci}=new Set([${allowed}]);for(let _i=0;_i<_k${ci}.length;_i++){if(${isAdditional}){_e.push({code:'${apLit.codeStr}',keyword:'additionalProperties',instancePath:${pathExpr||'""'},schemaPath:'${apSp}',params:{additionalProperty:_k${ci}[_i]},message:'must NOT have additional properties',docUrl:'${apLit.docUrl}'${apLit.frame}});if(!_all)return{valid:false,errors:_e}}}`
3646
+ const inner = `const _k${ci}=Object.keys(${v});const _a${ci}=new Set([${allowed}]);for(let _i=0;_i<_k${ci}.length;_i++){if(${isAdditional}){_e.push({code:'${apLit.codeStr}',keyword:'additionalProperties',instancePath:${pathExpr||'""'},schemaPath:'${apSp}'${ordinalField(ctx, `${apSp}`)},params:{additionalProperty:_k${ci}[_i]},message:'must NOT have additional properties',docUrl:'${apLit.docUrl}'${apLit.frame}});if(!_all)return{valid:false,errors:_e}}}`
3638
3647
  lines.push(isObj ? `{${inner}}` : `if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){${inner}}`)
3639
3648
  }
3640
3649
 
@@ -3644,7 +3653,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3644
3653
  const drLit = buildErrorLiteral({ keyword: 'dependentRequired', schemaPath: drSp, sourceMap: ctx.sourceMap })
3645
3654
  for (const [key, deps] of Object.entries(schema.dependentRequired)) {
3646
3655
  for (const dep of deps) {
3647
- lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){_e.push({code:'${drLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${drSp}',params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'",docUrl:'${drLit.docUrl}'${drLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3656
+ lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){_e.push({code:'${drLit.codeStr}',keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${drSp}'${ordinalField(ctx, `${drSp}`)},params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'",docUrl:'${drLit.docUrl}'${drLit.frame}});if(!_all)return{valid:false,errors:_e}}`)
3648
3657
  }
3649
3658
  }
3650
3659
  }
@@ -3731,7 +3740,7 @@ function genCodeE(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3731
3740
  if (schema.propertyNames === false) {
3732
3741
  const ki = ctx.varCounter++
3733
3742
  const p = pathExpr ? `${pathExpr}+'/'+_k${ki}` : `'/'+_k${ki}`
3734
- lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){_e.push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames',params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}}}`)
3743
+ lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){_e.push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames'${ordinalField(ctx, `${schemaPrefix}/propertyNames`)},params:{},message:'boolean schema is false'});if(!_all)return{valid:false,errors:_e}}}`)
3735
3744
  }
3736
3745
 
3737
3746
  // propertyNames
@@ -3973,7 +3982,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
3973
3982
  if (schema === false) {
3974
3983
  // Leading semicolon: the previous generated line may end in an
3975
3984
  // expression, and a line starting with `(` would be parsed as a call.
3976
- lines.push(`;(_e||(_e=[])).push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}',params:{},message:'boolean schema is false'})`)
3985
+ lines.push(`;(_e||(_e=[])).push({keyword:'not',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}'${ordinalField(ctx, `${schemaPrefix}`)},params:{},message:'boolean schema is false'})`)
3977
3986
  return
3978
3987
  }
3979
3988
  if (schema === true) return
@@ -4061,12 +4070,15 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
4061
4070
  const pathVal = pathExpr ? pathExpr.slice(1, -1) : ''
4062
4071
  const msgVal = msgCode.slice(1, -1)
4063
4072
  ctx.closureVars.push(errVar)
4064
- ctx.closureVals.push(Object.freeze({keyword, instancePath: pathVal, schemaPath: sp, params: Object.freeze(paramsVal), message: msgVal}))
4073
+ const o = ordinalFor(ctx.rootSchema, sp)
4074
+ const lit = {keyword, instancePath: pathVal, schemaPath: sp, params: Object.freeze(paramsVal), message: msgVal}
4075
+ if (o !== null) lit._o = o
4076
+ ctx.closureVals.push(Object.freeze(lit))
4065
4077
  return `(_e||(_e=[])).push(${errVar})`
4066
4078
  }
4067
4079
  }
4068
4080
  // Dynamic path (e.g., array index): inline as before
4069
- return `(_e||(_e=[])).push({keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode}})`
4081
+ return `(_e||(_e=[])).push({keyword:'${keyword}',instancePath:${pathExpr||'""'},schemaPath:'${sp}',params:${paramsCode},message:${msgCode}${ordinalField(ctx, sp)}})`
4070
4082
  }
4071
4083
 
4072
4084
  if (types) {
@@ -4135,7 +4147,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
4135
4147
  ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/required`, params: Object.freeze({missingProperty: key}), message: `must have required property '${key}'`}))
4136
4148
  lines.push(`if(${check}){(_e||(_e=[])).push(${errVar})}`)
4137
4149
  } else {
4138
- lines.push(`if(${check}){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
4150
+ lines.push(`if(${check}){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required'${ordinalField(ctx, `${schemaPrefix}/required`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
4139
4151
  }
4140
4152
  }
4141
4153
  } else if (schema.required) {
@@ -4149,7 +4161,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
4149
4161
  ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/required`, params: Object.freeze({missingProperty: key}), message: `must have required property '${key}'`}))
4150
4162
  lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push(${errVar})}`)
4151
4163
  } else {
4152
- lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required',params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
4164
+ lines.push(`if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})&&!(${JSON.stringify(key)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/required'${ordinalField(ctx, `${schemaPrefix}/required`)},params:{missingProperty:'${esc(key)}'},message:"must have required property '${esc(key)}'"})}`)
4153
4165
  }
4154
4166
  }
4155
4167
  }
@@ -4271,7 +4283,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
4271
4283
  ctx.closureVals.push(Object.freeze({keyword: 'required', instancePath: pathVal, schemaPath: `${schemaPrefix}/dependentRequired`, params: Object.freeze({missingProperty: dep}), message: `must have required property '${dep}'`}))
4272
4284
  lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push(${errVar})}`)
4273
4285
  } else {
4274
- lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/dependentRequired',params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'"})}`)
4286
+ lines.push(`if(typeof ${v}==='object'&&${v}!==null&&${JSON.stringify(key)} in ${v}&&!(${JSON.stringify(dep)} in ${v})){(_e||(_e=[])).push({keyword:'required',instancePath:${pathExpr||'""'},schemaPath:'${schemaPrefix}/dependentRequired'${ordinalField(ctx, `${schemaPrefix}/dependentRequired`)},params:{missingProperty:'${esc(dep)}'},message:"must have required property '${esc(dep)}'"})}`)
4275
4287
  }
4276
4288
  }
4277
4289
  }
@@ -4417,7 +4429,7 @@ function genCodeC(schema, v, pathExpr, lines, ctx, schemaPrefix) {
4417
4429
  if (schema.propertyNames === false) {
4418
4430
  const ki = ctx.varCounter++
4419
4431
  const p = pathExpr ? `${pathExpr}+'/'+_k${ki}` : `'/'+_k${ki}`
4420
- lines.push(`;if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){(_e||(_e=[])).push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames',params:{},message:'boolean schema is false'})}}`)
4432
+ lines.push(`;if(typeof ${v}==='object'&&${v}!==null&&!Array.isArray(${v})){for(const _k${ki} in ${v}){(_e||(_e=[])).push({keyword:'not',instancePath:${p},schemaPath:'${schemaPrefix}/propertyNames'${ordinalField(ctx, `${schemaPrefix}/propertyNames`)},params:{},message:'boolean schema is false'})}}`)
4421
4433
  }
4422
4434
 
4423
4435
  // propertyNames — skip if already merged into patternProperties loop
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+
3
+ // Declaration order of a schemaPath within its root schema.
4
+ //
5
+ // `rankFor` is the path of child indexes from the root to the node the
6
+ // schemaPath names (or to the deepest node it can reach), which sorts errors
7
+ // in the order their keywords appear in the schema. `ordinalFor` is the same
8
+ // order as one integer: the node's pre-order position in the schema tree.
9
+ // Comparing two ranks segment by segment gives exactly the pre-order
10
+ // relation, so the integer can stand in for the array, and the code
11
+ // generator can compute it once per error site instead of the reader
12
+ // deriving it from the path string on every rejection.
13
+ //
14
+ // Both are memoized per root schema; a validator's root never changes.
15
+
16
+ const _keyIndexCache = new WeakMap();
17
+ const _rankCache = new WeakMap();
18
+ const _ordinalCache = new WeakMap();
19
+
20
+ function keyIndex(node, seg) {
21
+ let index = _keyIndexCache.get(node);
22
+ if (index === undefined) {
23
+ index = new Map();
24
+ const keys = Object.keys(node);
25
+ for (let i = 0; i < keys.length; i++) index.set(keys[i], i);
26
+ _keyIndexCache.set(node, index);
27
+ }
28
+ const at = index.get(seg);
29
+ return at === undefined ? -1 : at;
30
+ }
31
+
32
+ // `~1` and `~0` are the only escapes a JSON pointer has, and almost no schema
33
+ // key contains a tilde. Looking for one is far cheaper than two regex passes
34
+ // over every segment of every path.
35
+ function unescapePointerSegment(seg) {
36
+ return seg.indexOf('~') < 0 ? seg : seg.replace(/~1/g, '/').replace(/~0/g, '~');
37
+ }
38
+
39
+ function escapePointerSegment(seg) {
40
+ return seg.indexOf('~') < 0 && seg.indexOf('/') < 0 ? seg : seg.replace(/~/g, '~0').replace(/\//g, '~1');
41
+ }
42
+
43
+ function rankFor(rootSchema, schemaPath) {
44
+ if (!schemaPath || typeof schemaPath !== 'string' || !schemaPath.startsWith('#')) return null;
45
+ if (rootSchema === null || typeof rootSchema !== 'object') return null;
46
+ let byPath = _rankCache.get(rootSchema);
47
+ if (byPath === undefined) { byPath = new Map(); _rankCache.set(rootSchema, byPath); }
48
+ const hit = byPath.get(schemaPath);
49
+ if (hit !== undefined) return hit;
50
+ const rank = computeRank(rootSchema, schemaPath);
51
+ byPath.set(schemaPath, rank);
52
+ return rank;
53
+ }
54
+
55
+ function computeRank(rootSchema, schemaPath) {
56
+ const rank = [];
57
+ let node = rootSchema;
58
+ let start = 1;
59
+ while (start <= schemaPath.length) {
60
+ let end = schemaPath.indexOf('/', start);
61
+ if (end < 0) end = schemaPath.length;
62
+ if (end === start) { start = end + 1; continue; }
63
+ const seg = unescapePointerSegment(schemaPath.slice(start, end));
64
+ start = end + 1;
65
+ if (node == null || typeof node !== 'object') break;
66
+ if (Array.isArray(node)) {
67
+ const idx = Number(seg);
68
+ if (!Number.isInteger(idx) || idx < 0 || idx >= node.length) break;
69
+ rank.push(idx);
70
+ node = node[idx];
71
+ } else {
72
+ const idx = keyIndex(node, seg);
73
+ if (idx < 0) break;
74
+ rank.push(idx);
75
+ node = node[seg];
76
+ }
77
+ }
78
+ return rank;
79
+ }
80
+
81
+ // Pre-order numbering of every node in the schema, keyed by its pointer as
82
+ // it appears in a schemaPath (segments escaped). Built once per root, on the
83
+ // first ask. Cyclic structures are guarded; a schema object can contain
84
+ // itself only through references, which are strings.
85
+ function ordinals(rootSchema) {
86
+ let map = _ordinalCache.get(rootSchema);
87
+ if (map !== undefined) return map;
88
+ map = new Map();
89
+ const seen = new Set();
90
+ let next = 0;
91
+ const walk = (node, pointer) => {
92
+ map.set(pointer, next++);
93
+ if (node === null || typeof node !== 'object') return;
94
+ if (seen.has(node)) return;
95
+ seen.add(node);
96
+ if (Array.isArray(node)) {
97
+ for (let i = 0; i < node.length; i++) walk(node[i], pointer + '/' + i);
98
+ } else {
99
+ for (const key of Object.keys(node)) walk(node[key], pointer + '/' + escapePointerSegment(key));
100
+ }
101
+ };
102
+ walk(rootSchema, '#');
103
+ _ordinalCache.set(rootSchema, map);
104
+ return map;
105
+ }
106
+
107
+ // The ordinal of the deepest node the schemaPath reaches; null when the path
108
+ // is not into this document.
109
+ function ordinalFor(rootSchema, schemaPath) {
110
+ if (!schemaPath || typeof schemaPath !== 'string' || schemaPath.charCodeAt(0) !== 35) return null;
111
+ if (rootSchema === null || typeof rootSchema !== 'object') return null;
112
+ const map = ordinals(rootSchema);
113
+ const hit = map.get(schemaPath);
114
+ if (hit !== undefined) return hit;
115
+ // Walk back to the longest prefix that exists. Paths through a keyword's
116
+ // value that is a primitive, or through a key the schema does not have,
117
+ // land on the nearest enclosing node.
118
+ let p = schemaPath;
119
+ while (true) {
120
+ const cut = p.lastIndexOf('/');
121
+ if (cut < 0) return 0;
122
+ p = p.slice(0, cut);
123
+ const o = map.get(p);
124
+ if (o !== undefined) return o;
125
+ }
126
+ }
127
+
128
+ module.exports = { rankFor, ordinalFor, unescapePointerSegment };
package/lib/version.js CHANGED
@@ -7,4 +7,4 @@
7
7
  //
8
8
  // Kept in lockstep with package.json by `tests/test_version_sync.js`.
9
9
 
10
- module.exports = '1.16.1';
10
+ module.exports = '1.17.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.16.1",
3
+ "version": "1.17.0",
4
4
  "description": "JSON Schema validation with first-class TypeScript and zero runtime cost. AOT compile to per-schema ESM modules with zero validator dependency. Generic Validator<T> for TypeBox/Zod/Valibot composition. Optional runtime API. Standard Schema V1 compatible.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -51,7 +51,7 @@
51
51
  "release:check": "node scripts/regen-safe-regex-source.js && node tests/test_pack_purity.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_source_sync.js && node tests/test_version_sync.js",
52
52
  "build": "cmake-js build --target ata",
53
53
  "rebuild": "cmake-js rebuild --target ata",
54
- "test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
54
+ "test": "node test.js && node tests/test_removed_aot_methods.js && node tests/test_no_native.js && node tests/test_no_eval.js && node tests/test_property_dependencies.js && node tests/test_v1_dialect.js && node tests/test_buffer_path_parity.js && node tests/test_buffer_gate.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_aot_parse.js && node tests/test_draft7_semantics.js && node tests/test_metaschema_ref.js && node tests/test_pure_js_unsupported.js && node tests/test_native_load_order.js && node tests/test_pack_purity.js && node tests/test_make_native_package.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_safe_regex_source_sync.js && node tests/test_t_builder.js && node tests/test_async_refine.js && node tests/test_safe_regex.js && node tests/test_safe_regex_integration.js && node tests/test_aot_build.js && node tests/test_aot_differential.js && node tests/test_aot_cli_build.js && node tests/test_aot_cli_smoke.js && node tests/test_bundle_standalone.js && node tests/test_standalone_anyof.js && node tests/test_standalone_formats.js && node tests/test_aot_format_mode.js && node tests/test_aot_additional_props_errors.js && node tests/test_id_anchor_refs.js && node tests/test_engine_routing.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_formats_single_pass.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_ajv_parity.js && node tests/test_user_format_error_path.js && node tests/test_unevaluated_error_path.js && node tests/test_pattern_properties_errors.js && node tests/test_no_input_mutation.js && node tests/test_typed_validator_runner.js && node tests/test_define_schema.js && node tests/test_error_codes_lock.js && node tests/test_error_code_lookup.js && node tests/test_error_order.js && node tests/test_error_order_ordinal.js && node tests/test_value_equality.js && node tests/test_vocabulary.js && node tests/test_schema_scan.js && node tests/test_lazy_errors.js && node tests/test_lazy_instance.js && node tests/test_cyclic_input.js && node tests/test_native_error_codes.js && node tests/test_verdict_preprocess.js && node tests/test_plan_compiler.js && node tests/test_nullable.js && node tests/test_validate_and_parse.js && node tests/test_validate_data.js && node tests/test_enrich_error.js && node tests/test_enrich_received.js && node tests/test_rich_errors_optout.js && node tests/test_error_messages.js && node tests/test_source_positions.js && node tests/fuzz_positions.js && node tests/test_data_positions.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_additive_fields.js && node tests/test_diagnostic_source.js && node tests/test_diagnose.js && node tests/test_correlate.js && node tests/test_diagnostics_score.js && node tests/test_runtime_error_dx.js && node tests/test_aot_error_dx.js && node tests/test_abort_early.js && node tests/test_branch_collapse.js && node tests/test_suggestions.js && node tests/test_cli_validate.js && node tests/test_cli_version.js && node benchmark/bench_aot_size.mjs",
55
55
  "bench:size": "node benchmark/bench_aot_size.mjs",
56
56
  "test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
57
57
  "test:compat": "node tests/test_compat.js",
@@ -122,13 +122,13 @@
122
122
  "LICENSE"
123
123
  ],
124
124
  "optionalDependencies": {
125
- "@ata-validator/native-darwin-arm64": "1.16.1",
126
- "@ata-validator/native-darwin-x64": "1.16.1",
127
- "@ata-validator/native-linux-arm64-gnu": "1.16.1",
128
- "@ata-validator/native-linux-arm64-musl": "1.16.1",
129
- "@ata-validator/native-linux-x64-gnu": "1.16.1",
130
- "@ata-validator/native-linux-x64-musl": "1.16.1",
131
- "@ata-validator/native-win32-x64": "1.16.1"
125
+ "@ata-validator/native-darwin-arm64": "1.17.0",
126
+ "@ata-validator/native-darwin-x64": "1.17.0",
127
+ "@ata-validator/native-linux-arm64-gnu": "1.17.0",
128
+ "@ata-validator/native-linux-arm64-musl": "1.17.0",
129
+ "@ata-validator/native-linux-x64-gnu": "1.17.0",
130
+ "@ata-validator/native-linux-x64-musl": "1.17.0",
131
+ "@ata-validator/native-win32-x64": "1.17.0"
132
132
  },
133
133
  "peerDependencies": {
134
134
  "yaml": "^2.0.0"