ata-validator 1.53.0 → 1.55.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.
@@ -0,0 +1,155 @@
1
+ 'use strict';
2
+
3
+ // RFC 3986 URI and URI-reference, RFC 3987 IRI and IRI-reference, as one walk
4
+ // over the string with no slicing. `mode` bit 1 asks for a scheme (uri, iri),
5
+ // bit 2 lets non-ASCII through (iri, iri-reference). The rules the walk holds
6
+ // that a character-class scan does not: a second "@" in the authority, a port
7
+ // that is not digits, square brackets anywhere but around an IP literal, the
8
+ // literal itself (RFC 3986 IPv6 with an embedded IPv4 of no leading zeros, an
9
+ // RFC 6874 zone id, IPvFuture), a colon in the first segment of a relative
10
+ // path, and a second "#". A reference made only of unreserved characters,
11
+ // sub-delimiters, "/" and "@" (a file name, a path) is one whatever its
12
+ // shape, and is answered by one scan before any of that.
13
+ //
14
+ // A factory, like lib/safe-regex.js: the interpreted engine calls the
15
+ // function it returns, and the code generator emits the factory's source
16
+ // text (`source`) into the program it builds, so a standalone module carries
17
+ // the same walk without importing it. Nothing inside the factory reads a
18
+ // free variable, and no comments inside it: its text is what gets emitted.
19
+ // `ip6` is the IPv6 check for a bracketed host, one string in: lib/formats.js
20
+ // gives its own and the generator emits ipv6Source, so neither carries a
21
+ // second copy. The slice it costs happens only on an IP literal.
22
+ function __ataUri (ip6) {
23
+ const C = new Uint8Array(128);
24
+ for (let i = 48; i < 58; i++) C[i] = 3;
25
+ for (let i = 65; i < 91; i++) C[i] = 3;
26
+ for (let i = 97; i < 123; i++) C[i] = 3;
27
+ C[43] = 3; C[45] = 3; C[46] = 3;
28
+ C[95] = 1; C[126] = 1;
29
+ C[33] = 1; C[36] = 1; C[38] = 1; C[39] = 1; C[40] = 1; C[41] = 1; C[42] = 1; C[44] = 1; C[59] = 1; C[61] = 1;
30
+ const H = new Uint8Array(128);
31
+ for (let i = 48; i < 58; i++) H[i] = 1;
32
+ for (let i = 65; i < 71; i++) H[i] = 1;
33
+ for (let i = 97; i < 103; i++) H[i] = 1;
34
+ function pct (s, i) {
35
+ const a = s.charCodeAt(i + 1), b = s.charCodeAt(i + 2);
36
+ return a < 128 && b < 128 && H[a] === 1 && H[b] === 1;
37
+ }
38
+ const P = new Uint8Array(128);
39
+ for (let i = 0; i < 128; i++) P[i] = C[i] & 1;
40
+ P[58] = 1; P[64] = 1; P[47] = 1;
41
+ const Q = new Uint8Array(P);
42
+ Q[63] = 1;
43
+ const S = new Uint8Array(P);
44
+ S[58] = 0;
45
+ function literal (s, from, to) {
46
+ if (from >= to) return false;
47
+ const f = s.charCodeAt(from);
48
+ if (f === 118 || f === 86) {
49
+ let i = from + 1, h = 0;
50
+ for (; i < to; i++) { const c = s.charCodeAt(i); if (c < 128 && H[c] === 1) h++; else break; }
51
+ if (h === 0 || s.charCodeAt(i) !== 46 || i + 1 >= to) return false;
52
+ for (i++; i < to; i++) { const c = s.charCodeAt(i); if (!(c < 128 && ((C[c] & 1) === 1 || c === 58))) return false; }
53
+ return true;
54
+ }
55
+ let z = -1;
56
+ for (let i = from; i < to; i++) if (s.charCodeAt(i) === 37) { z = i; break; }
57
+ if (z === -1) return ip6(s.slice(from, to));
58
+ if (s.charCodeAt(z + 1) !== 50 || s.charCodeAt(z + 2) !== 53 || z + 3 >= to) return false;
59
+ for (let i = z + 3; i < to; i++) {
60
+ const c = s.charCodeAt(i);
61
+ if (c === 37) { if (!pct(s, i)) return false; i += 2; continue; }
62
+ if (!(c < 128 && (C[c] & 1) === 1)) return false;
63
+ }
64
+ return ip6(s.slice(from, z));
65
+ }
66
+ return function (s, mode) {
67
+ const n = s.length;
68
+ const wide = (mode & 2) !== 0;
69
+ if ((mode & 1) === 0 && !(s.charCodeAt(0) === 47 && s.charCodeAt(1) === 47)) {
70
+ let k = 0;
71
+ for (; k < n; k++) { const c = s.charCodeAt(k); if (c > 127 || S[c] === 0) break; }
72
+ if (k === n) return true;
73
+ }
74
+ let i = 0, c = s.charCodeAt(0), scheme = false;
75
+ if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)) {
76
+ let j = 1;
77
+ while (j < n) { c = s.charCodeAt(j); if (c === 58 || c > 127 || (C[c] & 2) === 0) break; j++; }
78
+ if (j < n && c === 58) { scheme = true; i = j + 1; }
79
+ }
80
+ if (!scheme && (mode & 1) !== 0) return false;
81
+ let auth = false;
82
+ if (s.charCodeAt(i) === 47 && s.charCodeAt(i + 1) === 47) {
83
+ auth = true;
84
+ const st = i + 2;
85
+ let end = n, at = -1, br = false, brAt = false, colon = -1;
86
+ for (let k = st; k < n; k++) {
87
+ c = s.charCodeAt(k);
88
+ if (c === 47 || c === 63 || c === 35) { end = k; break; }
89
+ if (c < 128) {
90
+ if ((C[c] & 1) === 1) continue;
91
+ if (c === 37) { if (!pct(s, k)) return false; k += 2; continue; }
92
+ if (c === 58) { if (colon === -1) colon = k; continue; }
93
+ if (c === 64) { if (at !== -1) return false; at = k; brAt = br; colon = -1; continue; }
94
+ if (c === 91 || c === 93) { br = true; continue; }
95
+ return false;
96
+ }
97
+ if (!wide) return false;
98
+ }
99
+ if (brAt) return false;
100
+ const hs = at === -1 ? st : at + 1;
101
+ if (s.charCodeAt(hs) === 91) {
102
+ let close = -1;
103
+ for (let k = hs + 1; k < end; k++) if (s.charCodeAt(k) === 93) { close = k; break; }
104
+ if (close === -1 || !literal(s, hs + 1, close)) return false;
105
+ if (close + 1 < end) {
106
+ if (s.charCodeAt(close + 1) !== 58) return false;
107
+ for (let k = close + 2; k < end; k++) { c = s.charCodeAt(k); if (c < 48 || c > 57) return false; }
108
+ }
109
+ } else {
110
+ if (br) return false;
111
+ if (colon !== -1) for (let k = colon + 1; k < end; k++) { c = s.charCodeAt(k); if (c < 48 || c > 57) return false; }
112
+ }
113
+ i = end;
114
+ }
115
+ if (!scheme && !auth && s.charCodeAt(i) !== 47) {
116
+ for (; i < n; i++) {
117
+ c = s.charCodeAt(i);
118
+ if (c === 47 || c === 63 || c === 35) break;
119
+ if (c === 58) return false;
120
+ if (c === 37) { if (!pct(s, i)) return false; i += 2; continue; }
121
+ if (c < 128 ? P[c] === 0 : !wide) return false;
122
+ }
123
+ }
124
+ for (; i < n; i++) {
125
+ c = s.charCodeAt(i);
126
+ if (c < 128 ? P[c] === 0 : !wide) {
127
+ if (c === 63 || c === 35) break;
128
+ if (c === 37) { const a = s.charCodeAt(i + 1), b = s.charCodeAt(i + 2); if (!(a < 128 && b < 128 && H[a] === 1 && H[b] === 1)) return false; i += 2; continue; }
129
+ return false;
130
+ }
131
+ }
132
+ if (i >= n) return true;
133
+ if (c === 63) {
134
+ for (i++; i < n; i++) {
135
+ c = s.charCodeAt(i);
136
+ if (c < 128 ? Q[c] === 0 : !wide) {
137
+ if (c === 35) break;
138
+ if (c === 37) { if (!pct(s, i)) return false; i += 2; continue; }
139
+ return false;
140
+ }
141
+ }
142
+ if (i >= n) return true;
143
+ }
144
+ for (i++; i < n; i++) {
145
+ c = s.charCodeAt(i);
146
+ if (c < 128 ? Q[c] === 0 : !wide) {
147
+ if (c === 37) { if (!pct(s, i)) return false; i += 2; continue; }
148
+ return false;
149
+ }
150
+ }
151
+ return true;
152
+ };
153
+ }
154
+
155
+ module.exports = { __ataUri };
@@ -33,12 +33,13 @@ let _aotLoader = null;
33
33
  function _registerAot(load) {
34
34
  _aotLoader = load;
35
35
  }
