ata-validator 1.62.1 → 1.63.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.
Files changed (51) hide show
  1. package/README.md +63 -8
  2. package/build.mjs +1 -0
  3. package/index.browser.mjs +23 -4
  4. package/index.bundle.mjs +14 -4
  5. package/index.edge.mjs +14 -4
  6. package/index.js +7 -2
  7. package/lib/aot-build.js +18 -0
  8. package/lib/codegen-engine.js +72 -3
  9. package/lib/compiled-common.js +2 -1
  10. package/lib/email-literal.js +4 -1
  11. package/lib/formats-source.js +39 -40
  12. package/lib/interpreter-core.js +17 -9
  13. package/lib/ir/emit-deps.mjs +131 -0
  14. package/lib/ir/emit.mjs +560 -0
  15. package/lib/ir/front.mjs +834 -0
  16. package/lib/ir/index.mjs +10 -0
  17. package/lib/ir/refs.mjs +108 -0
  18. package/lib/ir/run.mjs +520 -0
  19. package/lib/ir/table.mjs +233 -0
  20. package/lib/js-compiler-errors.js +9 -4
  21. package/lib/kernels/collapse.mjs +114 -0
  22. package/lib/kernels/custom.mjs +70 -0
  23. package/lib/kernels/fill.mjs +6 -0
  24. package/lib/kernels/formats-small.mjs +40 -0
  25. package/lib/kernels/formats.mjs +29 -0
  26. package/lib/kernels/index.mjs +11 -0
  27. package/lib/kernels/kernels.mjs +285 -0
  28. package/lib/kernels/leaves.mjs +28 -0
  29. package/lib/kernels/order.mjs +25 -0
  30. package/lib/kernels/plan-rich.mjs +17 -0
  31. package/lib/kernels/plan.d.ts +9 -0
  32. package/lib/kernels/plan.mjs +128 -0
  33. package/lib/kernels/preprocess.mjs +223 -0
  34. package/lib/kernels/rank.mjs +97 -0
  35. package/lib/kernels/rt.mjs +249 -0
  36. package/lib/kernels/table.mjs +182 -0
  37. package/lib/kernels/unique.mjs +157 -0
  38. package/lib/native-positions.js +1 -1
  39. package/lib/openapi.d.ts +2 -0
  40. package/lib/openapi.js +128 -0
  41. package/lib/plan-compiler.js +84 -7
  42. package/lib/public-api.js +7 -2
  43. package/lib/rejections.js +3 -1
  44. package/lib/schema-helpers.js +12 -0
  45. package/lib/schema-helpers.mjs +20 -0
  46. package/lib/schema-order.js +4 -2
  47. package/lib/standard-schema.js +1 -1
  48. package/lib/validator-core.js +35 -30
  49. package/lib/version.js +1 -1
  50. package/lite.js +7 -2
  51. package/package.json +26 -8
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ // defineSchema and schemaOf outside the core; lib/schema-helpers.mjs says why.
4
+ function defineSchema (schema) {
5
+ return schema;
6
+ }
7
+
8
+ function schemaOf () {
9
+ throw new Error('schemaOf<T>() is replaced at build time by @ata-project/unplugin (with ts-json-schema-generator installed); it has no run-time form. Write the JSON Schema, or build with the plugin.');
10
+ }
11
+
12
+ module.exports = { defineSchema, schemaOf };
@@ -0,0 +1,20 @@
1
+ // The ES form of lib/schema-helpers.js, for the ES entries. Those entries read
2
+ // each core name through a call marked pure, so a module that imports only
3
+ // `defineSchema` leaves the validator core out of its bundle; a destructuring
4
+ // `export const { ... } = core` was kept whole, and a form whose validator the
5
+ // build plugin had compiled away still shipped the runtime through it. The core
6
+ // holds no copy, so a bundle carries the helpers once.
7
+ // tests/test_define_schema_bundle.js covers both forms.
8
+
9
+ // Identity at run time: it gives an inline schema its JSONSchema type
10
+ // (index.d.ts) for autocomplete and value checks while authoring.
11
+ export function defineSchema (schema) {
12
+ return schema;
13
+ }
14
+
15
+ // Written in by @ata-project/unplugin from a TypeScript type at build time. A
16
+ // call that reaches run time was not replaced, and a loud error beats an
17
+ // empty schema that accepts everything.
18
+ export function schemaOf () {
19
+ throw new Error('schemaOf<T>() is replaced at build time by @ata-project/unplugin (with ts-json-schema-generator installed); it has no run-time form. Write the JSON Schema, or build with the plugin.');
20
+ }
@@ -140,8 +140,10 @@ function computeRank(rootSchema, schemaPath) {
140
140
  function remoteTarget(docs, base, node) {
141
141
  const ref = node.$ref;
142
142
  if (typeof ref !== 'string' || ref.charCodeAt(0) === 35) return null;
143
- const abs = resolveUri(ref, base);
144
- if (abs === null) return null;
143
+ // A name with no base to resolve against (a root without $id referencing
144
+ // `shared#`) is looked up as written, the way such documents are registered
145
+ // (schemas: [{ $id: 'shared' }]); it used to stop the rank there.
146
+ const abs = resolveUri(ref, base) || ref;
145
147
  const hash = abs.indexOf('#');
146
148
  const uri = hash < 0 ? abs : abs.slice(0, hash);
147
149
  let target = docs.get(uri);
@@ -117,7 +117,7 @@ function standardSchemaFor(self, getSchema, validate) {
117
117
  if (!message) {
118
118
  // The native engine reports numeric codes without a message; the
119
119
  // enrich pass knows how to word those. Rare, so required lazily.
120
- message = require('./native-message')(err);
120
+ { const m = require('./native-message'); message = (typeof m === 'function' ? m : m.default)(err); }
121
121
  }
122
122
  issues[i] = { message, path: parsePointerPath(path) };
123
123
  }
@@ -6,8 +6,14 @@
6
6
  // threshold, version(). Loading it at require cost about 1.9 ms of a 9.7 ms
7
7
  // serverless start, for every process that never calls any of those.
8
8
  let _nativeMod;
9
+ // A module whose exports are one function, as a function. A CDN that turns
10
+ // each CommonJS file into an ES module (esm.sh) hands require() an object
11
+ // with the function on `default`, and calling it threw on the first
12
+ // validator. Node and bundlers hand over the function itself.
13
+ function callable(m) { return typeof m === 'function' ? m : m.default; }
14
+
9
15
  function getNative() {
10
- if (_nativeMod === undefined) _nativeMod = require("./native-load")();
16
+ if (_nativeMod === undefined) _nativeMod = callable(require("./native-load"))();
11
17
  return _nativeMod;
12
18
  }
13
19
  const { env } = require('./env');
@@ -83,9 +89,9 @@ const _hasOwn = Object.prototype.hasOwnProperty;
83
89
 
84
90
  // Build a function that coerces property values to match schema types in-place.
85
91
  // Handles string→number, string→integer, string→boolean, number→string, boolean→string.
86
- function buildCoercer(schema) {
92
+ function buildCoercer(schema, arrayMode) {
87
93
  if (typeof schema !== "object" || schema === null) return null;
88
- const node = buildNodeCoercer(schema, new Set());
94
+ const node = buildNodeCoercer(schema, new Set(), arrayMode === true);
89
95
  if (node === null) return null;
90
96
  return (data) => { if (typeof data === "object" && data !== null) node(data); };
91
97
  }
@@ -101,7 +107,7 @@ function coercionFor(schema, seen) {
101
107
 
102
108
  // The steps for the object or array at `schema`. `seen` stops a schema that
103
109
  // contains itself through an inline cycle.
104
- function buildNodeCoercer(schema, seen) {
110
+ function buildNodeCoercer(schema, seen, arrayMode) {
105
111
  if (seen.has(schema)) return null;
106
112
  seen.add(schema);
107
113
  const steps = [];
@@ -110,13 +116,17 @@ function buildNodeCoercer(schema, seen) {
110
116
  // Assignment to `__proto__` would replace the prototype; the generated
111
117
  // pass skips it for the same reason.
112
118
  if (key === "__proto__") continue;
119
+ // coerceTypes: 'array' wraps a lone value of a top-level property typed
120
+ // array, as the generated pass does; this pass used to leave it.
121
+ const wrap = arrayMode === true && prop && prop.type === "array";
113
122
  const c = coercionFor(prop, seen);
114
- if (!c) continue;
115
- const { scalar, inner } = c;
123
+ if (!c && !wrap) continue;
124
+ const { scalar, inner } = c || {};
116
125
  steps.push((o) => {
117
126
  // Own properties only: `key in o` found values the object inherits,
118
127
  // and the pass then rewrote the shared object behind them.
119
128
  if (!_hasOwn.call(o, key)) return;
129
+ if (wrap && o[key] !== undefined && !Array.isArray(o[key])) o[key] = [o[key]];
120
130
  if (scalar) {
121
131
  const v = scalar(o[key]);
122
132
  if (v !== undefined) o[key] = v;
@@ -964,6 +974,14 @@ class Validator {
964
974
 
965
975
  _ensureCompiled() {
966
976
  if (this._initialized) return;
977
+ // A compile that throws (a custom keyword's compile returning no
978
+ // function, say) leaves the validator uncompiled, so the next call throws
979
+ // the same error. The flag stayed set, and the next call's lazy method
980
+ // called itself until the stack ran out.
981
+ try { this._compile(); } catch (e) { this._initialized = false; throw e; }
982
+ }
983
+
984
+ _compile() {
967
985
  if (LazyRejection === undefined) _loadRejections();
968
986
  this._ensureVocabularies();
969
987
  this._initialized = true;
@@ -1002,7 +1020,7 @@ class Validator {
1002
1020
  // The generated code takes the form of the target engine (js-compiler's
1003
1021
  // setTargetEngine), so a function written for one engine is never handed
1004
1022
  // to a compile asked for the other in the same process.
1005
- const mapKey = compileCacheKey(this._schemaStr, this._schemaMap) + '\u0000' + (_codegen && _codegen.jsCompiler && typeof _codegen.jsCompiler.targetEngine === 'function' ? _codegen.jsCompiler.targetEngine() : 'v8');
1023
+ const mapKey = (_codegen !== null && _codegen.keyFor !== undefined && _codegen.keyFor(this)) || compileCacheKey(this._schemaStr, this._schemaMap) + '\u0000' + (_codegen && _codegen.jsCompiler && typeof _codegen.jsCompiler.targetEngine === 'function' ? _codegen.jsCompiler.targetEngine() : 'v8');
1006
1024
  var _forceNapi = this._interpretOnly || env('ATA_FORCE_NAPI');
1007
1025
  // Custom formats are JS functions: bypass the compile cache since they can
1008
1026
  // differ between validators that share the same schema string. An
@@ -1112,7 +1130,7 @@ class Validator {
1112
1130
  if (!preprocess) {
1113
1131
  // Without a `default` in the text the defaults module stays unloaded.
1114
1132
  const applyDefaults = options.useDefaults === false || !mayHaveDefaults ? null : buildDefaultsApplier(preprocessSchema);
1115
- const applyCoerce = options.coerceTypes ? buildCoercer(preprocessSchema) : null;
1133
+ const applyCoerce = options.coerceTypes ? buildCoercer(preprocessSchema, options.coerceTypes === 'array') : null;
1116
1134
  const applyRemove = options.removeAdditional
1117
1135
  ? buildRemover(preprocessSchema)
1118
1136
  : null;
@@ -1626,7 +1644,7 @@ class Validator {
1626
1644
  _ensureNative() {
1627
1645
  if (this._nativeReady) return;
1628
1646
  this._nativeReady = true;
1629
- require('./native-attach.js')(this, getNative());
1647
+ callable(require('./native-attach.js'))(this, getNative());
1630
1648
  }
1631
1649
 
1632
1650
  // The buffer APIs, installed on the first call to any of them. The schema
@@ -1647,7 +1665,7 @@ class Validator {
1647
1665
  if (!native && typeof Buffer === 'undefined') throw new Error(`Native addon required for ${name}(). Use validate(), isValidObject() or validateJSON(), which do not need it.`);
1648
1666
  const { bufferNeedsSlowPath, installSlowBufferApis } = require('./buffer-gate.js');
1649
1667
  if (!native) return installSlowBufferApis(this);
1650
- require('./native-attach.js').installFast(this, native, bufferNeedsSlowPath, installSlowBufferApis);
1668
+ callable(require('./native-attach.js')).installFast(this, native, bufferNeedsSlowPath, installSlowBufferApis);
1651
1669
  }
1652
1670
 
1653
1671
  addSchema(schema) {
@@ -1688,7 +1706,12 @@ class Validator {
1688
1706
  return;
1689
1707
  }
1690
1708
  this._ensureVocabularies();
1691
- if (this._interpretOnly || env('ATA_FORCE_NAPI') || _loadCodegen() === null) return;
1709
+ // Where the realm refuses generated code (a strict CSP,
1710
+ // --disallow-code-generation-from-strings) the verdict-only compile could
1711
+ // only reach the closure compiler, which answers in about twice the time
1712
+ // of the interpreted engine the full compile binds there; the callers
1713
+ // fall through to that compile when this leaves no function.
1714
+ if (this._interpretOnly || env('ATA_FORCE_NAPI') || _loadCodegen() === null || !codegenAvailable()) return;
1692
1715
  _codegen.compileVerdict.call(this);
1693
1716
  }
1694
1717
 
@@ -1710,7 +1733,7 @@ class Validator {
1710
1733
 
1711
1734
  // Mutators
1712
1735
  const applyDefaults = buildDefaultsApplier(schemaObj);
1713
- const applyCoerce = options.coerceTypes ? buildCoercer(schemaObj) : null;
1736
+ const applyCoerce = options.coerceTypes ? buildCoercer(schemaObj, options.coerceTypes === 'array') : null;
1714
1737
  const applyRemove = options.removeAdditional
1715
1738
  ? buildRemover(schemaObj)
1716
1739
  : null;
@@ -1941,22 +1964,6 @@ function compile(schema, opts) {
1941
1964
  // and the suggestion helper are exported by index.js. None of them is called
1942
1965
  // by a Validator, so ata-validator/lite leaves them out.
1943
1966
 
1944
- // Authoring helper: identity at runtime. Its only job is to attach the
1945
- // JSONSchema type (see index.d.ts) to an inline schema object so TypeScript
1946
- // gives autocomplete and value checking while authoring. Returns the schema
1947
- // untouched so it can be passed straight to Validator, toStandaloneModule, etc.
1948
- // `schemaOf<T>()`: the JSON Schema of a TypeScript type, written in by
1949
- // @ata-project/unplugin at build time from the type and its JSDoc tags. It
1950
- // has no run-time form: a call that reaches here was not replaced, and the
1951
- // loud error is better than an empty schema that accepts everything.
1952
- function schemaOf () {
1953
- throw new Error('schemaOf<T>() is replaced at build time by @ata-project/unplugin (with ts-json-schema-generator installed); it has no run-time form. Write the JSON Schema, or build with the plugin.');
1954
- }
1955
-
1956
- function defineSchema (schema) {
1957
- return schema;
1958
- }
1959
-
1960
1967
  // Public methods start as memoized accessors on the prototype. A fresh
1961
1968
  // Validator allocates none of them; the first read of a method builds the
1962
1969
  // bound closure, stores it on the instance as an ordinary writable property
@@ -2457,8 +2464,6 @@ module.exports = {
2457
2464
  createPaddedBuffer,
2458
2465
  SIMDJSON_PADDING,
2459
2466
  parseJSON,
2460
- defineSchema,
2461
- schemaOf,
2462
2467
  };
2463
2468
  // How an entry registers the code generator. Not enumerable, so the exported
2464
2469
  // surface of `require('ata-validator')` is what it was.
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.62.1';
10
+ module.exports = '1.63.0';
package/lite.js CHANGED
@@ -15,12 +15,17 @@
15
15
  // where the size of what ships matters more than nanoseconds per call.
16
16
  const core = require('./lib/validator-core.js');
17
17
 
18
+ // Loaded on first call, like the tools: a process that never calls them does
19
+ // not read the file.
20
+ function defineSchema (schema) { return require('./lib/schema-helpers.js').defineSchema(schema); }
21
+ function schemaOf (...a) { return require('./lib/schema-helpers.js').schemaOf(...a); }
22
+
18
23
  module.exports = {
19
24
  Validator: core.Validator,
20
25
  validate: core.validate,
21
26
  validateAsync: core.validateAsync,
22
27
  parseAsync: core.parseAsync,
23
- defineSchema: core.defineSchema,
24
- schemaOf: core.schemaOf,
28
+ defineSchema,
29
+ schemaOf,
25
30
  version: core.version,
26
31
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ata-validator",
3
- "version": "1.62.1",
3
+ "version": "1.63.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",
@@ -109,6 +109,24 @@
109
109
  "types": "./codegen.d.ts",
110
110
  "import": "./codegen.mjs",
111
111
  "require": "./codegen.js"
112
+ },
113
+ "./kernels": {
114
+ "import": "./lib/kernels/index.mjs"
115
+ },
116
+ "./plan": {
117
+ "types": "./lib/kernels/plan.d.ts",
118
+ "import": "./lib/kernels/plan.mjs"
119
+ },
120
+ "./plan-rich": {
121
+ "types": "./lib/kernels/plan.d.ts",
122
+ "import": "./lib/kernels/plan-rich.mjs"
123
+ },
124
+ "./openapi": {
125
+ "types": "./lib/openapi.d.ts",
126
+ "default": "./lib/openapi.js"
127
+ },
128
+ "./ir": {
129
+ "import": "./lib/ir/index.mjs"
112
130
  }
113
131
  },
114
132
  "sideEffects": [
@@ -248,13 +266,13 @@
248
266
  "codegen.d.ts"
249
267
  ],
250
268
  "optionalDependencies": {
251
- "@ata-validator/native-darwin-arm64": "1.62.1",
252
- "@ata-validator/native-darwin-x64": "1.62.1",
253
- "@ata-validator/native-linux-arm64-gnu": "1.62.1",
254
- "@ata-validator/native-linux-arm64-musl": "1.62.1",
255
- "@ata-validator/native-linux-x64-gnu": "1.62.1",
256
- "@ata-validator/native-linux-x64-musl": "1.62.1",
257
- "@ata-validator/native-win32-x64": "1.62.1"
269
+ "@ata-validator/native-darwin-arm64": "1.63.0",
270
+ "@ata-validator/native-darwin-x64": "1.63.0",
271
+ "@ata-validator/native-linux-arm64-gnu": "1.63.0",
272
+ "@ata-validator/native-linux-arm64-musl": "1.63.0",
273
+ "@ata-validator/native-linux-x64-gnu": "1.63.0",
274
+ "@ata-validator/native-linux-x64-musl": "1.63.0",
275
+ "@ata-validator/native-win32-x64": "1.63.0"
258
276
  },
259
277
  "peerDependencies": {
260
278
  "yaml": "^2.0.0"