ata-validator 1.43.0 → 1.45.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.
@@ -604,8 +604,10 @@ function resolveSchemaForPreprocess(schema, schemaMap) {
604
604
  if (p && typeof p === 'object' && p.$ref && !p.type) {
605
605
  const t = resolveRefForPreprocess(p.$ref, schemaMap)
606
606
  if (t && typeof t === 'object') {
607
- if (!cloned) { cloned = Object.assign({}, s); cloned.properties = Object.assign({}, s.properties) }
608
- cloned.properties[key] = t
607
+ // Spread and defineProperty: a property named "__proto__" stays an own
608
+ // key of the copy (assignment would set the copy's prototype).
609
+ if (!cloned) { cloned = { ...s }; cloned.properties = { ...s.properties } }
610
+ Object.defineProperty(cloned.properties, key, { value: t, writable: true, enumerable: true, configurable: true })
609
611
  }
610
612
  }
611
613
  }
@@ -775,6 +777,7 @@ class Validator {
775
777
  // to attach dataFrame entries to each enriched error.
776
778
  this._posCache = null; // created by _pos() on first use, only the JSON text path needs it
777
779
  this._lastRawInput = null;
780
+ this._lastParsed = undefined;
778
781
  // undefined: not built yet. null: this schema has no scanner.
779
782
  this._scanner = undefined;
780
783
  // Checks a wrapper registered through _extendChecks. Declared here so
@@ -815,7 +818,7 @@ class Validator {
815
818
  }
816
819
 
817
820
  _pos() {
818
- return this._posCache || (this._posCache = require('./data-position-cache').createCache());
821
+ return this._posCache || (this._posCache = require('./data-position-cache').createCache(_codegen !== null && _codegen.nativePositions ? _codegen.nativePositions() : null));
819
822
  }
820
823
 
821
824
  _ensureVocabularies() {
@@ -847,7 +850,12 @@ class Validator {
847
850
  // "validate this schema against its dialect" needs no network and no
848
851
  // caller-supplied registry. Only schemas that mention json-schema.org in a
849
852
  // reference pay for the lookup.
850
- if (this._schemaStr.includes('json-schema.org/draft')) {
853
+ // A reference, not `$schema`: nearly every schema names its dialect, and
854
+ // matching that loaded the vendored meta-schemas into every validator's
855
+ // map, 27 entries that made its compile cache key a 30 KB string, rebuilt
856
+ // in 20 microseconds at each compile, and sent every compile through the
857
+ // external-document checks.
858
+ if (this._schemaStr.includes('json-schema.org/') && /"\$(?:ref|dynamicRef|recursiveRef)":"[^"]*json-schema\.org\//.test(this._schemaStr)) {
851
859
  const { METASCHEMAS } = require('./metaschemas');
852
860
  this._ownSchemaMap();
853
861
  for (const [id, meta] of METASCHEMAS) {
@@ -1104,6 +1112,17 @@ class Validator {
1104
1112
  _bindVerdict(this, this._fastVerdict
1105
1113
  ? this._fastVerdict
1106
1114
  : (data) => run(data).valid);
1115
+ // Parsed, then the verdict first and the errors only for a document that
1116
+ // fails: collecting them on every document cost an accepted 5 MB one 9 ms
1117
+ // over JSON.parse and validate(). At this layer, below the presentation
1118
+ // that the text path wraps around it: going through validate() as it
1119
+ // stands once every layer is in place handed the text path errors
1120
+ // already presented, and they lost their source anchor.
1121
+ const runText = options.abortEarly
1122
+ ? run
1123
+ : (preprocess
1124
+ ? (data) => { preprocess(data); return interp.isValid(data) ? VALID_RESULT : interp.validate(data); }
1125
+ : (data) => (interp.isValid(data) ? VALID_RESULT : interp.validate(data)));
1107
1126
  this.validateJSON = (jsonStr) => {
1108
1127
  let data;
1109
1128
  try {
@@ -1112,9 +1131,19 @@ class Validator {
1112
1131
  if (!(e instanceof SyntaxError)) throw e;
1113
1132
  return _jsonSyntaxRejection(e);
1114
1133
  }
1115
- return run(data);
1134
+ this._lastParsed = data;
1135
+ return runText(data);
1136
+ };
1137
+ this.isValidJSON = (jsonStr) => {
1138
+ let data;
1139
+ try {
1140
+ data = JSON.parse(jsonStr);
1141
+ } catch (e) {
1142
+ if (!(e instanceof SyntaxError)) throw e;
1143
+ return false;
1144
+ }
1145
+ return this.isValidObject(data);
1116
1146
  };
1117
- this.isValidJSON = (jsonStr) => this.validateJSON(jsonStr).valid;
1118
1147
  }
1119
1148
 
1120
1149
  // Error presentation, one lazy layer: declaration-order sorting, rich
@@ -1163,21 +1192,38 @@ class Validator {
1163
1192
  // rejection it builds. Cleared as soon as it returns: the rejection
1164
1193
  // carries the text itself, so nothing outlives the call.
1165
1194
  this._lastRawInput = jsonStr;
1166
- let result;
1195
+ this._lastParsed = undefined;
1196
+ let result, parsed;
1167
1197
  try {
1168
1198
  result = innerJson(jsonStr);
1169
1199
  } finally {
1170
1200
  this._lastRawInput = null;
1201
+ parsed = this._lastParsed;
1202
+ this._lastParsed = undefined;
1171
1203
  }
1172
1204
  // Every diagnostic the text path adds is deferred. Deciding here
1173
1205
  // whether there is anything to add would mean reading `result.errors`,
1174
1206
  // and on the codegen path that realizes the inner lazy layer, which is
1175
1207
  // the document walk this exists to avoid.
1176
1208
  if (result && result.valid === false) {
1177
- return new LazyJsonRejection(result, jsonStr, this, enrich);
1209
+ return new LazyJsonRejection(result, jsonStr, this, enrich, parsed);
1178
1210
  }
1179
1211
  return result;
1180
1212
  };
1213
+ } else if (this.validateJSON) {
1214
+ // Without enrichment the text path still presents its errors as
1215
+ // validate() does, in declaration order: on generated code they came
1216
+ // out in the order the function found them, so the same document gave
1217
+ // its errors in one order from validate() and another from here.
1218
+ const innerJson = this.validateJSON;
1219
+ this.validateJSON = (jsonStr) => {
1220
+ this._lastParsed = undefined;
1221
+ const result = innerJson(jsonStr);
1222
+ const parsed = this._lastParsed;
1223
+ this._lastParsed = undefined;
1224
+ if (!(result && result.valid === false && parsed !== undefined)) return result;
1225
+ return present(result, parsed);
1226
+ };
1181
1227
  }
1182
1228
  }
1183
1229
 
@@ -1211,10 +1257,12 @@ class Validator {
1211
1257
  // errorMessage keep the validate hot path untouched. Layered after rich
1212
1258
  // enrichment so `code`/`keyword`/`path` are already final and only the
1213
1259
  // human-facing message changes.
1260
+ // The module loads only for a schema that has the keyword: loading it
1261
+ // to ask was a file read on every process's first compile.
1214
1262
  {
1215
- const emLib = require('./error-messages');
1216
1263
  const schemaStr = this._schemaStr || (this._schemaObj ? JSON.stringify(this._schemaObj) : '');
1217
- if (emLib.schemaHasErrorMessages(schemaStr)) {
1264
+ if (schemaStr.indexOf('"errorMessage"') !== -1) {
1265
+ const emLib = require('./error-messages');
1218
1266
  const root = this._schemaObj;
1219
1267
  const wrap = (inner) => (arg) => {
1220
1268
  const result = inner(arg);
@@ -2184,7 +2232,15 @@ for (const [name, pick] of [
2184
2232
  });
2185
2233
  }
2186
2234
 
2235
+ // Cold start: an interpreted twin answers a large schema's first calls where
2236
+ // the code generator is registered (see coldTwin in index.js). Lite has none.
2237
+ Validator.prototype._coldTwin = function () {
2238
+ return _codegen === null || _codegen.coldTwin === undefined ? null : _codegen.coldTwin(this, Validator);
2239
+ };
2240
+
2187
2241
  _defineLazyMethod('validate', (self) => (data) => {
2242
+ const t = self._coldTwin();
2243
+ if (t !== null) return t.validate(data);
2188
2244
  self._ensureCompiled();
2189
2245
  return self.validate(data);
2190
2246
  });
@@ -2195,6 +2251,7 @@ _defineLazyMethod('isValidObject', (self) => {
2195
2251
  // again on every call, about 200 ns, ten times the check.
2196
2252
  let bound = false;
2197
2253
  return (data) => {
2254
+ if (!bound) { const t = self._coldTwin(); if (t !== null) return t.isValidObject(data); }
2198
2255
  if (bound) return self.isValidObject(data);
2199
2256
  bound = true;
2200
2257
  // A validator that rewrites its input goes through the full compile, which
@@ -2234,10 +2291,14 @@ _defineLazyMethod('isValidObject', (self) => {
2234
2291
  };
2235
2292
  });
2236
2293
  _defineLazyMethod('validateJSON', (self) => (jsonStr) => {
2294
+ const t = self._coldTwin();
2295
+ if (t !== null) return t.validateJSON(jsonStr);
2237
2296
  self._ensureCompiled();
2238
2297
  return self.validateJSON(jsonStr);
2239
2298
  });
2240
2299
  _defineLazyMethod('isValidJSON', (self) => (jsonStr) => {
2300
+ const t = self._coldTwin();
2301
+ if (t !== null) return t.isValidJSON(jsonStr);
2241
2302
  self._ensureCompiled();
2242
2303
  return self.isValidJSON(jsonStr);
2243
2304
  });
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.43.0';
10
+ module.exports = '1.45.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.43.0",
3
+ "version": "1.45.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
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -64,7 +64,7 @@
64
64
  "release:check": "node tests/test_pack_purity.js && node scripts/check-doc-coverage.js && node tests/test_error_codes_lock.js && node tests/test_safe_regex_embed.js && node tests/test_version_sync.js",
65
65
  "build": "cmake-js build --target ata",
66
66
  "rebuild": "cmake-js rebuild --target ata",
67
- "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_number_text_parity.js && node tests/test_text_path_errors.js && node tests/test_compiled_parity.js && node tests/test_compiled_extension_parity.js && node tests/test_buffer_gate.js && node tests/test_scanner_differential.js && node tests/test_validate_json_scanner_cost.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_error_list_differential.js && node tests/test_output_format.js && node tests/test_standard_json_schema.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.js && node tests/test_browser_nofs.js && node tests/test_browser_imports_guard.js && node tests/test_esm_exports.js && node tests/test_version_sync.js && node tests/test_native_loaded.js && node tests/test_native_lazy.js && node tests/test_buffer_apis_without_native.js && node tests/test_cold_start_modules.js && node tests/test_safe_regex_embed.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_regex_ecma_whitespace.js && node tests/test_regex_native_linear.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_error_accumulator_collision.js && node tests/test_uri_helper_parity.js && node tests/test_uri_fast_path.js && node tests/test_extend_verdict.js && node tests/test_ipv4_regex.js && node tests/test_ipv6_fast_path.js && node tests/test_nested_recursion_decline.js && node tests/test_generator_error_content.js && node tests/test_inherited_key_presence.js && node tests/test_proto_accessor.js && node tests/test_hybrid_tier.js && node tests/test_first_rejection_builds_one.js && node tests/test_container_local.js && node tests/test_one_shot_validate.js && node tests/test_fixed_pattern_inline.js && node tests/test_plan_source.js && node tests/test_fused_remove_additional.js && node tests/test_runtime_parse.js && node tests/test_formats_single_pass.js && node tests/test_email_format_cost.js && node tests/test_format_single_error.js && node tests/test_defs_pointer_alias.js && node tests/test_encoded_refs.js && node tests/test_cross_doc_root_ref.js && node tests/test_codegen_entrypoint_agreement.js && node tests/test_schema_code_injection.js && node tests/test_aot_html_safe.js && node tests/test_ref_annotation_siblings.js && node tests/test_gate_wrapped_schemas.js && node tests/test_pattern_message_escape.js && node tests/test_nested_defaults_engines.js && node tests/test_nested_coercion_parity.js && node tests/test_preprocess_cache.js && node tests/test_large_schema_codegen.js && node tests/test_base_uri.js && node tests/test_hoisted_def_recursion.js && node tests/test_alias_definitions.js && node tests/test_property_names_ref.js && node tests/test_hybrid_agreement.js && node tests/test_codegen_edge_shapes.js && node tests/test_deferred_def_scope.js && node tests/test_node_scoped_ctx_flags.js && node tests/test_fast_slot_exhaustion.js && node tests/test_ajv_errors.js && node tests/test_custom_keywords.js && node tests/test_custom_keyword_codegen.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_unevaluated_differential.js && node tests/fuzz_differential.js && node tests/test_pattern_properties_errors.js && node tests/test_additional_properties_scaling.js && node tests/test_additional_props_combined_cost.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_ref_error_order.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_error_read_paths.js && node tests/test_unique_items_error_pair.js && node tests/test_rich_errors_generated.js && node tests/test_captured_verdict_stub.js && node tests/test_generated_returns_rewrite.js && node tests/test_deep_pointer_refs.js && node tests/test_uneval_props_dynamic.js && node tests/test_one_pass_no_fallback.js && node tests/test_scanner_size_cap.js && node tests/test_scanner_index_keys.js && node tests/test_both_defs_containers.js && node tests/test_uneval_branch_counts.js && node tests/test_branch_verdicts.js && node tests/test_shared_definitions.js && node tests/test_compile_cache_bound.js && node tests/test_uneval_items_dynamic.js && node tests/test_escaped_property_names.js && node tests/test_ref_siblings_combined.js && node tests/test_unicode_property_patterns.js && node tests/test_single_pass_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_lite_parity.js && node tests/test_lite_bundle_size.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_targeted_positions.js && node tests/test_position_map_cost.js && node tests/test_targeted_positions_cost.js && node tests/test_aot_staleness.js && node tests/test_file_positions.js && node tests/test_aot_positions_cost.js && node tests/test_schema_hash.js && node tests/test_render_shared.js && node tests/test_renderers.js && node tests/test_render_without_process.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_aot_source_frames.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 tests/test_collect_evaluated.js && node tests/test_differential_tiers.js && node tests/test_draft7.js && node tests/test_dual_path.js && node tests/test_keywords_codegen.js && node tests/test_ref_cross.js && node tests/test_shape_classifier.js && node tests/test_tier0.js && node benchmark/bench_aot_size.mjs",
67
+ "test": "node tests/run.js",
68
68
  "bench:size": "node benchmark/bench_aot_size.mjs",
69
69
  "test:suite": "node tests/run_suite.js && node tests/run_suite.js draft7 && node tests/run_suite.js v1",
70
70
  "test:compat": "node tests/test_compat.js",
@@ -143,13 +143,13 @@
143
143
  "LICENSE"
144
144
  ],
145
145
  "optionalDependencies": {
146
- "@ata-validator/native-darwin-arm64": "1.43.0",
147
- "@ata-validator/native-darwin-x64": "1.43.0",
148
- "@ata-validator/native-linux-arm64-gnu": "1.43.0",
149
- "@ata-validator/native-linux-arm64-musl": "1.43.0",
150
- "@ata-validator/native-linux-x64-gnu": "1.43.0",
151
- "@ata-validator/native-linux-x64-musl": "1.43.0",
152
- "@ata-validator/native-win32-x64": "1.43.0"
146
+ "@ata-validator/native-darwin-arm64": "1.45.0",
147
+ "@ata-validator/native-darwin-x64": "1.45.0",
148
+ "@ata-validator/native-linux-arm64-gnu": "1.45.0",
149
+ "@ata-validator/native-linux-arm64-musl": "1.45.0",
150
+ "@ata-validator/native-linux-x64-gnu": "1.45.0",
151
+ "@ata-validator/native-linux-x64-musl": "1.45.0",
152
+ "@ata-validator/native-win32-x64": "1.45.0"
153
153
  },
154
154
  "peerDependencies": {
155
155
  "yaml": "^2.0.0"