36
- const { draftCode, normalizeDraft2019, normalizeDraft7, normalizeNullable, normalizeExclusiveBounds, stripFormatAssertions } = require("./draft7");
37
- const { enabledKeywords, stripDisabledKeywords } = require("./vocabularies");
36
+ // draft7.js, vocabularies.js, shape-classifier.js and tier0.js load where
37
+ // they are first used: a fresh process validating a 2020-12 schema runs none
38
+ // of their code, and reading them cost it about a tenth of what it loads.
39
+ const _draft7 = () => require("./draft7");
40
+ const _vocabularies = () => require("./vocabularies");
38
41
  const { needsNormalization } = require("./schema-scan");
39
- const { isV1Dialect } = require("./dialect");
40
- const { classify } = require("./shape-classifier");
41
- const { buildTier0Plan, tier0Validate } = require("./tier0");
42
+ const { isV1Dialect, draftCode } = require("./dialect");
42
43
 
43
44
  // The closure defaults pass. Only a validator without the generated
44
45
  // preprocess pass calls it, so it loads on that first call; loading it with
@@ -470,8 +471,9 @@ function _normalizeCallerSchema(s, inheritDraft7) {
470
471
  function _normalizeCallerSchemaUncached(s, inheritDraft7) {
471
472
  const declared = s && typeof s === 'object' ? s.$schema : undefined
472
473
  const code = declared !== undefined ? draftCode(declared) : (inheritDraft7 || 0)
473
- const needsDraft7 = code === 1 || code === 2
474
- const draft6 = code === 2
474
+ const needsDraft7 = code === 1 || code === 2 || code === 4
475
+ const draft4 = code === 4
476
+ const draft6 = code === 2 || draft4
475
477
  const draft2019 = code === 3
476
478
  // One walk answers whether there is anything to do. Almost always there is
477
479
  // not, and then the serialize, clone, normalize, serialize, compare below is
@@ -482,7 +484,8 @@ function _normalizeCallerSchemaUncached(s, inheritDraft7) {
482
484
  if (!draft6 && !draft2019 && !needsNormalization(s, needsDraft7)) return s
483
485
 
484
486
  const copy = _deepCloneWithSymbols(s)
485
- if (needsDraft7) normalizeDraft7(copy, true, draft6)
487
+ const { normalizeDraft7, normalizeDraft2019, normalizeNullable, normalizeExclusiveBounds } = _draft7()
488
+ if (needsDraft7) normalizeDraft7(copy, true, draft6, draft4)
486
489
  if (draft2019) normalizeDraft2019(copy, true)
487
490
  normalizeNullable(copy)
488
491
  normalizeExclusiveBounds(copy)
@@ -615,7 +618,11 @@ function _applyVocabularies(schemaObj, original, schemaMap) {
615
618
  if (!schemaObj || typeof schemaObj !== 'object') return schemaObj
616
619
  const declared = schemaObj.$schema
617
620
  if (typeof declared !== 'string') return schemaObj
618
- const enabled = enabledKeywords(schemaMap.get(declared))
621
+ // Only a meta-schema with a $vocabulary can disable a keyword.
622
+ const meta = schemaMap.get(declared)
623
+ if (!meta || typeof meta !== 'object' || !meta.$vocabulary || typeof meta.$vocabulary !== 'object') return schemaObj
624
+ const { enabledKeywords, stripDisabledKeywords } = _vocabularies()
625
+ const enabled = enabledKeywords(meta)
619
626
  if (!enabled) return schemaObj
620
627
  // `original` is the caller's own object when it reached here unchanged, and
621
628
  // that one is never mutated.
@@ -724,7 +731,7 @@ function _materializeSchema(self) {
724
731
  // Always on a copy: a normalized schema is shared by every validator built
725
732
  // from the same object (see _normalizeCallerSchema), so stripping in place
726
733
  // would take format checks away from the others.
727
- schemaObj = stripFormatAssertions(_deepCloneWithSymbols(schemaObj));
734
+ schemaObj = _draft7().stripFormatAssertions(_deepCloneWithSymbols(schemaObj));
728
735
  }
729
736
  // A keyword used only in a schema reached through $ref counts too: the
730
737
  // interpreted engine applies it there, and every path that does not know the
@@ -2395,8 +2402,10 @@ _defineLazyMethod('isValidObject', (self) => {
2395
2402
  return self.isValidObject(data);
2396
2403
  }
2397
2404
  // Lazy: classify + build tier 0 plan on first call, not in constructor.
2398
- const _tier = classify(self._schemaObj);
2405
+ const _tier = require("./shape-classifier").classify(self._schemaObj);
2399
2406
  if (_tier.tier === 0) {
2407
+ // Bound once here, so the verdict below reads a local, not the module.
2408
+ const { buildTier0Plan, tier0Validate } = require("./tier0");
2400
2409
  const _plan = buildTier0Plan(self._schemaObj);
2401
2410
  let _n = 0;
2402
2411
  _bindVerdict(self, (d) => {
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.53.0';
10
+ module.exports = '1.55.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.53.0",
3
+ "version": "1.55.0",
4
4
  "description": "JSON Schema validator that compiles to plain JavaScript, still runs where code generation is blocked, and can be compiled away at build time. Passes the full official test suite.",
5
5
  "type": "commonjs",
6
6
  "main": "index.js",
@@ -88,7 +88,7 @@
88
88
  "rebuild": "cmake-js rebuild --target ata",
89
89
  "test": "node tests/run.js",
90
90
  "bench:size": "node benchmark/bench_aot_size.mjs",
91
- "test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1 && node tests/run_suite.js draft6 && node tests/run_suite.js draft2019-09",
91
+ "test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1 && node tests/run_suite.js draft6 && node tests/run_suite.js draft2019-09 && node tests/run_suite.js draft4",
92
92
  "test:compat": "node tests/test_compat.js",
93
93
  "test:standard-schema": "node tests/test_standard_schema.js",
94
94
  "test:browser": "node tests/test_browser.js",
@@ -174,13 +174,13 @@
174
174
  "LICENSE"
175
175
  ],
176
176
  "optionalDependencies": {
177
- "@ata-validator/native-darwin-arm64": "1.53.0",
178
- "@ata-validator/native-darwin-x64": "1.53.0",
179
- "@ata-validator/native-linux-arm64-gnu": "1.53.0",
180
- "@ata-validator/native-linux-arm64-musl": "1.53.0",
181
- "@ata-validator/native-linux-x64-gnu": "1.53.0",
182
- "@ata-validator/native-linux-x64-musl": "1.53.0",
183
- "@ata-validator/native-win32-x64": "1.53.0"
177
+ "@ata-validator/native-darwin-arm64": "1.55.0",
178
+ "@ata-validator/native-darwin-x64": "1.55.0",
179
+ "@ata-validator/native-linux-arm64-gnu": "1.55.0",
180
+ "@ata-validator/native-linux-arm64-musl": "1.55.0",
181
+ "@ata-validator/native-linux-x64-gnu": "1.55.0",
182
+ "@ata-validator/native-linux-x64-musl": "1.55.0",
183
+ "@ata-validator/native-win32-x64": "1.55.0"
184
184
  },
185
185
  "peerDependencies": {
186
186
  "yaml": "^2.0.0"