ata-validator 1.27.1 → 1.28.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 +10 -0
- package/README.md +3 -0
- package/index.d.ts +12 -1
- package/index.js +28 -11
- package/lib/data-positions.js +84 -48
- package/lib/version.js +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
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.28.0 - 2026-09-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `engine: 'interpreter'`, a per-validator setting that keeps a schema off code generation: no `new Function`, no shared compile cache; the eval-free interpreted engine answers `validate()`, `isValidObject()` and `validateJSON()`. The default is the right trade for a schema the application wrote. A schema that arrives at runtime from a plugin or a tenant is input, and until now the only way to validate against one without executing source derived from it was the process-wide `ATA_FORCE_NAPI` switch. `engine()` reports `'interpreter'` for such a validator; any value other than `'auto'` or `'interpreter'` throws, so a misspelling cannot fall through to the generator. `tests/test_engine_option.js` holds the verdicts equal across engines and proves, with `Function` guarded, that the interpreter validator never builds a function from source while the default one does. Contributed by @d4tocchini in #43.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- The position map behind `dataFrame` is built without per-node work, which makes an invalid document cheaper to report on. It used to record an entry for every node in the document: a JSON pointer rebuilt from a path array with `concat`, `map` and `join`, a binary search and an object allocation for the value and another pair for its key, and a `JSON.parse` of every string value whose result was then discarded. String values are now spanned and not decoded, a key decodes only when its token holds an escape or a raw control character, the pointer is carried down the walk instead of being rebuilt, and line and column are resolved at the end for the nodes that were recorded. On a 132 KB config with three errors the map went from 2800 to about 1040 microseconds, which is 19.8x down to 7.3x the cost of `JSON.parse` on the same text, and the whole `validateJSON` call went from 3673 to 1825 microseconds. Output is unchanged: 112661 fuzzed documents, random and truncated and CRLF and BOM-prefixed and byte-punched, map identically against the previous walker, field order and throws included, so a document that declined to map still declines. Standalone modules built with `{ positions: true }` embed this walk, so they carry the same improvement once rebuilt. `tests/test_position_map_cost.js` gates it as a ratio to `JSON.parse` rather than as a time, because the cost is what regressed.
|
|
14
|
+
|
|
5
15
|
## 1.27.1 - 2026-09-17
|
|
6
16
|
|
|
7
17
|
### Fixed
|
package/README.md
CHANGED
|
@@ -445,11 +445,14 @@ const v = new Validator(schema, {
|
|
|
445
445
|
removeAdditional: true, // strip properties not in schema
|
|
446
446
|
schemas: [otherSchema], // cross-schema $ref registry
|
|
447
447
|
abortEarly: true, // skip detailed error collection on failure (~4x faster on invalid data)
|
|
448
|
+
engine: 'interpreter', // eval-free interpreted engine only: for a schema from outside the trust boundary
|
|
448
449
|
});
|
|
449
450
|
```
|
|
450
451
|
|
|
451
452
|
`abortEarly` returns a shared `{ valid: false, errors: [{ message: 'validation failed' }] }` on failure instead of running the detailed error collector. Useful when the caller only needs a pass/fail decision (Fastify route guards, high-throughput gatekeepers, request rejection at the edge).
|
|
452
453
|
|
|
454
|
+
`engine: 'interpreter'` keeps one validator off code generation: no `new Function`, no shared compile cache, the interpreted engine answers every call. The default turns a schema into JavaScript source, which is the right trade for a schema you wrote; a schema that arrives at runtime from a plugin or a tenant is input, and this option validates against it without ever executing anything derived from it. Same verdict, higher per-call cost; `ATA_FORCE_NAPI=1` does the same for a whole process.
|
|
455
|
+
|
|
453
456
|
### Build-time compile (`ata compile`)
|
|
454
457
|
|
|
455
458
|
The `ata` CLI turns a JSON Schema file into a self-contained JavaScript module. No runtime dependency on `ata-validator`, so only the generated validator ships to the browser. Typical output is about 4.5 KB gzipped for a ten-field schema, full error detail included, against 87 KB for the runtime bundled for the browser.
|
package/index.d.ts
CHANGED
|
@@ -425,6 +425,17 @@ export interface ValidatorOptions {
|
|
|
425
425
|
* v0.14 error shape.
|
|
426
426
|
*/
|
|
427
427
|
richErrors?: boolean;
|
|
428
|
+
/**
|
|
429
|
+
* Which engine may answer this validator. 'auto' (default) picks the fastest
|
|
430
|
+
* engine that handles the schema, generated JavaScript for most schemas.
|
|
431
|
+
* 'interpreter' keeps the schema off code generation entirely: no
|
|
432
|
+
* `new Function`, no shared compile cache; the eval-free interpreted engine
|
|
433
|
+
* answers `validate()`, `isValidObject()` and `validateJSON()`. For a schema
|
|
434
|
+
* that arrives from outside the trust boundary. The verdict is the same on
|
|
435
|
+
* every engine; the cost is not. The buffer APIs (`isValid`, `countValid`,
|
|
436
|
+
* `batchIsValid`) are native-only and unaffected.
|
|
437
|
+
*/
|
|
438
|
+
engine?: 'auto' | 'interpreter';
|
|
428
439
|
}
|
|
429
440
|
|
|
430
441
|
export interface BundleStandaloneOptions extends ValidatorOptions {
|
|
@@ -473,7 +484,7 @@ export interface Validator<T = unknown> {
|
|
|
473
484
|
* Which engine answers `validate()` for this schema: 'codegen' (generated
|
|
474
485
|
* JS), 'closure' (the closure compiler) or 'interpreter'; 'native' is
|
|
475
486
|
* reserved. The verdict is the same on every engine; the cost is not.
|
|
476
|
-
* A diagnostic
|
|
487
|
+
* A diagnostic; the `engine` option is the setting.
|
|
477
488
|
*/
|
|
478
489
|
engine(): 'codegen' | 'closure' | 'native' | 'interpreter';
|
|
479
490
|
|
package/index.js
CHANGED
|
@@ -896,6 +896,18 @@ class Validator {
|
|
|
896
896
|
this._rawIsCallers = typeof schema !== "string";
|
|
897
897
|
this._options = options;
|
|
898
898
|
this._noOpts = !opts;
|
|
899
|
+
// engine: 'interpreter' keeps this validator off code generation: no
|
|
900
|
+
// `new Function`, no shared compile cache, the eval-free interpreted
|
|
901
|
+
// engine answers validate(), isValidObject() and validateJSON(). For a
|
|
902
|
+
// schema that arrives from outside the trust boundary (a plugin's
|
|
903
|
+
// declared config shape, a tenant's upload), where turning it into source
|
|
904
|
+
// is not an acceptable execution model. ATA_FORCE_NAPI does this for the
|
|
905
|
+
// whole process; the option does it for one validator. A misspelling
|
|
906
|
+
// must not fall through to codegen, so anything else is refused.
|
|
907
|
+
if (options.engine !== undefined && options.engine !== 'auto' && options.engine !== 'interpreter') {
|
|
908
|
+
throw new TypeError("engine must be 'auto' or 'interpreter', got " + JSON.stringify(options.engine));
|
|
909
|
+
}
|
|
910
|
+
this._interpretOnly = options.engine === 'interpreter';
|
|
899
911
|
this._initialized = false;
|
|
900
912
|
this._nativeReady = false;
|
|
901
913
|
this._compiled = null;
|
|
@@ -1044,11 +1056,14 @@ class Validator {
|
|
|
1044
1056
|
// Check cache first -- reuse compiled functions for same schema
|
|
1045
1057
|
const sm = this._schemaMap.size > 0 ? this._schemaMap : null;
|
|
1046
1058
|
const mapKey = compileCacheKey(this._schemaStr, this._schemaMap);
|
|
1059
|
+
var _forceNapi = this._interpretOnly || (typeof process !== 'undefined' && process.env && process.env.ATA_FORCE_NAPI);
|
|
1047
1060
|
// Custom formats are JS functions: bypass the compile cache since they can
|
|
1048
|
-
// differ between validators that share the same schema string.
|
|
1049
|
-
|
|
1061
|
+
// differ between validators that share the same schema string. An
|
|
1062
|
+
// interpreter-only validator never touches it either way: a function a
|
|
1063
|
+
// trusted validator compiled for the same schema string must not answer
|
|
1064
|
+
// for it.
|
|
1065
|
+
const cached = (this._userFormats || this._usesKeywords || _forceNapi) ? null : _compileCache.get(mapKey);
|
|
1050
1066
|
let jsFn, jsCombinedFn, jsErrFn, _isCodegen = false;
|
|
1051
|
-
var _forceNapi = typeof process !== 'undefined' && process.env && process.env.ATA_FORCE_NAPI;
|
|
1052
1067
|
// v1 removes the bookending requirement for $dynamicRef. Only the
|
|
1053
1068
|
// interpreted engine implements that; the JS compiler and the native
|
|
1054
1069
|
// engine both resolve the 2020-12 way, so a v1 schema using the keyword
|
|
@@ -1063,15 +1078,16 @@ class Validator {
|
|
|
1063
1078
|
// either. The closure path does not call `new Function` itself, so it
|
|
1064
1079
|
// survives the block and would quietly handle schemas it gets wrong; the
|
|
1065
1080
|
// interpreted engine is both eval-free and more correct, so go straight
|
|
1066
|
-
// there.
|
|
1067
|
-
|
|
1081
|
+
// there. The forced case is decided before the probe: the probe is a
|
|
1082
|
+
// `new Function` too, and a validator that promised none must not run it.
|
|
1083
|
+
if (_forceNapi || this._v1Dynamic || this._usesKeywords || !codegenAvailable()) {
|
|
1068
1084
|
jsFn = null; jsCombinedFn = null; jsErrFn = null;
|
|
1069
1085
|
// `full` separates an entry that holds every compiled function from one
|
|
1070
1086
|
// the verdict-only fast path seeded, where `combined` and `errFn` are null
|
|
1071
1087
|
// because nothing has tried to build them yet. Both halves of that
|
|
1072
1088
|
// distinction are null, and reading the second as the first costs this
|
|
1073
1089
|
// schema its generated error function for the life of the process.
|
|
1074
|
-
} else if (cached && cached.jsFn !== undefined
|
|
1090
|
+
} else if (cached && cached.jsFn !== undefined) {
|
|
1075
1091
|
// `full` says the error and combined functions exist too. An entry
|
|
1076
1092
|
// without it still carries a verdict function worth reusing; the pair is
|
|
1077
1093
|
// built by _buildDeferred below if something asks for an error, and the
|
|
@@ -1084,7 +1100,7 @@ class Validator {
|
|
|
1084
1100
|
jsErrFn = cached.errFn;
|
|
1085
1101
|
_isCodegen = !!cached.isCodegen;
|
|
1086
1102
|
this._engine = _isCodegen ? 'codegen' : jsFn ? 'closure' : null;
|
|
1087
|
-
} else
|
|
1103
|
+
} else {
|
|
1088
1104
|
const uf = this._userFormats;
|
|
1089
1105
|
const _cgFn = compileToJSCodegen(schemaObj, sm, uf);
|
|
1090
1106
|
jsFn = _cgFn || compileToJS(schemaObj, null, sm);
|
|
@@ -1100,8 +1116,6 @@ class Validator {
|
|
|
1100
1116
|
if (!uf) {
|
|
1101
1117
|
_compileCache.set(mapKey, { jsFn, combined: undefined, errFn: undefined, isCodegen: _isCodegen, full: false });
|
|
1102
1118
|
}
|
|
1103
|
-
} else {
|
|
1104
|
-
jsFn = null; jsCombinedFn = null; jsErrFn = null;
|
|
1105
1119
|
}
|
|
1106
1120
|
this._jsFn = jsFn;
|
|
1107
1121
|
if (this._engine === undefined) this._engine = null;
|
|
@@ -1111,7 +1125,10 @@ class Validator {
|
|
|
1111
1125
|
// shape (e.g. Fastify `params: { $ref: 'shared#' }` or property refs like
|
|
1112
1126
|
// `{ id: { $ref: 'shared#/properties/id' } }`).
|
|
1113
1127
|
const preprocessSchema = resolveSchemaForPreprocess(schemaObj, this._schemaMap);
|
|
1114
|
-
|
|
1128
|
+
// The mutator pass (defaults, coercion, removal) is generated source too,
|
|
1129
|
+
// with the schema's `default` values embedded; an interpreter-only
|
|
1130
|
+
// validator takes the closure mutators instead.
|
|
1131
|
+
let preprocess = this._interpretOnly ? null : buildPreprocessCodegen(preprocessSchema, options);
|
|
1115
1132
|
if (!preprocess) {
|
|
1116
1133
|
const applyDefaults = options.useDefaults === false ? null : buildDefaultsApplier(preprocessSchema);
|
|
1117
1134
|
const applyCoerce = options.coerceTypes ? buildCoercer(preprocessSchema) : null;
|
|
@@ -1999,7 +2016,7 @@ class Validator {
|
|
|
1999
2016
|
return;
|
|
2000
2017
|
}
|
|
2001
2018
|
this._ensureVocabularies();
|
|
2002
|
-
if (typeof process !== 'undefined' && process.env && process.env.ATA_FORCE_NAPI) return;
|
|
2019
|
+
if (this._interpretOnly || (typeof process !== 'undefined' && process.env && process.env.ATA_FORCE_NAPI)) return;
|
|
2003
2020
|
if (!this._schemaStr) this._schemaStr = JSON.stringify(this._schemaObj);
|
|
2004
2021
|
const sm = this._schemaMap.size > 0 ? this._schemaMap : null;
|
|
2005
2022
|
const mapKey = compileCacheKey(this._schemaStr, this._schemaMap);
|
package/lib/data-positions.js
CHANGED
|
@@ -9,27 +9,22 @@
|
|
|
9
9
|
// Self-contained on purpose: `toStandaloneModule({ positions: true })` embeds
|
|
10
10
|
// this function verbatim via Function.prototype.toString, so it may not close
|
|
11
11
|
// over anything in this module and may not assume Node globals. The inlined
|
|
12
|
-
//
|
|
12
|
+
// pointer escaping below duplicates lib/source-positions.js for that reason.
|
|
13
13
|
function buildDataPositionMap (input) {
|
|
14
|
-
const escapePtr = (s) => s.replace(/~/g, '~0').replace(/\//g, '~1');
|
|
15
14
|
const text = (typeof Buffer !== 'undefined' && Buffer.isBuffer(input)) ? input.toString('utf8') : String(input);
|
|
16
15
|
const map = Object.create(null);
|
|
17
|
-
const
|
|
18
|
-
const lineStart = new Array(lines.length + 1);
|
|
19
|
-
lineStart[0] = 0;
|
|
20
|
-
for (let i = 0; i < lines.length; i++) lineStart[i + 1] = lineStart[i] + lines[i].length + 1;
|
|
16
|
+
const n = text.length;
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
// Offsets during the walk, line and column afterwards. Resolving them here
|
|
19
|
+
// cost a binary search and an object allocation for every node in the
|
|
20
|
+
// document, when only the nodes an error names are ever read.
|
|
21
|
+
const ptrs = [];
|
|
22
|
+
const starts = [];
|
|
23
|
+
const lens = [];
|
|
24
|
+
const keyStarts = [];
|
|
25
|
+
const keyLens = [];
|
|
30
26
|
|
|
31
27
|
let i = 0;
|
|
32
|
-
const n = text.length;
|
|
33
28
|
|
|
34
29
|
function skipWs () {
|
|
35
30
|
while (i < n) {
|
|
@@ -38,28 +33,40 @@ function buildDataPositionMap (input) {
|
|
|
38
33
|
}
|
|
39
34
|
}
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
// Span the string token, leaving `i` just past the closing quote. A plain
|
|
37
|
+
// token is sliced; one holding an escape or a raw control character goes
|
|
38
|
+
// through JSON.parse, which is what decodes `é` and what rejects a
|
|
39
|
+
// literal newline or a bad escape. Values are spanned and not decoded, but a
|
|
40
|
+
// malformed one still has to be rejected, so it is parsed for the throw.
|
|
41
|
+
//
|
|
42
|
+
// A token that does not open with a quote is not simple either. Object keys
|
|
43
|
+
// are read here unconditionally, so a document whose opening quote is missing
|
|
44
|
+
// (`{ mo": 1 }`) arrives with `m` under the cursor, and slicing it would map a
|
|
45
|
+
// key nobody wrote. Parsing the span rejects it instead.
|
|
46
|
+
function readString (decode) {
|
|
42
47
|
const start = i;
|
|
48
|
+
let simple = text.charCodeAt(i) === 0x22;
|
|
43
49
|
i++;
|
|
50
|
+
let closed = false;
|
|
44
51
|
while (i < n) {
|
|
45
52
|
const ch = text.charCodeAt(i);
|
|
46
|
-
if (ch === 0x5c) { i += 2; continue; }
|
|
47
|
-
if (ch === 0x22) { i++;
|
|
53
|
+
if (ch === 0x5c) { simple = false; i += 2; continue; }
|
|
54
|
+
if (ch === 0x22) { i++; closed = true; break; }
|
|
55
|
+
if (ch < 0x20) simple = false;
|
|
48
56
|
i++;
|
|
49
57
|
}
|
|
50
|
-
throw new Error('unterminated string at offset ' + start);
|
|
58
|
+
if (!closed) throw new Error('unterminated string at offset ' + start);
|
|
59
|
+
if (simple) return decode ? text.slice(start + 1, i - 1) : null;
|
|
60
|
+
const decoded = JSON.parse(text.slice(start, i));
|
|
61
|
+
return decode ? decoded : null;
|
|
51
62
|
}
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function walk (path, keySpan) {
|
|
64
|
+
// The pointer is carried down the walk. Rebuilding it per node from a path
|
|
65
|
+
// array cost an array copy, a map and a join for every node.
|
|
66
|
+
function walk (ptr, keyStart, keyLen) {
|
|
59
67
|
skipWs();
|
|
60
68
|
if (i >= n) return;
|
|
61
69
|
const start = i;
|
|
62
|
-
const pos = offsetToLineCol(start);
|
|
63
70
|
|
|
64
71
|
const ch = text.charCodeAt(i);
|
|
65
72
|
if (ch === 0x7b) {
|
|
@@ -76,19 +83,16 @@ function buildDataPositionMap (input) {
|
|
|
76
83
|
// Record the key token before consuming it. The caret for an error
|
|
77
84
|
// that names a property belongs on the property, not on the value and
|
|
78
85
|
// not on the enclosing object.
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
const span = {
|
|
83
|
-
keyOffset: keyStart,
|
|
84
|
-
keyLength: i - keyStart,
|
|
85
|
-
keyLine: keyPos.line,
|
|
86
|
-
keyCol: keyPos.col,
|
|
87
|
-
};
|
|
86
|
+
const memberKeyStart = i;
|
|
87
|
+
const key = readString(true);
|
|
88
|
+
const memberKeyLen = i - memberKeyStart;
|
|
88
89
|
skipWs();
|
|
89
90
|
if (text.charCodeAt(i) !== 0x3a) throw new Error('expected ":" at offset ' + i);
|
|
90
91
|
i++;
|
|
91
|
-
|
|
92
|
+
const seg = (key.indexOf('~') === -1 && key.indexOf('/') === -1)
|
|
93
|
+
? key
|
|
94
|
+
: key.replace(/~/g, '~0').replace(/\//g, '~1');
|
|
95
|
+
walk(ptr + '/' + seg, memberKeyStart, memberKeyLen);
|
|
92
96
|
}
|
|
93
97
|
} else if (ch === 0x5b) {
|
|
94
98
|
i++;
|
|
@@ -99,7 +103,7 @@ function buildDataPositionMap (input) {
|
|
|
99
103
|
if (text.charCodeAt(i) === 0x5d) { i++; break; }
|
|
100
104
|
if (text.charCodeAt(i) === 0x2c) { i++; continue; }
|
|
101
105
|
const before = i;
|
|
102
|
-
walk(
|
|
106
|
+
walk(ptr + '/' + idx, -1, 0);
|
|
103
107
|
// A character that begins no value at all, a stray `}` for instance,
|
|
104
108
|
// leaves the position where it was, and a loop that does not advance
|
|
105
109
|
// does not end. `validateJSON('[')` hung here on one byte.
|
|
@@ -107,7 +111,7 @@ function buildDataPositionMap (input) {
|
|
|
107
111
|
idx++;
|
|
108
112
|
}
|
|
109
113
|
} else if (ch === 0x22) {
|
|
110
|
-
readString();
|
|
114
|
+
readString(false);
|
|
111
115
|
} else {
|
|
112
116
|
while (i < n) {
|
|
113
117
|
const c = text.charCodeAt(i);
|
|
@@ -116,19 +120,51 @@ function buildDataPositionMap (input) {
|
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
entry.keyLine = keySpan.keyLine;
|
|
125
|
-
entry.keyCol = keySpan.keyCol;
|
|
126
|
-
}
|
|
127
|
-
map[pointerOf(path)] = entry;
|
|
123
|
+
ptrs.push(ptr);
|
|
124
|
+
starts.push(start);
|
|
125
|
+
lens.push(i - start);
|
|
126
|
+
keyStarts.push(keyStart);
|
|
127
|
+
keyLens.push(keyLen);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
if (text.charCodeAt(0) === 0xfeff) i = 1;
|
|
131
|
-
walk(
|
|
131
|
+
walk('', -1, 0);
|
|
132
|
+
|
|
133
|
+
if (ptrs.length === 0) return map;
|
|
134
|
+
|
|
135
|
+
const lines = text.split('\n');
|
|
136
|
+
const lineStart = new Array(lines.length + 1);
|
|
137
|
+
lineStart[0] = 0;
|
|
138
|
+
for (let k = 0; k < lines.length; k++) lineStart[k + 1] = lineStart[k] + lines[k].length + 1;
|
|
139
|
+
|
|
140
|
+
function lineOf (off) {
|
|
141
|
+
let lo = 0, hi = lineStart.length - 1;
|
|
142
|
+
while (lo < hi) {
|
|
143
|
+
const mid = (lo + hi + 1) >> 1;
|
|
144
|
+
if (lineStart[mid] <= off) lo = mid; else hi = mid - 1;
|
|
145
|
+
}
|
|
146
|
+
return lo;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (let k = 0; k < ptrs.length; k++) {
|
|
150
|
+
const off = starts[k];
|
|
151
|
+
const line = lineOf(off);
|
|
152
|
+
const entry = {
|
|
153
|
+
byteOffset: off,
|
|
154
|
+
length: lens[k],
|
|
155
|
+
line: line + 1,
|
|
156
|
+
col: off - lineStart[line] + 1,
|
|
157
|
+
text: lines[line] || '',
|
|
158
|
+
};
|
|
159
|
+
if (keyStarts[k] >= 0) {
|
|
160
|
+
const keyLine = lineOf(keyStarts[k]);
|
|
161
|
+
entry.keyOffset = keyStarts[k];
|
|
162
|
+
entry.keyLength = keyLens[k];
|
|
163
|
+
entry.keyLine = keyLine + 1;
|
|
164
|
+
entry.keyCol = keyStarts[k] - lineStart[keyLine] + 1;
|
|
165
|
+
}
|
|
166
|
+
map[ptrs[k]] = entry;
|
|
167
|
+
}
|
|
132
168
|
return map;
|
|
133
169
|
}
|
|
134
170
|
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ata-validator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "JSON Schema validation that compiles for speed and still runs where code generation is blocked. Compiled and interpreted engines answer identically at 100% of the official suite. TypeScript inference, Standard Schema V1, and a build step that emits dependency-free modules.",
|
|
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_scanner_differential.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_exclusive_bounds.js && node tests/test_engine_differential.js && node tests/test_error_shape_differential.js && node tests/test_output_format.js && node tests/test_retry_message.js && node tests/test_describe_schema.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_compile_cache_order.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_uri_helper_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_strict_schema.js && node tests/test_aot_external_checks.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_unevaluated_error_shape.js && node tests/test_pattern_properties_errors.js && node tests/test_additional_properties_scaling.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_rejection_shape.js && node tests/test_lazy_normalization.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_defaults_own_keys.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_malformed_json_termination.js && node tests/test_data_positions.js && node tests/test_file_positions.js && node tests/test_schema_hash.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_scanner_differential.js && node tests/test_buffer_reject_cost.js && node tests/test_nan_verdict.js && node tests/test_remove_additional_nested.js && node tests/test_exclusive_bounds.js && node tests/test_engine_differential.js && node tests/test_error_shape_differential.js && node tests/test_output_format.js && node tests/test_retry_message.js && node tests/test_describe_schema.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_option.js && node tests/test_compile_cache_order.js && node tests/test_engine_diagnostic.js && node tests/test_format_engine_parity.js && node tests/test_uri_helper_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_strict_schema.js && node tests/test_aot_external_checks.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_unevaluated_error_shape.js && node tests/test_pattern_properties_errors.js && node tests/test_additional_properties_scaling.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_rejection_shape.js && node tests/test_lazy_normalization.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_defaults_own_keys.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_malformed_json_termination.js && node tests/test_data_positions.js && node tests/test_position_map_cost.js && node tests/test_file_positions.js && node tests/test_schema_hash.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.
|
|
126
|
-
"@ata-validator/native-darwin-x64": "1.
|
|
127
|
-
"@ata-validator/native-linux-arm64-gnu": "1.
|
|
128
|
-
"@ata-validator/native-linux-arm64-musl": "1.
|
|
129
|
-
"@ata-validator/native-linux-x64-gnu": "1.
|
|
130
|
-
"@ata-validator/native-linux-x64-musl": "1.
|
|
131
|
-
"@ata-validator/native-win32-x64": "1.
|
|
125
|
+
"@ata-validator/native-darwin-arm64": "1.28.0",
|
|
126
|
+
"@ata-validator/native-darwin-x64": "1.28.0",
|
|
127
|
+
"@ata-validator/native-linux-arm64-gnu": "1.28.0",
|
|
128
|
+
"@ata-validator/native-linux-arm64-musl": "1.28.0",
|
|
129
|
+
"@ata-validator/native-linux-x64-gnu": "1.28.0",
|
|
130
|
+
"@ata-validator/native-linux-x64-musl": "1.28.0",
|
|
131
|
+
"@ata-validator/native-win32-x64": "1.28.0"
|
|
132
132
|
},
|
|
133
133
|
"peerDependencies": {
|
|
134
134
|
"yaml": "^2.0.0"
|