ata-validator 1.52.0 → 1.54.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/README.md +7 -0
- package/compat.js +325 -29
- package/lib/codegen-engine.js +2 -1
- package/lib/compat-errors.js +131 -17
- package/lib/dialect.js +36 -1
- package/lib/draft7.js +80 -61
- package/lib/enrich-site.js +29 -2
- package/lib/error-runtime.js +6 -2
- package/lib/formats-source.js +43 -66
- package/lib/formats.js +37 -231
- package/lib/interpreter-compat.js +144 -0
- package/lib/interpreter-core.js +204 -17
- package/lib/js-compiler-errors.js +52 -16
- package/lib/js-compiler.js +540 -66
- package/lib/keywords.js +24 -1
- package/lib/levenshtein.js +21 -5
- package/lib/metaschemas.js +5 -3
- package/lib/plan-compiler.js +28 -6
- package/lib/regex-linear.js +81 -1
- package/lib/safe-regex.js +14 -11
- package/lib/schema-scan.js +20 -1
- package/lib/tier0.js +1 -0
- package/lib/unique-items.js +16 -5
- package/lib/uri-core.js +155 -0
- package/lib/validator-core.js +118 -23
- package/lib/version.js +1 -1
- package/package.json +9 -9
package/lib/keywords.js
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
// { macro(value, parent) -> schema } the returned schema is applied in
|
|
11
11
|
// place, and the keyword reports an
|
|
12
12
|
// error of its own when it fails
|
|
13
|
+
// with optional `dataContext: true`: the per-value function is also given
|
|
14
|
+
// `{ instancePath, parentData, parentDataProperty, rootData }`, as the default
|
|
15
|
+
// validator's keywords are, so it can read or change the value where it sits
|
|
16
|
+
// (validate(value, data, parent, ctx), or the compiled fn(data, ctx)). Such a
|
|
17
|
+
// schema runs on the interpreted engine's collecting walk, which knows where
|
|
18
|
+
// every value is.
|
|
13
19
|
// with optional `type`: a JSON Schema type name or a list of them. A typed
|
|
14
20
|
// keyword is skipped for data of any other type, which is what makes
|
|
15
21
|
// `{ type: 'number', ... }` safe next to `type: ['number', 'string']`.
|
|
@@ -72,6 +78,12 @@ function normalizeKeywords(defs) {
|
|
|
72
78
|
validate: hasValidate ? def.validate : null,
|
|
73
79
|
compile: hasCompile ? def.compile : null,
|
|
74
80
|
macro: hasMacro ? def.macro : null,
|
|
81
|
+
dataContext: def.dataContext === true,
|
|
82
|
+
// Order among the custom keywords of one node, as the default
|
|
83
|
+
// validator's keywords declare it: `before` names a keyword this one
|
|
84
|
+
// runs ahead of, `post` runs it after the others.
|
|
85
|
+
before: typeof def.before === 'string' ? def.before : null,
|
|
86
|
+
post: def.post === true,
|
|
75
87
|
};
|
|
76
88
|
}
|
|
77
89
|
return out;
|
|
@@ -110,4 +122,15 @@ const NAME_MAPS = new Set([
|
|
|
110
122
|
'dependentSchemas', 'dependentRequired', 'dependencies', 'propertyDependencies',
|
|
111
123
|
]);
|
|
112
124
|
|
|
113
|
-
|
|
125
|
+
// Does the schema use a registered keyword that asks for its data's context?
|
|
126
|
+
function schemaUsesDataContext(schema, keywords) {
|
|
127
|
+
if (!keywords) return false;
|
|
128
|
+
let any = false;
|
|
129
|
+
for (const name of Object.keys(keywords)) if (keywords[name].dataContext) { any = true; break; }
|
|
130
|
+
if (!any) return false;
|
|
131
|
+
const only = Object.create(null);
|
|
132
|
+
for (const name of Object.keys(keywords)) if (keywords[name].dataContext) only[name] = keywords[name];
|
|
133
|
+
return schemaUsesKeywords(schema, only);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = { normalizeKeywords, schemaUsesKeywords, schemaUsesDataContext };
|
package/lib/levenshtein.js
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// Bounded
|
|
3
|
+
// Bounded edit distance. Returns Infinity if distance > maxDistance (or, past
|
|
4
4
|
// the bound, possibly some number greater than it; callers compare).
|
|
5
5
|
//
|
|
6
|
+
// Two adjacent characters swapped count as one edit, not two (the optimal
|
|
7
|
+
// string alignment distance): `nmae` for `name` is the commonest typo there
|
|
8
|
+
// is, and at two edits a four-letter name's budget of one turned it away.
|
|
9
|
+
//
|
|
6
10
|
// Only the cells within the bound of the diagonal are computed: a path
|
|
7
11
|
// through any other cell already costs more than the bound. A typo hint asks
|
|
8
12
|
// with a bound of one or two and compares the missing name with every key
|
|
9
13
|
// present, so a row is five cells instead of the whole key. Without a bound
|
|
10
14
|
// the band is the whole row.
|
|
11
15
|
//
|
|
12
|
-
//
|
|
16
|
+
// Three rows of scratch, reused across calls. The function is not recursive
|
|
13
17
|
// and the library is single-threaded, so nothing else is using them; growing
|
|
14
18
|
// them once beats allocating two arrays on every comparison, which the
|
|
15
19
|
// reject-path profile showed as most of this function's cost.
|
|
16
20
|
let scratchA = new Int32Array(64);
|
|
17
21
|
let scratchB = new Int32Array(64);
|
|
22
|
+
let scratchC = new Int32Array(64);
|
|
18
23
|
|
|
19
24
|
function levenshtein (a, b, maxDistance) {
|
|
20
25
|
if (a === b) return 0;
|
|
@@ -28,7 +33,11 @@ function levenshtein (a, b, maxDistance) {
|
|
|
28
33
|
if (scratchA.length < m + 2) {
|
|
29
34
|
scratchA = new Int32Array(m + 2);
|
|
30
35
|
scratchB = new Int32Array(m + 2);
|
|
36
|
+
scratchC = new Int32Array(m + 2);
|
|
31
37
|
}
|
|
38
|
+
// The row before the previous one, read for a swap: within the band of
|
|
39
|
+
// row i the cell two back on the diagonal is inside the band of row i - 2.
|
|
40
|
+
let prev2 = scratchC;
|
|
32
41
|
let prev = scratchA;
|
|
33
42
|
let curr = scratchB;
|
|
34
43
|
for (let j = 0; j <= m; j++) prev[j] = j <= max ? j : big;
|
|
@@ -40,20 +49,27 @@ function levenshtein (a, b, maxDistance) {
|
|
|
40
49
|
// charCodeAt rather than indexing: reading a character by index allocates
|
|
41
50
|
// a one-character string, and this is the innermost loop.
|
|
42
51
|
const ca = a.charCodeAt(i - 1);
|
|
52
|
+
const pa = i > 1 ? a.charCodeAt(i - 2) : -1;
|
|
43
53
|
for (let j = lo; j <= hi; j++) {
|
|
44
|
-
|
|
54
|
+
const cb = b.charCodeAt(j - 1);
|
|
55
|
+
let v = prev[j - 1] + (ca === cb ? 0 : 1);
|
|
45
56
|
const del = curr[j - 1] + 1;
|
|
46
57
|
if (del < v) v = del;
|
|
47
58
|
const ins = prev[j] + 1;
|
|
48
59
|
if (ins < v) v = ins;
|
|
60
|
+
if (j > 1 && ca !== cb && ca === b.charCodeAt(j - 2) && pa === cb) {
|
|
61
|
+
const swap = prev2[j - 2] + 1;
|
|
62
|
+
if (swap < v) v = swap;
|
|
63
|
+
}
|
|
49
64
|
if (v > big) v = big;
|
|
50
65
|
curr[j] = v;
|
|
51
66
|
if (v < rowMin) rowMin = v;
|
|
52
67
|
}
|
|
53
68
|
if (hi < m) curr[hi + 1] = big;
|
|
54
69
|
if (rowMin > max) return Infinity;
|
|
55
|
-
// A destructured swap builds an array per row;
|
|
56
|
-
const t =
|
|
70
|
+
// A destructured swap builds an array per row; temporaries do not.
|
|
71
|
+
const t = prev2;
|
|
72
|
+
prev2 = prev;
|
|
57
73
|
prev = curr;
|
|
58
74
|
curr = t;
|
|
59
75
|
}
|
package/lib/metaschemas.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
// The official meta-schemas, vendored so a `$ref` to one of them resolves
|
|
4
4
|
// without a network. Draft 2020-12 is eight documents joined by $dynamicRef;
|
|
5
|
-
// draft-07 and draft-
|
|
5
|
+
// draft-07, draft-06 and draft-04 are one each; 2019-09 is seven. Sources:
|
|
6
6
|
// https://json-schema.org/draft/2020-12/schema and
|
|
7
|
-
// http://json-schema.org/draft-07/schema, fetched 2026-08-23,
|
|
7
|
+
// http://json-schema.org/draft-07/schema, fetched 2026-08-23,
|
|
8
8
|
// http://json-schema.org/draft-06/schema and
|
|
9
|
-
// https://json-schema.org/draft/2019-09/schema, fetched 2026-10-10,
|
|
9
|
+
// https://json-schema.org/draft/2019-09/schema, fetched 2026-10-10, and
|
|
10
|
+
// http://json-schema.org/draft-04/schema, fetched 2026-10-14, unmodified.
|
|
10
11
|
// The 2019-09 documents are read through the same 2019-09 rewrite as a
|
|
11
12
|
// caller's schema (lib/draft7.js) once, at load, since they use
|
|
12
13
|
// `$recursiveRef`, which the engines read as `$dynamicRef`.
|
|
@@ -22,6 +23,7 @@ const METASCHEMAS = new Map([
|
|
|
22
23
|
["https://json-schema.org/draft/2020-12/meta/content", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/content","$dynamicAnchor":"meta","title":"Content vocabulary meta-schema","type":["object","boolean"],"properties":{"contentEncoding":{"type":"string"},"contentMediaType":{"type":"string"},"contentSchema":{"$dynamicRef":"#meta"}}}],
|
|
23
24
|
["https://json-schema.org/draft/2020-12/meta/unevaluated", {"$schema":"https://json-schema.org/draft/2020-12/schema","$id":"https://json-schema.org/draft/2020-12/meta/unevaluated","$dynamicAnchor":"meta","title":"Unevaluated applicator vocabulary meta-schema","type":["object","boolean"],"properties":{"unevaluatedItems":{"$dynamicRef":"#meta"},"unevaluatedProperties":{"$dynamicRef":"#meta"}}}],
|
|
24
25
|
["http://json-schema.org/draft-07/schema#", {"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"writeOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}],
|
|
26
|
+
["http://json-schema.org/draft-04/schema#", {"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}],
|
|
25
27
|
["http://json-schema.org/draft-06/schema#", {"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}],
|
|
26
28
|
["https://json-schema.org/draft/2019-09/schema", {"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/schema","$vocabulary":{"https://json-schema.org/draft/2019-09/vocab/core":true,"https://json-schema.org/draft/2019-09/vocab/applicator":true,"https://json-schema.org/draft/2019-09/vocab/validation":true,"https://json-schema.org/draft/2019-09/vocab/meta-data":true,"https://json-schema.org/draft/2019-09/vocab/format":false,"https://json-schema.org/draft/2019-09/vocab/content":true},"$recursiveAnchor":true,"title":"Core and Validation specifications meta-schema","allOf":[{"$ref":"meta/core"},{"$ref":"meta/applicator"},{"$ref":"meta/validation"},{"$ref":"meta/meta-data"},{"$ref":"meta/format"},{"$ref":"meta/content"}],"type":["object","boolean"],"properties":{"definitions":{"$comment":"While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.","type":"object","additionalProperties":{"$recursiveRef":"#"},"default":{}},"dependencies":{"$comment":"\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"","type":"object","additionalProperties":{"anyOf":[{"$recursiveRef":"#"},{"$ref":"meta/validation#/$defs/stringArray"}]}}}}],
|
|
27
29
|
["https://json-schema.org/draft/2019-09/meta/core", {"$schema":"https://json-schema.org/draft/2019-09/schema","$id":"https://json-schema.org/draft/2019-09/meta/core","$recursiveAnchor":true,"title":"Core vocabulary meta-schema","type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference","$comment":"Non-empty fragments not allowed.","pattern":"^[^#]*#?$"},"$schema":{"type":"string","format":"uri"},"$anchor":{"type":"string","pattern":"^[A-Za-z][-A-Za-z0-9.:_]*$"},"$ref":{"type":"string","format":"uri-reference"},"$recursiveRef":{"type":"string","format":"uri-reference"},"$recursiveAnchor":{"type":"boolean","default":false},"$vocabulary":{"type":"object","propertyNames":{"type":"string","format":"uri"},"additionalProperties":{"type":"boolean"}},"$comment":{"type":"string"},"$defs":{"type":"object","additionalProperties":{"$recursiveRef":"#"},"default":{}}}}],
|
package/lib/plan-compiler.js
CHANGED
|
@@ -213,11 +213,18 @@ function install(deps) {
|
|
|
213
213
|
const objs = [];
|
|
214
214
|
if (P.required !== null) {
|
|
215
215
|
const req = P.required;
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
// A required key holding undefined is missing; for a declared
|
|
217
|
+
// property the property step finds it (requiredInProps).
|
|
218
|
+
const undef = P.requiredUndef;
|
|
219
|
+
if (req.length === 1) { const k = req[0]; objs.push(undef !== null && undef[0] ? (d) => Object.hasOwn(d, k) && d[k] !== undefined : (d) => Object.hasOwn(d, k)); }
|
|
220
|
+
else if (undef === null) objs.push((d) => {
|
|
218
221
|
for (let i = 0; i < req.length; i++) if (!Object.hasOwn(d, req[i])) return false;
|
|
219
222
|
return true;
|
|
220
223
|
});
|
|
224
|
+
else objs.push((d) => {
|
|
225
|
+
for (let i = 0; i < req.length; i++) if (!Object.hasOwn(d, req[i]) || (undef[i] && d[req[i]] === undefined)) return false;
|
|
226
|
+
return true;
|
|
227
|
+
});
|
|
221
228
|
}
|
|
222
229
|
if (P.minProperties !== undefined) { const m = P.minProperties; objs.push((d) => Object.keys(d).length >= m); }
|
|
223
230
|
if (P.maxProperties !== undefined) { const m = P.maxProperties; objs.push((d) => Object.keys(d).length <= m); }
|
|
@@ -490,8 +497,10 @@ function install(deps) {
|
|
|
490
497
|
// Declared properties: a linear scan over a short list beats a Map
|
|
491
498
|
// lookup, and most schemas declare a handful.
|
|
492
499
|
const propKeys = props !== null ? [...props.keys()] : null;
|
|
500
|
+
// req: the key is also required, so holding undefined it is missing.
|
|
501
|
+
const reqIn = P.requiredInProps;
|
|
493
502
|
const propList = props !== null
|
|
494
|
-
? [...props
|
|
503
|
+
? [...props].map(([key, entry]) => ({ fn: child(entry.node), seg: entry.seg, schemaSeg: entry.schemaSeg, req: reqIn !== null && reqIn.has(key) }))
|
|
495
504
|
: null;
|
|
496
505
|
const propMap = props !== null && props.size > 8 ? new Map(propKeys.map((k, i) => [k, propList[i]])) : null;
|
|
497
506
|
const lookup = propMap !== null
|
|
@@ -532,10 +541,19 @@ function install(deps) {
|
|
|
532
541
|
const key = keys[k];
|
|
533
542
|
let evaluated = false;
|
|
534
543
|
const prop = lookup !== null ? lookup(key) : undefined;
|
|
544
|
+
// A declared property whose value is undefined is not checked (see
|
|
545
|
+
// the interpreter's eval); required, it is missing.
|
|
535
546
|
if (prop !== undefined) {
|
|
536
|
-
|
|
547
|
+
const value = data[key];
|
|
548
|
+
if (value !== undefined) {
|
|
549
|
+
if (!((prop.fn.leaf && prop.fn.v(value, stack)) || prop.fn.c(value, errors, instancePath + prop.seg, schemaPath + prop.schemaSeg, stack))) {
|
|
550
|
+
ok = false;
|
|
551
|
+
if (errors === NOERRORS) return false;
|
|
552
|
+
}
|
|
553
|
+
} else if (prop.req) {
|
|
537
554
|
ok = false;
|
|
538
555
|
if (errors === NOERRORS) return false;
|
|
556
|
+
errors.push(err('required', 'required', instancePath, schemaPath + '/required', { missingProperty: key }, `must have required property '${key}'`));
|
|
539
557
|
}
|
|
540
558
|
evaluated = true;
|
|
541
559
|
}
|
|
@@ -578,7 +596,9 @@ function install(deps) {
|
|
|
578
596
|
for (let i = 0; i < n; i++) {
|
|
579
597
|
const key = propKeys[i];
|
|
580
598
|
if (!Object.hasOwn(data, key)) continue;
|
|
581
|
-
|
|
599
|
+
const value = data[key];
|
|
600
|
+
if (value !== undefined) { if (!propList[i].fn.v(value, stack)) return false; }
|
|
601
|
+
else if (propList[i].req) return false;
|
|
582
602
|
if (collect) addProp(rec, key);
|
|
583
603
|
}
|
|
584
604
|
return true;
|
|
@@ -594,7 +614,9 @@ function install(deps) {
|
|
|
594
614
|
let evaluated = false;
|
|
595
615
|
const prop = lookup !== null ? lookup(key) : undefined;
|
|
596
616
|
if (prop !== undefined) {
|
|
597
|
-
|
|
617
|
+
const value = data[key];
|
|
618
|
+
if (value !== undefined) { if (!prop.fn.v(value, stack)) return false; }
|
|
619
|
+
else if (prop.req) return false;
|
|
598
620
|
evaluated = true;
|
|
599
621
|
}
|
|
600
622
|
if (patterns !== null) {
|
package/lib/regex-linear.js
CHANGED
|
@@ -210,6 +210,86 @@ function deterministicRule (ast) {
|
|
|
210
210
|
return unbounded === 0 || anchored(ast)
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
// Two more shapes the rules above decline, both anchored with `^` and `$`
|
|
214
|
+
// around one top-level sequence.
|
|
215
|
+
//
|
|
216
|
+
// One choice: characters and classes, each repeated a fixed or bounded number
|
|
217
|
+
// of times, with only one of the repeats able to vary, by at most 256
|
|
218
|
+
// (`^[a-z0-9_-]{1,128}$`).
|
|
219
|
+
// The engine backtracks through that one repeat and nowhere else, at most its
|
|
220
|
+
// width per attempt, and the anchor allows one attempt.
|
|
221
|
+
//
|
|
222
|
+
// A delimited loop: `^P(Xd)*Q$` or with `+`, where d is one character or
|
|
223
|
+
// class, X and Q match nothing d matches (Q may end with d, or an optional
|
|
224
|
+
// d), and P holds no unbounded quantifier. Dotted identifiers and paths are
|
|
225
|
+
// written so: `^([A-Za-z_$][\w$]*\.)*[A-Za-z_$][\w$]*$`, `^/?([^/]+/)*[^/]+/?$`.
|
|
226
|
+
// Every iteration and Q's match end at a d or at the end, so each wrong
|
|
227
|
+
// choice between another iteration and Q fails within one segment, and the
|
|
228
|
+
// segments together are the input once. X and Q each hold at most one
|
|
229
|
+
// unbounded quantifier, over a character or class, so a segment is not split
|
|
230
|
+
// two ways either.
|
|
231
|
+
function sequenceOf (ast) {
|
|
232
|
+
if (ast.t !== 'concat') return null
|
|
233
|
+
const parts = ast.parts
|
|
234
|
+
if (parts.length < 3 || parts[0].t !== 'bol' || parts[parts.length - 1].t !== 'eol') return null
|
|
235
|
+
return parts.slice(1, -1)
|
|
236
|
+
}
|
|
237
|
+
const repeatOfAtom = (n) => (n.t === 'star' || n.t === 'plus' || n.t === 'quest' || n.t === 'repeat') && atom(n.child)
|
|
238
|
+
const unboundedNode = (n) => n.t === 'star' || n.t === 'plus' || (n.t === 'repeat' && n.max === Infinity)
|
|
239
|
+
|
|
240
|
+
function oneChoiceRule (ast) {
|
|
241
|
+
const seq = sequenceOf(ast)
|
|
242
|
+
if (seq === null) return false
|
|
243
|
+
let varying = 0
|
|
244
|
+
for (const n of seq) {
|
|
245
|
+
if (atom(n)) continue
|
|
246
|
+
if (n.t === 'repeat' && atom(n.child) && n.max !== Infinity) {
|
|
247
|
+
if (n.max > 256) return false
|
|
248
|
+
if (n.max > n.min) varying++
|
|
249
|
+
continue
|
|
250
|
+
}
|
|
251
|
+
return false
|
|
252
|
+
}
|
|
253
|
+
return varying <= 1
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function delimitedLoopRule (ast) {
|
|
257
|
+
const seq = sequenceOf(ast)
|
|
258
|
+
if (seq === null) return false
|
|
259
|
+
const loopAt = seq.findIndex((n) => unboundedNode(n) && !atom(n.child))
|
|
260
|
+
if (loopAt < 0) return false
|
|
261
|
+
let body = seq[loopAt].child
|
|
262
|
+
while (body.t === 'group') body = body.child
|
|
263
|
+
if (body.t !== 'concat' || body.parts.length < 2) return false
|
|
264
|
+
const d = body.parts[body.parts.length - 1]
|
|
265
|
+
if (!atom(d)) return false
|
|
266
|
+
const D = charSet(d)
|
|
267
|
+
// A run of characters, classes and their repeats that matches nothing in
|
|
268
|
+
// D, with at most one unbounded quantifier.
|
|
269
|
+
const run = (nodes) => {
|
|
270
|
+
let unbounded = 0
|
|
271
|
+
for (const n of nodes) {
|
|
272
|
+
const a = atom(n) ? n : repeatOfAtom(n) ? n.child : null
|
|
273
|
+
if (a === null || overlap(charSet(a), D)) return false
|
|
274
|
+
if (unboundedNode(n)) unbounded++
|
|
275
|
+
if (n.t === 'repeat' && n.max !== Infinity && n.max - n.min > 64) return false
|
|
276
|
+
}
|
|
277
|
+
return unbounded <= 1
|
|
278
|
+
}
|
|
279
|
+
if (!run(body.parts.slice(0, -1))) return false
|
|
280
|
+
const prefix = seq.slice(0, loopAt)
|
|
281
|
+
if (prefix.some(hasUnbounded)) return false
|
|
282
|
+
const pb = simpleRule({ t: 'concat', parts: prefix })
|
|
283
|
+
if (!pb && prefix.length > 0) return false
|
|
284
|
+
let suffix = seq.slice(loopAt + 1)
|
|
285
|
+
const last = suffix[suffix.length - 1]
|
|
286
|
+
if (last !== undefined) {
|
|
287
|
+
const tail = atom(last) ? last : last.t === 'quest' && atom(last.child) ? last.child : null
|
|
288
|
+
if (tail !== null && !overlap(charSet(tail), { bits: D.bits.map((b) => b ^ 1), high: D.high ? 0 : 1 })) suffix = suffix.slice(0, -1)
|
|
289
|
+
}
|
|
290
|
+
return run(suffix)
|
|
291
|
+
}
|
|
292
|
+
|
|
213
293
|
function nativeIsLinear (src) {
|
|
214
294
|
if (typeof src !== 'string' || src.length > 512) return false
|
|
215
295
|
for (let i = 0; i < src.length; i++) {
|
|
@@ -225,7 +305,7 @@ function nativeIsLinear (src) {
|
|
|
225
305
|
}
|
|
226
306
|
let ast
|
|
227
307
|
try { ast = parse(src) } catch { return false }
|
|
228
|
-
return simpleRule(ast) || deterministicRule(ast)
|
|
308
|
+
return simpleRule(ast) || deterministicRule(ast) || oneChoiceRule(ast) || delimitedLoopRule(ast)
|
|
229
309
|
}
|
|
230
310
|
|
|
231
311
|
module.exports = { nativeIsLinear }
|
package/lib/safe-regex.js
CHANGED
|
@@ -473,25 +473,28 @@ function __ataSafeRegex () {
|
|
|
473
473
|
}
|
|
474
474
|
if (id < 0) return testNFA(s)
|
|
475
475
|
if (len === 0) return (flags[id] & 1) === 1
|
|
476
|
-
|
|
477
|
-
//
|
|
478
|
-
//
|
|
476
|
+
if ((flags[id] & 1) === 1) return true
|
|
477
|
+
// The last character, with the end flag, is stepped after the loop.
|
|
478
|
+
// Tables are locals, reread after `step` (which may grow them).
|
|
479
479
|
const last = len - 1
|
|
480
|
+
let T = trans
|
|
481
|
+
let F = flags
|
|
480
482
|
for (let pos = 0; pos < last; pos++) {
|
|
481
|
-
if ((flags[id] & 1) === 1) return true
|
|
482
483
|
const c = s.charCodeAt(pos)
|
|
483
|
-
let nid
|
|
484
|
-
if (
|
|
485
|
-
nid = trans[(id << 7) | c]
|
|
486
|
-
if (nid === -2) { nid = step(states[id], c, false); if (nid >= 0 || overflow) trans[(id << 7) | c] = nid }
|
|
487
|
-
} else {
|
|
484
|
+
let nid = c < 128 ? T[(id << 7) | c] : -2
|
|
485
|
+
if (nid === -2) {
|
|
488
486
|
nid = step(states[id], c, false)
|
|
487
|
+
T = trans; F = flags
|
|
488
|
+
if (c < 128 && (nid >= 0 || overflow)) T[(id << 7) | c] = nid
|
|
489
489
|
}
|
|
490
490
|
if (nid < 0) return testNFA(s)
|
|
491
491
|
id = nid
|
|
492
|
-
|
|
492
|
+
const f = F[id]
|
|
493
|
+
if (f !== 0) {
|
|
494
|
+
if ((f & 2) === 2) return false
|
|
495
|
+
return true
|
|
496
|
+
}
|
|
493
497
|
}
|
|
494
|
-
if ((flags[id] & 1) === 1) return true
|
|
495
498
|
const c = s.charCodeAt(last)
|
|
496
499
|
let nid
|
|
497
500
|
if (c < 128) {
|
package/lib/schema-scan.js
CHANGED
|
@@ -30,6 +30,11 @@ const TUPLE_ITEMS = 1 << 5; // array-valued `items`, split into `prefixItem
|
|
|
30
30
|
const EXCLUSIVE_BOOL = 1 << 6; // draft-04's boolean `exclusiveMinimum`/`exclusiveMaximum`
|
|
31
31
|
const ENCODED_REF = 1 << 7; // a fragment `$ref` holding a percent escape, decoded by normalizeNullable's walk
|
|
32
32
|
|
|
33
|
+
// Questions compat asks of a schema it is about to compile, read on the same
|
|
34
|
+
// walk so that a document is not walked again for them. compat sets the keys
|
|
35
|
+
// and their bits (setExtraKeys); without compat the walk reads none.
|
|
36
|
+
let EXTRA = null;
|
|
37
|
+
|
|
33
38
|
// Everything only draft-07 normalization acts on. A schema of another dialect
|
|
34
39
|
// can carry these without them meaning anything, so they are read together
|
|
35
40
|
// with whether the document is draft-07 at all.
|
|
@@ -53,7 +58,7 @@ const ANCHOR_ID_RE = /^#[A-Za-z][A-Za-z0-9_.:-]*$/;
|
|
|
53
58
|
// This assumes a schema is not mutated after being handed to a Validator,
|
|
54
59
|
// which is already true of everything else here: the compile cache, the
|
|
55
60
|
// identity cache and the schema map would all be stale too.
|
|
56
|
-
|
|
61
|
+
let CACHE = new WeakMap();
|
|
57
62
|
|
|
58
63
|
function scan(schema) {
|
|
59
64
|
if (typeof schema !== 'object' || schema === null) return 0;
|
|
@@ -92,6 +97,12 @@ function scan(schema) {
|
|
|
92
97
|
}
|
|
93
98
|
// Every key, not just the subschema keywords, so this cannot miss a place
|
|
94
99
|
// the normalizers would reach.
|
|
100
|
+
if (EXTRA !== null) {
|
|
101
|
+
for (let i = 0; i < keys.length; i++) {
|
|
102
|
+
const b = EXTRA.get(keys[i]);
|
|
103
|
+
if (b !== undefined) bits |= b;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
95
106
|
for (let i = 0; i < keys.length; i++) walk(node[keys[i]]);
|
|
96
107
|
};
|
|
97
108
|
|
|
@@ -125,3 +136,11 @@ module.exports = {
|
|
|
125
136
|
ENCODED_REF,
|
|
126
137
|
DRAFT7_WORK,
|
|
127
138
|
};
|
|
139
|
+
|
|
140
|
+
// A schema scanned before the keys were set is scanned again: what was
|
|
141
|
+
// remembered for it does not answer the new questions.
|
|
142
|
+
function setExtraKeys(map) {
|
|
143
|
+
EXTRA = map;
|
|
144
|
+
CACHE = new WeakMap();
|
|
145
|
+
}
|
|
146
|
+
Object.defineProperty(module.exports, '_setExtraKeys', { value: setExtraKeys, enumerable: false });
|
package/lib/tier0.js
CHANGED
|
@@ -173,6 +173,7 @@ function tier0ValidateObject(plan, data) {
|
|
|
173
173
|
// treated as absent, as the interpreted engine treats it.
|
|
174
174
|
if (v !== undefined && (c.protoName || (_PN ? data.__proto__ : Object.getPrototypeOf(data)) !== Object.prototype) && !_hop.call(data, c.key)) v = undefined;
|
|
175
175
|
if (v === undefined) {
|
|
176
|
+
// A required key holding undefined is missing, as in every engine.
|
|
176
177
|
if (reqMask & (1 << i)) return false;
|
|
177
178
|
continue;
|
|
178
179
|
}
|
package/lib/unique-items.js
CHANGED
|
@@ -22,17 +22,28 @@ function _deq(a, b) {
|
|
|
22
22
|
if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false;
|
|
23
23
|
var aa = Array.isArray(a);
|
|
24
24
|
if (aa !== Array.isArray(b)) return false;
|
|
25
|
-
var i;
|
|
25
|
+
var i, k, x, y;
|
|
26
26
|
if (aa) {
|
|
27
27
|
if (a.length !== b.length) return false;
|
|
28
|
-
for (i =
|
|
28
|
+
for (i = a.length; i-- !== 0;) if (!_deq(a[i], b[i])) return false;
|
|
29
29
|
return true;
|
|
30
30
|
}
|
|
31
31
|
var ka = Object.keys(a);
|
|
32
32
|
if (ka.length !== Object.keys(b).length) return false;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
// Keys and scalar values first, nested values after, from the last key back:
|
|
34
|
+
// two items of a list most often differ in a name, a path or an id, and
|
|
35
|
+
// walking a nested list first made each comparison of rust-project's crates
|
|
36
|
+
// three times what it needed (250 against 78 ns for the three; the default
|
|
37
|
+
// validator's deep equal takes 115).
|
|
38
|
+
for (i = ka.length; i-- !== 0;) {
|
|
39
|
+
k = ka[i];
|
|
40
|
+
if (!Object.prototype.hasOwnProperty.call(b, k)) return false;
|
|
41
|
+
x = a[k]; y = b[k];
|
|
42
|
+
if (x !== y && (x === null || y === null || typeof x !== 'object' || typeof y !== 'object')) return false;
|
|
43
|
+
}
|
|
44
|
+
for (i = ka.length; i-- !== 0;) {
|
|
45
|
+
k = ka[i]; x = a[k];
|
|
46
|
+
if (x !== null && typeof x === 'object' && !_deq(x, b[k])) return false;
|
|
36
47
|
}
|
|
37
48
|
return true;
|
|
38
49
|
}
|
package/lib/uri-core.js
ADDED
|
@@ -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 };
|