ata-validator 1.27.1 → 1.29.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 +6 -0
- package/build.d.ts +4 -2
- package/index.d.ts +12 -1
- package/index.js +151 -80
- package/lib/aot-impl.js +15 -8
- package/lib/data-positions.js +84 -48
- package/lib/ts-gen.js +5 -2
- package/lib/version.js +1 -1
- package/package.json +9 -10
- package/CHANGELOG.md +0 -740
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/ts-gen.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const ATA_VERSION = require('./version');
|
|
4
|
+
|
|
3
5
|
// Schema -> TypeScript type declaration.
|
|
4
6
|
// Emits an interface or type alias for each top-level schema, plus
|
|
5
7
|
// `isValid` (type predicate) and `validate` signatures.
|
|
@@ -215,7 +217,7 @@ function toTypeScript(schema, opts) {
|
|
|
215
217
|
? `${rootDoc}export interface ${rootName} ${rootType}`
|
|
216
218
|
: `${rootDoc}export type ${rootName} = ${rootType};`;
|
|
217
219
|
|
|
218
|
-
return `// Auto-generated by ata-validator
|
|
220
|
+
return `// Auto-generated by ata-validator ${ATA_VERSION}, do not edit.
|
|
219
221
|
${defLines.length ? defLines.join('\n\n') + '\n\n' : ''}${rootDecl}
|
|
220
222
|
|
|
221
223
|
export interface ValidationError {
|
|
@@ -239,7 +241,8 @@ export type Result = ValidResult | InvalidResult;
|
|
|
239
241
|
export declare function isValid(data: unknown): data is ${rootName};
|
|
240
242
|
export declare function validate(data: unknown): Result;
|
|
241
243
|
export declare const schemaHash: string;
|
|
242
|
-
declare const
|
|
244
|
+
export declare const ataVersion: string;
|
|
245
|
+
declare const _default: { validate: typeof validate; isValid: typeof isValid; schemaHash: typeof schemaHash; ataVersion: typeof ataVersion };
|
|
243
246
|
export default _default;
|
|
244
247
|
`;
|
|
245
248
|
}
|
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.29.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_json_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_aot_staleness.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",
|
|
@@ -118,17 +118,16 @@
|
|
|
118
118
|
"t.d.ts",
|
|
119
119
|
"bin/",
|
|
120
120
|
"README.md",
|
|
121
|
-
"CHANGELOG.md",
|
|
122
121
|
"LICENSE"
|
|
123
122
|
],
|
|
124
123
|
"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.
|
|
124
|
+
"@ata-validator/native-darwin-arm64": "1.29.0",
|
|
125
|
+
"@ata-validator/native-darwin-x64": "1.29.0",
|
|
126
|
+
"@ata-validator/native-linux-arm64-gnu": "1.29.0",
|
|
127
|
+
"@ata-validator/native-linux-arm64-musl": "1.29.0",
|
|
128
|
+
"@ata-validator/native-linux-x64-gnu": "1.29.0",
|
|
129
|
+
"@ata-validator/native-linux-x64-musl": "1.29.0",
|
|
130
|
+
"@ata-validator/native-win32-x64": "1.29.0"
|
|
132
131
|
},
|
|
133
132
|
"peerDependencies": {
|
|
134
133
|
"yaml": "^2.0.0"
|