diff --git a/DEPENDENCIES b/DEPENDENCIES index 733f3f3c..17cd1816 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,7 +1,7 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 uwebsockets https://github.com/uNetworking/uWebSockets v20.76.0 core https://github.com/sourcemeta/core 94b0c4860231adfb18bb8d16951089f95bc3cc4c -blaze https://github.com/sourcemeta/blaze 307e9fd12a1fa10987e55e1da8e8a7b9e6ea5171 +blaze https://github.com/sourcemeta/blaze 83e2458856b934aa7995c44da36ab09152bdfc8d jsonbinpack https://github.com/sourcemeta/jsonbinpack 2fe6502cad30e539de271d2e58ee7f8432b95a4d hydra https://github.com/sourcemeta/hydra 8cbbe5739c31d282a822dece8ed36ef0120cccbe codegen https://github.com/sourcemeta/codegen 8799edb6a88b37b138c360936dd358389c2a3390 diff --git a/vendor/blaze/ports/javascript/LICENSE b/vendor/blaze/ports/javascript/LICENSE new file mode 100644 index 00000000..0a041280 --- /dev/null +++ b/vendor/blaze/ports/javascript/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/blaze/ports/javascript/README.md b/vendor/blaze/ports/javascript/README.md new file mode 100644 index 00000000..28a5091b --- /dev/null +++ b/vendor/blaze/ports/javascript/README.md @@ -0,0 +1,69 @@ +# @sourcemeta/blaze + +[![NPM Version](https://img.shields.io/npm/v/@sourcemeta/blaze)](https://www.npmjs.com/package/@sourcemeta/blaze) +[![NPM Downloads](https://img.shields.io/npm/dm/%40sourcemeta%2Fblaze)](https://www.npmjs.com/package/@sourcemeta/blaze) +[![GitHub contributors](https://img.shields.io/github/contributors/sourcemeta/blaze.svg)](https://github.com/sourcemeta/blaze/graphs/contributors/) + +A pure JavaScript port of the evaluator from +[Blaze](https://github.com/sourcemeta/blaze), a high-performance +C++ JSON Schema validator. Zero dependencies. Supports Draft 4, +Draft 6, Draft 7, 2019-09, and 2020-12 with schema-specific code +generation for near-native speed. + +## Install + +```sh +npm install --save @sourcemeta/blaze +``` + +## Usage + +Blaze evaluates pre-compiled schema templates. Compile your JSON +Schema using the +[jsonschema](https://github.com/sourcemeta/jsonschema) CLI +([compile docs](https://github.com/sourcemeta/jsonschema/blob/main/docs/compile.markdown)): + +```sh +npm install --global @sourcemeta/jsonschema + +cat > schema.json <<'EOF' +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "name": { "type": "string" }, + "age": { "type": "integer" } + }, + "required": [ "name" ] +} +EOF + +jsonschema compile schema.json --fast > template.json +``` + +Then validate instances: + +```javascript +import { readFileSync } from "node:fs"; +import { Blaze } from "@sourcemeta/blaze"; + +const template = + JSON.parse(readFileSync("template.json", "utf-8")); +const evaluator = new Blaze(template); + +// true or false +console.log(evaluator.validate({ name: "John", age: 30 })); +``` + +With an evaluation callback for tracing: + +```javascript +const instance = { name: "John", age: 30 }; +const result = evaluator.validate(instance, + (type, valid, instruction, + evaluatePath, instanceLocation, annotation) => { + console.log(type, evaluatePath, + instanceLocation, valid); + }); +console.log(result); // true or false +``` diff --git a/vendor/blaze/ports/javascript/index.d.mts b/vendor/blaze/ports/javascript/index.d.mts new file mode 100644 index 00000000..9f151364 --- /dev/null +++ b/vendor/blaze/ports/javascript/index.d.mts @@ -0,0 +1,15 @@ +export type Template = Array; + +export type EvaluationCallback = ( + type: "pre" | "post", + valid: boolean, + instruction: unknown[], + evaluatePath: string, + instanceLocation: string, + annotation: unknown +) => void; + +export declare class Blaze { + constructor(template: Template); + validate(instance: unknown, callback?: EvaluationCallback): boolean; +} diff --git a/vendor/blaze/ports/javascript/index.mjs b/vendor/blaze/ports/javascript/index.mjs index 5d7a6671..5cdccfd1 100644 --- a/vendor/blaze/ports/javascript/index.mjs +++ b/vendor/blaze/ports/javascript/index.mjs @@ -1,9 +1,11 @@ +const JSON_VERSION = 1; const DEPTH_LIMIT = 300; const ANNOTATION_EMIT = 44; const ANNOTATION_TO_PARENT = 45; const ANNOTATION_BASENAME_TO_PARENT = 46; const CONTROL_GROUP_START = 85; const CONTROL_EVALUATE_END = 89; +const URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/; function buildJsonPointer(tokens, length) { if (length === 0) return ''; @@ -42,9 +44,14 @@ function isIntegral(value) { } function resolveInstance(instance, relativeInstanceLocation) { - if (relativeInstanceLocation.length === 0) return instance; + const length = relativeInstanceLocation.length; + if (length === 0) return instance; + if (length === 1) { + if (instance === undefined || instance === null) return undefined; + return instance[relativeInstanceLocation[0]]; + } let current = instance; - for (let index = 0; index < relativeInstanceLocation.length; index++) { + for (let index = 0; index < length; index++) { if (current === undefined || current === null) return undefined; current = current[relativeInstanceLocation[index]]; } @@ -110,11 +117,27 @@ function prepareInstruction(instruction) { } } + const opcode = instruction[0]; + if (opcode === 27 && Array.isArray(instruction[5])) { + const values = instruction[5]; + let allPrimitive = true; + for (let index = 0; index < values.length; index++) { + const element = values[index]; + if (element !== null && typeof element === 'object') { + allPrimitive = false; + break; + } + } + if (allPrimitive) { + instruction[5] = { set: new Set(values), values, primitive: true }; + } + } + if (instruction.length < 7) { instruction.push(undefined); } - instruction.push(handlers[instruction[0]] || null); + instruction.push(handlers[opcode] || null); const children = instruction[6]; if (children) { @@ -172,7 +195,7 @@ function collectAnchorNamesFromInstructions(instructions, result) { } function compile(template) { - const targets = template[2]; + const targets = template[3]; for (let targetIndex = 0; targetIndex < targets.length; targetIndex++) { const target = targets[targetIndex]; for (let index = 0; index < target.length; index++) { @@ -185,14 +208,14 @@ function compile(template) { } const labels = new Map(); - const rawLabels = template[3]; + const rawLabels = template[4]; for (let index = 0; index < rawLabels.length; index++) { const pair = rawLabels[index]; labels.set(pair[0], pair[1]); } const anchors = new Map(); - if (template[0]) { + if (template[1]) { const anchorNames = new Set(); collectAnchorNames(targets, anchorNames); const resourceCount = targets.length; @@ -212,20 +235,172 @@ function compile(template) { return template; } +function emitResolve(varName, instanceExpr, relInstance) { + if (relInstance.length === 0) return `var ${varName}=${instanceExpr};`; + if (relInstance.length === 1) return `var ${varName}=${instanceExpr}==null?void 0:${instanceExpr}[${JSON.stringify(relInstance[0])}];`; + return null; +} + +function compileInstructionToCode(instruction, captures, visited, budget) { + if (budget[0] <= 0) { var ci = captures.length; captures.push(instruction); return 'return _fh['+instruction[0]+'](_c['+ci+'],i,d,_t,_v);'; } + var opcode = instruction[0], ri = instruction[2], value = instruction[5], children = instruction[6]; + function R(v) { return emitResolve(v, 'i', ri); } + function inlineCondition(child, tv) { + var op = child[0], cr = child[2], cv = child[5]; + if (cr.length !== 0) return null; + switch (op) { + case 11: return '{if(_es(' + tv + ')!==' + cv + ')return false;}'; + case 38: return 'if(' + tv + '!=null&&typeof ' + tv + "==='object'&&!Array.isArray(" + tv + ')){' + emitResolve('t', tv, cr) + 'if(t!==void 0&&_es(t)!==' + cv + ')return false;}'; + default: return null; + } + } + function seq(ci, tv) { var c = ''; for (var j = 0; j < ci.length; j++) { var inl = inlineCondition(ci[j], tv); if (inl !== null) { budget[0] -= inl.length; c += inl; continue; } var r = compileInstructionToCode(ci[j], captures, visited, budget); if (r === null) { var idx = captures.length; captures.push(ci[j]); c += 'if(!_e(_c['+idx+'],'+tv+',d+1,_t,_v))return false;'; } else { budget[0] -= r.length; c += 'if(!(function(i,d,_t,_v){'+r+'})('+tv+',d+1,_t,_v))return false;'; } } return c; } + function lb(ci, iv) { return seq(ci, iv); } + function fb(op) { var ci = captures.length; captures.push(instruction); return 'return _fh['+op+'](_c['+ci+'],i,d,_t,_v);'; } + function cc(child, tv) { var r = compileInstructionToCode(child, captures, visited, budget); if (r === null) { var ci = captures.length; captures.push(child); return '_e(_c['+ci+'],'+tv+',d+1,_t,_v)'; } budget[0] -= r.length; return '(function(i,d,_t,_v){'+r+'})('+tv+',d+1,_t,_v)'; } + var IO = "if(i==null||typeof i!=='object'||Array.isArray(i))return true;"; + var TO = "if(t==null||typeof t!=='object'||Array.isArray(t))"; + switch (opcode) { + case 0: return 'return false;'; + case 1: { var r=R('t'); return r?r+TO+'return true;return Object.hasOwn(t,'+JSON.stringify(value)+');':null; } + case 2: { var r=R('t'); return r?r+"return t!=null&&typeof t==='object'&&!Array.isArray(t)&&Object.hasOwn(t,"+JSON.stringify(value)+');':null; } + case 3: { var r=R('t'); if(!r)return null; var c=r+TO+'return true;'; for(var j=0;j'+value[1]+')return false;':'')+'return true;':null; } + case 14: { var r=R('t'); return r?r+"return typeof t==='string'&&_ul(t)<="+value+';':null; } + case 15: { var r=R('t'); return r?r+'if(!Array.isArray(t))return false;if(t.length<'+value[0]+')return false;'+(value[1]!==null?'if(t.length>'+value[1]+')return false;':'')+'return true;':null; } + case 16: { var r=R('t'); return r?r+'return Array.isArray(t)&&t.length<='+value+';':null; } + case 17: { var r=R('t'); return r?r+TO+'return false;var s=0;for(var k in t)s++;if(s<'+value[0]+')return false;'+(value[1]!==null?'if(s>'+value[1]+')return false;':'')+'return true;':null; } + case 18: { var r=R('t'); return r?r+TO+'return false;var s=0;for(var k in t)s++;return s<='+value+';':null; } + case 19: return fb(19); case 20: return fb(20); case 21: return fb(21); + case 22: { var r=R('t'); return r?r+'if(!Array.isArray(t))return true;return t.length<'+value+';':null; } + case 23: { var r=R('t'); return r?r+'if(!Array.isArray(t))return true;return t.length>'+value+';':null; } + case 24: { var r=R('t'); return r?r+TO+'return true;var s=0;for(var k in t)s++;return s<'+value+';':null; } + case 25: { var r=R('t'); return r?r+TO+'return true;var s=0;for(var k in t)s++;return s>'+value+';':null; } + case 26: { if(typeof value==='string'||typeof value==='number'||typeof value==='boolean'||value===null){var r=R('t');return r?r+'return t==='+JSON.stringify(value)+';':null;}return fb(26); } + case 27: return fb(27); case 28: return fb(28); + case 29: { var r=R('t'); return r?r+"if(typeof t!=='number')return true;return t>="+value+';':null; } + case 30: { var r=R('t'); return r?r+"if(typeof t!=='number')return true;return t<="+value+';':null; } + case 31: { var r=R('t'); return r?r+"if(typeof t!=='number')return true;return t>"+value+';':null; } + case 32: { var r=R('t'); return r?r+"if(typeof t!=='number')return true;return t<"+value+';':null; } + case 33: return fb(33); case 34: return fb(34); case 35: return fb(35); + case 36: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;var a=_jt(t);return a==='+value+'||('+value+'===2&&_ii(t));':null; } + case 37: return fb(37); + case 38: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return _es(t)==='+value+';':null; } + case 39: return fb(39); + case 40: { var r=R('t'); return r?IO+r+'if(t===void 0)return true;return('+value+'&(1<<_es(t)))!==0;':null; } + case 41: return fb(41); case 42: return fb(42); case 43: return fb(43); + case 44: return 'return true;'; case 45: return 'return true;'; case 46: return 'return true;'; case 47: return 'return true;'; + case 48: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return 'return false;'; var c=r; for(var j=0;j0)c+=seq(children,'t'); return c+'return true;'; } + case 55: { var r=R('t'); if(!r)return null; var c=r+TO+'return true;if(!Object.hasOwn(t,'+JSON.stringify(value)+'))return true;'; if(children&&children.length>0)c+=seq(children,'t'); return c+'return true;'; } + case 56: { var r=R('t'); if(!r)return null; var c=r+'if(!Array.isArray(t)||t.length<='+value+')return true;'; if(children&&children.length>0)c+=seq(children,'t'); return c+'return true;'; } + case 57: return fb(57); case 58: return fb(58); + case 59: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; var mi=captures.length; captures.push(value); var gf=''; for(var gi=0;gi0){gf+='function(i,d,_t,_v){'+lb(gc,'i')+'return true;},';}else{gf+='null,';}} return r+TO+'return true;var __cg=['+gf+'];for(var k in t){var __mi=_c['+mi+'][k];if(__mi!==void 0){var __cf=__cg[__mi];if(__cf&&!__cf(t,d,_t,_v))return false;}}return true;'; } + case 60: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; var mi=captures.length; captures.push(value); var gf=''; for(var gi=0;gi0){gf+='function(i,d,_t,_v){'+lb(gc,'i')+'return true;},';}else{gf+='null,';}} return r+TO+'return true;var __cg=['+gf+'];for(var k in t){var __mi=_c['+mi+'][k];if(__mi===void 0)return false;var __cf=__cg[__mi];if(__cf&&!__cf(t,d,_t,_v))return false;}return true;'; } + case 61: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; return r+TO+'return true;for(var k in t){'+lb(children,'t[k]')+'}return true;'; } + case 62: return fb(62); case 63: return fb(63); case 64: return fb(64); case 65: return fb(65); case 66: return fb(66); + case 67: return fb(67); case 68: return fb(68); case 69: return fb(69); case 70: return fb(70); + case 71: { var r=R('t'); return r?r+TO+'return true;for(var k in t){if(_es(t[k])!=='+value+')return false;}return true;':null; } + case 72: return fb(72); case 73: return fb(73); case 74: return fb(74); case 75: return fb(75); + case 76: { var r=R('t'); if(!r)return null; if(!children||children.length===0)return r+'return true;'; return r+'if(!Array.isArray(t))return true;for(var j=0;j=t.length)return true;for(var j='+value+';j0)c+=seq(children,'i'); return c+'return true;'; } + case 87: { var c=IO+'if(!Object.hasOwn(i,'+JSON.stringify(value)+'))return true;'; if(children&&children.length>0)c+=seq(children,'i'); return c+'return true;'; } + case 88: { var c='if(_jt(i)!=='+value+')return true;'; if(children&&children.length>0)c+=seq(children,'i'); return c+'return true;'; } + case 89: return 'return true;'; + case 90: return fb(90); + case 91: { if(!value)return 'return true;'; if(visited&&visited.has(instruction))return fb(91); if(!visited)visited=new Set(); visited.add(instruction); var r=R('t'); if(!r)return fb(91); var c=r; for(var j=0;j true; + const instructions = targets[0]; + if (instructions.length === 0) return () => true; + + const capturedInstructions = []; + const budget = [5000000]; + let body = ''; + for (let index = 0; index < instructions.length; index++) { + const code = compileInstructionToCode(instructions[index], capturedInstructions, null, budget); + if (code === null) return null; + budget[0] -= code.length; + body += `if(!(function(i,d,_t,_v){${code}})(instance,0,_t,_v))return false;`; + } + body += 'return true;'; + + try { + const fn = eval( + '(function(_es,_jt,_ii,_ul,_e,_fh,_c,_t){' + + 'return function(instance,_v){' + body + '};' + + '})' + ); + return fn( + effectiveTypeStrictReal, jsonTypeOf, isIntegral, unicodeLength, + evaluateInstructionFast, fastHandlers, capturedInstructions, template + ); + } catch { + return null; + } +} + class Blaze { constructor(template) { + if (!Array.isArray(template) || template[0] !== JSON_VERSION) { + throw new Error( + `Only version ${JSON_VERSION} of the compiled template is supported by this version of the evaluator`); + } compile(template); this.template = template; this.callbackMode = false; + this.trackMode = false; + this.dynamicMode = false; + this.callback = null; + this.evaluatePathLength = 0; + this.evaluatePathTokens = null; + this.instanceLocationLength = 0; + this.instanceLocationTokens = null; + this.resources = null; + this.evaluated = null; + this.propertyTarget = undefined; + this.propertyParent = undefined; + this.propertyKey = undefined; + this._nativeValidate = generateNativeValidator(template); } validate(instance, callback) { + if (callback === undefined && this._nativeValidate) { + return this._nativeValidate(instance, this); + } + const template = this.template; - const targets = template[2]; + const targets = template[3]; if (targets.length === 0) return true; - const track = template[1]; - const dynamic = template[0]; + const track = template[2]; + const dynamic = template[1]; this.trackMode = track; this.dynamicMode = dynamic; this.callbackMode = callback !== undefined; @@ -268,11 +443,11 @@ class Blaze { } } - this.resources = undefined; - this.evaluated = undefined; - this.evaluatePathTokens = undefined; - this.instanceLocationTokens = undefined; - this.callback = undefined; + this.resources = null; + this.evaluated = null; + this.evaluatePathTokens = null; + this.instanceLocationTokens = null; + this.callback = null; this.callbackMode = false; return result; } @@ -435,7 +610,7 @@ function evaluateInstructionFast(instruction, instance, depth, template, evaluat if (depth > DEPTH_LIMIT) { throw new Error('The evaluation path depth limit was reached likely due to infinite recursion'); } - const handler = instruction[7]; + const handler = fastHandlers[instruction[0]]; if (!handler) return true; return handler(instruction, instance, depth, template, evaluator); } @@ -444,7 +619,7 @@ function evaluateInstructionTracked(instruction, instance, depth, template, eval if (depth > DEPTH_LIMIT) { throw new Error('The evaluation path depth limit was reached likely due to infinite recursion'); } - const handler = instruction[7]; + const handler = fastHandlers[instruction[0]]; if (!handler) return true; const type = instruction[0]; @@ -474,7 +649,7 @@ function evaluateInstructionFastCallback(instruction, instance, depth, template, if (depth > DEPTH_LIMIT) { throw new Error('The evaluation path depth limit was reached likely due to infinite recursion'); } - const handler = instruction[7]; + const handler = handlers[instruction[0]]; if (!handler) return true; return handler(instruction, instance, depth, template, evaluator); } @@ -483,7 +658,7 @@ function evaluateInstructionTrackedCallback(instruction, instance, depth, templa if (depth > DEPTH_LIMIT) { throw new Error('The evaluation path depth limit was reached likely due to infinite recursion'); } - const handler = instruction[7]; + const handler = handlers[instruction[0]]; if (!handler) return true; const type = instruction[0]; @@ -512,9 +687,14 @@ function evaluateInstructionTrackedCallback(instruction, instance, depth, templa let evaluateInstruction = evaluateInstructionFast; function effectiveTypeStrictReal(value) { - const type = jsonTypeOf(value); - if (type === Type.Real && Number.isInteger(value)) return Type.Integer; - return type; + if (value === null) return Type.Null; + switch (typeof value) { + case 'boolean': return Type.Boolean; + case 'number': return Number.isInteger(value) ? Type.Integer : Type.Real; + case 'string': return Type.String; + case 'object': return Array.isArray(value) ? Type.Array : Type.Object; + default: return Type.Null; + } } function typeSetTest(bitmask, typeIndex) { @@ -566,12 +746,34 @@ function fastHash(value) { } function isUnique(array) { - if (array.length <= 1) return true; - const hashes = new Array(array.length); - for (let index = 0; index < array.length; index++) { + const length = array.length; + if (length <= 1) return true; + const first = array[0]; + const firstType = typeof first; + if (first !== null && firstType !== 'object') { + let allPrimitive = true; + for (let index = 1; index < length; index++) { + const element = array[index]; + if (element === null || typeof element === 'object') { + allPrimitive = false; + break; + } + } + if (allPrimitive) { + const set = new Set(); + for (let index = 0; index < length; index++) { + const size = set.size; + set.add(array[index]); + if (set.size === size) return false; + } + return true; + } + } + const hashes = new Array(length); + for (let index = 0; index < length; index++) { hashes[index] = fastHash(array[index]); } - for (let index = 1; index < array.length; index++) { + for (let index = 1; index < length; index++) { for (let previous = 0; previous < index; previous++) { if (hashes[index] === hashes[previous] && jsonEqual(array[index], array[previous])) return false; } @@ -591,7 +793,8 @@ function unicodeLength(string) { let count = 0; for (let index = 0; index < string.length; index++) { count++; - if (string.charCodeAt(index) >= 0xD800 && string.charCodeAt(index) <= 0xDBFF) index++; + const code = string.charCodeAt(index); + if (code >= 0xD800 && code <= 0xDBFF) index++; } return count; } @@ -972,22 +1175,19 @@ function AssertionEqual(instruction, instance, depth, template, evaluator) { function AssertionEqualsAny(instruction, instance, depth, template, evaluator) { if (evaluator.callbackMode) evaluator.callbackPush(instruction); - if (evaluator.propertyTarget !== undefined) { - const values = instruction[5]; - for (let index = 0; index < values.length; index++) { - if (jsonEqual(evaluator.propertyTarget, values[index])) { - if (evaluator.callbackMode) evaluator.callbackPop(instruction, true); - return true; - } - } - } else { - const target = resolveInstance(instance, instruction[2]); - const values = instruction[5]; - for (let index = 0; index < values.length; index++) { - if (jsonEqual(target, values[index])) { - if (evaluator.callbackMode) evaluator.callbackPop(instruction, true); - return true; - } + const value = instruction[5]; + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (value.primitive) { + const __result = value.set.has(target); + if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result); + return __result; + } + const values = Array.isArray(value) ? value : value.values; + for (let index = 0; index < values.length; index++) { + if (jsonEqual(target, values[index])) { + if (evaluator.callbackMode) evaluator.callbackPop(instruction, true); + return true; } } if (evaluator.callbackMode) evaluator.callbackPop(instruction, false); @@ -1088,14 +1288,9 @@ function AssertionStringType(instruction, instance, depth, template, evaluator) ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); if (typeof target !== 'string') return true; if (evaluator.callbackMode) evaluator.callbackPush(instruction); - try { - new URL(target); - if (evaluator.callbackMode) evaluator.callbackPop(instruction, true); - return true; - } catch { - if (evaluator.callbackMode) evaluator.callbackPop(instruction, false); - return false; - } + const __result = URI_REGEX.test(target); + if (evaluator.callbackMode) evaluator.callbackPop(instruction, __result); + return __result; }; function AssertionPropertyType(instruction, instance, depth, template, evaluator) { @@ -2331,4 +2526,1189 @@ const handlers = [ ControlJump // 91 ]; +function AssertionTypeArrayBounded_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return false; + const range = instruction[5]; + if (target.length < range[0]) return false; + if (range[1] !== null && target.length > range[1]) return false; + return true; +} + +function LoopItemsTypeStrictAny_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return true; + const bitmask = instruction[5]; + for (let index = 0; index < target.length; index++) { + if (!typeSetTest(bitmask, effectiveTypeStrictReal(target[index]))) return false; + } + return true; +} + +function AssertionPropertyTypeStrict_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + return effectiveTypeStrictReal(target) === instruction[5]; +} + +function AssertionTypeStrict_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + return effectiveTypeStrictReal(target) === instruction[5]; +} + +function AssertionDefinesAllStrict_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return false; + const strings = instruction[5]; + for (let index = 0; index < strings.length; index++) { + if (!Object.hasOwn(target, strings[index])) return false; + } + return true; +} + +function AssertionEqual_fast(instruction, instance, depth, template, evaluator) { + if (evaluator.propertyTarget !== undefined) { + const value = instruction[5]; + return typeof value === 'string' && value === evaluator.propertyTarget; + } + return jsonEqual(resolveInstance(instance, instruction[2]), instruction[5]); +} + +function LoopPropertiesMatch_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const children = instruction[6]; + for (const key in target) { + const index = instruction[5][key]; + if (index === undefined) continue; + const subinstruction = children[index]; + const subchildren = subinstruction[6]; + if (subchildren) { + for (let childIndex = 0; childIndex < subchildren.length; childIndex++) { + if (!evaluateInstruction(subchildren[childIndex], target, depth + 1, template, evaluator)) return false; + } + } + } + return true; +} + +function LogicalOr_fast(instruction, instance, depth, template, evaluator) { + const children = instruction[6]; + if (!children || children.length === 0) return true; + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const exhaustive = instruction[5]; + let result = false; + if (exhaustive) { + for (let index = 0; index < children.length; index++) { + if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) result = true; + } + } else { + for (let index = 0; index < children.length; index++) { + if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return true; + } + } + return result; +} + +function ControlJump_fast(instruction, instance, depth, template, evaluator) { + const jumpTarget = instruction[5]; + if (!jumpTarget) return true; + const relInstance = instruction[2]; + const resolved = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + for (let index = 0; index < jumpTarget.length; index++) { + if (!evaluateInstruction(jumpTarget[index], resolved, depth + 1, template, evaluator)) return false; + } + return true; +} + +function AssertionEqualsAnyStringHash_fast(instruction, instance, depth, template, evaluator) { + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget + : resolveInstance(instance, instruction[2]); + if (typeof target !== 'string') return false; + const value = instruction[5]; + const entries = value[0]; + const tableOfContents = value[1]; + const stringSize = target.length; + if (stringSize < tableOfContents.length) { + const hint = tableOfContents[stringSize]; + if (hint[1] === 0) return false; + for (let index = hint[0] - 1; index < hint[1]; index++) { + if (entries[index][1] === target) return true; + } + } + return false; +} + +function LogicalXor_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const exhaustive = instruction[5]; + const children = instruction[6]; + let result = true; + let hasMatched = false; + if (children) { + for (let index = 0; index < children.length; index++) { + if (evaluateInstruction(children[index], target, depth + 1, template, evaluator)) { + if (hasMatched) { + result = false; + if (!exhaustive) break; + } else { + hasMatched = true; + } + } + } + } + return result && hasMatched; +} + +function AssertionDefinesStrict_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + return isObject(target) && Object.hasOwn(target, instruction[5]); +} + +function LoopItems_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return true; + const children = instruction[6]; + for (let index = 0; index < target.length; index++) { + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[index], depth + 1, template, evaluator)) return false; + } + } + } + return true; +} + +function LoopPropertiesMatchClosed_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const children = instruction[6]; + for (const key in target) { + const index = instruction[5][key]; + if (index === undefined) return false; + const subinstruction = children[index]; + const subchildren = subinstruction[6]; + if (subchildren) { + for (let childIndex = 0; childIndex < subchildren.length; childIndex++) { + if (!evaluateInstruction(subchildren[childIndex], target, depth + 1, template, evaluator)) return false; + } + } + } + return true; +} + +function LogicalAnd_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const children = instruction[6]; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return false; + } + } + return true; +} + +function AssertionTypeStringBounded_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (typeof target !== 'string') return false; + const range = instruction[5]; + const length = unicodeLength(target); + if (length < range[0]) return false; + return range[1] === null || length <= range[1]; +} + +function AssertionPropertyDependencies_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + const value = instruction[5]; + for (const property in value) { + if (!Object.hasOwn(target, property)) continue; + const dependencies = value[property]; + for (let index = 0; index < dependencies.length; index++) { + if (!Object.hasOwn(target, dependencies[index])) return false; + } + } + return true; +} + +function AssertionTypeAny_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const bitmask = instruction[5]; + const typeIndex = jsonTypeOf(target); + if (typeSetTest(bitmask, typeIndex)) return true; + return typeSetTest(bitmask, Type.Integer) && isIntegral(target); +} + +function LogicalCondition_fast(instruction, instance, depth, template, evaluator) { + const value = instruction[5]; + const thenStart = value[0]; + const elseStart = value[1]; + const children = instruction[6]; + const childrenSize = children ? children.length : 0; + let conditionEnd = childrenSize; + if (thenStart > 0) conditionEnd = thenStart; + else if (elseStart > 0) conditionEnd = elseStart; + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + let conditionResult = true; + for (let cursor = 0; cursor < conditionEnd; cursor++) { + if (!evaluateInstruction(children[cursor], target, depth + 1, template, evaluator)) { + conditionResult = false; + break; + } + } + const consequenceStart = conditionResult ? thenStart : elseStart; + const consequenceEnd = (conditionResult && elseStart > 0) ? elseStart : childrenSize; + if (consequenceStart > 0) { + if (evaluator.trackMode) { + evaluator.popPath(instruction[1].length); + } + let result = true; + for (let cursor = consequenceStart; cursor < consequenceEnd; cursor++) { + if (!evaluateInstruction(children[cursor], target, depth + 1, template, evaluator)) { + result = false; + break; + } + } + if (evaluator.trackMode) { + evaluator.pushPath(instruction[1]); + } + return result; + } + return true; +} + +function LoopPropertiesExcept_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const filter = instruction[5]; + const filterStrings = filter[0]; + const filterPrefixes = filter[1]; + const filterRegexes = filter[2]; + const children = instruction[6]; + for (const key in target) { + if (filterStrings.has(key)) continue; + let matched = false; + for (let index = 0; index < filterPrefixes.length; index++) { + if (key.startsWith(filterPrefixes[index])) { matched = true; break; } + } + if (matched) continue; + for (let index = 0; index < filterRegexes.length; index++) { + filterRegexes[index].lastIndex = 0; + if (filterRegexes[index].test(key)) { matched = true; break; } + } + if (matched) continue; + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return true; +} + +function AssertionRegex_fast(instruction, instance, depth, template, evaluator) { + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (typeof target !== 'string') return true; + return instruction[5].test(target); +} + +function LoopProperties_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const children = instruction[6]; + for (const key in target) { + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return true; +} + +function AssertionDefines_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + return Object.hasOwn(target, instruction[5]); +} + +function LogicalWhenType_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (jsonTypeOf(target) !== instruction[5]) return true; + const children = instruction[6]; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return false; + } + } + return true; +} + +function LogicalWhenDefines_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + if (!Object.hasOwn(target, instruction[5])) return true; + const children = instruction[6]; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return false; + } + } + return true; +} + +function AssertionFail_fast() { return false; } + +function LoopContains_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return true; + const range = instruction[5]; + const minimum = range[0]; + const maximum = range[1]; + const isExhaustive = range[2]; + if (minimum === 0 && target.length === 0) return true; + const children = instruction[6]; + let matchCount = 0; + for (let index = 0; index < target.length; index++) { + let subresult = true; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[index], depth + 1, template, evaluator)) { + subresult = false; + break; + } + } + } + if (subresult) { + matchCount++; + if (maximum !== null && matchCount > maximum) return false; + if (matchCount >= minimum && maximum === null && !isExhaustive) return true; + } + } + return matchCount >= minimum; +} + +function LogicalNot_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const children = instruction[6]; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return true; + } + } + return false; +} + +function LoopItemsType_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return true; + const expected = instruction[5]; + for (let index = 0; index < target.length; index++) { + const actual = jsonTypeOf(target[index]); + if (actual !== expected && !(expected === Type.Integer && isIntegral(target[index]))) return false; + } + return true; +} + +function LoopItemsTypeStrict_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!Array.isArray(target)) return true; + const expected = instruction[5]; + for (let index = 0; index < target.length; index++) { + if (effectiveTypeStrictReal(target[index]) !== expected) return false; + } + return true; +} + +function AssertionEqualsAny_fast(instruction, instance, depth, template, evaluator) { + const value = instruction[5]; + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (value.primitive) return value.set.has(target); + const values = Array.isArray(value) ? value : value.values; + for (let index = 0; index < values.length; index++) { + if (jsonEqual(target, values[index])) return true; + } + return false; +} + +function AssertionDefinesAll_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + const strings = instruction[5]; + for (let index = 0; index < strings.length; index++) { + if (!Object.hasOwn(target, strings[index])) return false; + } + return true; +} + +function AssertionDefinesExactly_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + let targetSize = 0; + for (const key in target) targetSize++; + const strings = instruction[5]; + if (targetSize !== strings.length) return false; + for (let index = 0; index < strings.length; index++) { + if (!Object.hasOwn(target, strings[index])) return false; + } + return true; +} + +function AssertionDefinesExactlyStrict_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return false; + let targetSize = 0; + for (const key in target) targetSize++; + const strings = instruction[5]; + if (targetSize !== strings.length) return false; + for (let index = 0; index < strings.length; index++) { + if (!Object.hasOwn(target, strings[index])) return false; + } + return true; +} + +function AssertionDefinesExactlyStrictHash3_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return false; + const entries = instruction[5][0]; + let count = 0; + for (const key in target) count++; + if (count !== 3) return false; + return Object.hasOwn(target, entries[0][1]) && + Object.hasOwn(target, entries[1][1]) && + Object.hasOwn(target, entries[2][1]); +} + +function AssertionType_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + const expected = instruction[5]; + const actual = jsonTypeOf(target); + if (actual === expected) return true; + return expected === Type.Integer && isIntegral(target); +} + +function AssertionTypeStrictAny_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + return typeSetTest(instruction[5], effectiveTypeStrictReal(target)); +} + +function AssertionTypeStringUpper_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + return typeof target === 'string' && unicodeLength(target) <= instruction[5]; +} + +function AssertionTypeArrayUpper_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + return Array.isArray(target) && target.length <= instruction[5]; +} + +function AssertionTypeObjectBounded_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return false; + const range = instruction[5]; + const size = objectSize(target); + if (size < range[0]) return false; + return range[1] === null || size <= range[1]; +} + +function AssertionTypeObjectUpper_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return false; + return objectSize(target) <= instruction[5]; +} + +function AssertionStringSizeLess_fast(instruction, instance, depth, template, evaluator) { + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (typeof target !== 'string') return true; + return unicodeLength(target) < instruction[5]; +} + +function AssertionStringSizeGreater_fast(instruction, instance, depth, template, evaluator) { + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (typeof target !== 'string') return true; + return unicodeLength(target) > instruction[5]; +} + +function AssertionArraySizeLess_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + return target.length < instruction[5]; +} + +function AssertionArraySizeGreater_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + return target.length > instruction[5]; +} + +function AssertionObjectSizeLess_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + return objectSize(target) < instruction[5]; +} + +function AssertionObjectSizeGreater_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + return objectSize(target) > instruction[5]; +} + +function AssertionGreaterEqual_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (typeof target !== 'number') return true; + return target >= instruction[5]; +} + +function AssertionLessEqual_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (typeof target !== 'number') return true; + return target <= instruction[5]; +} + +function AssertionGreater_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (typeof target !== 'number') return true; + return target > instruction[5]; +} + +function AssertionLess_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (typeof target !== 'number') return true; + return target < instruction[5]; +} + +function AssertionUnique_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + return isUnique(target); +} + +function AssertionDivisible_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (typeof target !== 'number') return true; + return isDivisibleBy(target, instruction[5]); +} + +function AssertionStringType_fast(instruction, instance, depth, template, evaluator) { + const target = evaluator.propertyTarget !== undefined + ? evaluator.propertyTarget : resolveInstance(instance, instruction[2]); + if (typeof target !== 'string') return true; + return URI_REGEX.test(target); +} + +function AssertionPropertyType_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + const expected = instruction[5]; + const actual = jsonTypeOf(target); + return actual === expected || (expected === Type.Integer && isIntegral(target)); +} + +function AssertionPropertyTypeEvaluate_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + const expected = instruction[5]; + const actual = jsonTypeOf(target); + const result = actual === expected || (expected === Type.Integer && isIntegral(target)); + if (result && evaluator.trackMode) { + const location = instruction[2]; + evaluator.markEvaluated(target, instance, location.length > 0 ? location[location.length - 1] : undefined); + } + return result; +} + +function AssertionPropertyTypeStrictEvaluate_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + const result = effectiveTypeStrictReal(target) === instruction[5]; + if (result && evaluator.trackMode) { + const location = instruction[2]; + evaluator.markEvaluated(target, instance, location.length > 0 ? location[location.length - 1] : undefined); + } + return result; +} + +function AssertionPropertyTypeStrictAny_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + return typeSetTest(instruction[5], effectiveTypeStrictReal(target)); +} + +function AssertionPropertyTypeStrictAnyEvaluate_fast(instruction, instance, depth, template, evaluator) { + if (!isObject(instance)) return true; + const target = resolveInstance(instance, instruction[2]); + if (target === undefined) return true; + const result = typeSetTest(instruction[5], effectiveTypeStrictReal(target)); + if (result && evaluator.trackMode) { + const location = instruction[2]; + evaluator.markEvaluated(target, instance, location.length > 0 ? location[location.length - 1] : undefined); + } + return result; +} + +function AssertionArrayPrefix_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + if (target.length === 0) return true; + const children = instruction[6]; + const prefixes = children.length - 1; + const pointer = target.length === prefixes ? prefixes : Math.min(target.length, prefixes) - 1; + const entry = children[pointer]; + const entryChildren = entry[6]; + if (entryChildren) { + for (let index = 0; index < entryChildren.length; index++) { + if (!evaluateInstruction(entryChildren[index], target, depth + 1, template, evaluator)) return false; + } + } + return true; +} + +function AssertionArrayPrefixEvaluate_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + if (target.length === 0) return true; + const children = instruction[6]; + const prefixes = children.length - 1; + const pointer = target.length === prefixes ? prefixes : Math.min(target.length, prefixes) - 1; + const entry = children[pointer]; + const entryChildren = entry[6]; + if (entryChildren) { + for (let index = 0; index < entryChildren.length; index++) { + if (!evaluateInstruction(entryChildren[index], target, depth + 1, template, evaluator)) return false; + } + } + if (evaluator.trackMode) { + if (target.length === prefixes) { + evaluator.markEvaluated(target); + } else { + for (let cursor = 0; cursor <= pointer; cursor++) { + evaluator.markEvaluated(target[cursor], target, cursor); + } + } + } + return true; +} + +function AnnotationEmit_fast() { return true; } +function AnnotationToParent_fast() { return true; } +function AnnotationBasenameToParent_fast() { return true; } + +function Evaluate_fast(instruction, instance, depth, template, evaluator) { + if (evaluator.trackMode) { + const target = resolveInstance(instance, instruction[2]); + evaluator.markEvaluated(target); + } + return true; +} + +function LogicalNotEvaluate_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + const children = instruction[6]; + let result = false; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) { + result = true; + break; + } + } + } + if (evaluator.trackMode) evaluator.unevaluate(); + return result; +} + +function LogicalWhenArraySizeGreater_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target) || target.length <= instruction[5]) return true; + const children = instruction[6]; + if (children) { + for (let index = 0; index < children.length; index++) { + if (!evaluateInstruction(children[index], target, depth + 1, template, evaluator)) return false; + } + } + return true; +} + +function LoopPropertiesUnevaluated_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + if (evaluator.trackMode && evaluator.isEvaluated(target)) return true; + const children = instruction[6]; + for (const key in target) { + if (evaluator.trackMode && evaluator.isEvaluated(target[key], target, key)) continue; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) return false; + } + } + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopPropertiesUnevaluatedExcept_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + if (evaluator.trackMode && evaluator.isEvaluated(target)) return true; + const filter = instruction[5]; + const filterStrings = filter[0]; + const filterPrefixes = filter[1]; + const filterRegexes = filter[2]; + const children = instruction[6]; + for (const key in target) { + if (filterStrings.has(key)) continue; + let matched = false; + for (let index = 0; index < filterPrefixes.length; index++) { + if (key.startsWith(filterPrefixes[index])) { matched = true; break; } + } + if (matched) continue; + for (let index = 0; index < filterRegexes.length; index++) { + filterRegexes[index].lastIndex = 0; + if (filterRegexes[index].test(key)) { matched = true; break; } + } + if (matched) continue; + if (evaluator.trackMode && evaluator.isEvaluated(target[key], target, key)) continue; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) return false; + } + } + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopPropertiesEvaluate_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const children = instruction[6]; + for (const key in target) { + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopPropertiesRegex_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const regex = instruction[5]; + const children = instruction[6]; + for (const key in target) { + regex.lastIndex = 0; + if (!regex.test(key)) continue; + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return true; +} + +function LoopPropertiesRegexClosed_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const regex = instruction[5]; + const children = instruction[6]; + for (const key in target) { + regex.lastIndex = 0; + if (!regex.test(key)) return false; + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return true; +} + +function LoopPropertiesStartsWith_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const prefix = instruction[5]; + const children = instruction[6]; + for (const key in target) { + if (!key.startsWith(prefix)) continue; + evaluator.propertyParent = target; + evaluator.propertyKey = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[key], depth + 1, template, evaluator)) { + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return false; + } + } + } + } + evaluator.propertyParent = undefined; + evaluator.propertyKey = undefined; + return true; +} + +function LoopPropertiesType_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const expected = instruction[5]; + for (const key in target) { + const actual = jsonTypeOf(target[key]); + if (actual !== expected && !(expected === Type.Integer && isIntegral(target[key]))) return false; + } + return true; +} + +function LoopPropertiesTypeEvaluate_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const expected = instruction[5]; + for (const key in target) { + const actual = jsonTypeOf(target[key]); + if (actual !== expected && !(expected === Type.Integer && isIntegral(target[key]))) return false; + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopPropertiesExactlyTypeStrict_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return false; + const value = instruction[5]; + let count = 0; + for (const key in target) { + count++; + if (effectiveTypeStrictReal(target[key]) !== value[0]) return false; + } + return count === value[1].length; +} + +function LoopPropertiesExactlyTypeStrictHash_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return false; + const value = instruction[5]; + const entries = value[1][0]; + const expectedCount = entries.length; + let count = 0; + for (const key in target) { + count++; + if (effectiveTypeStrictReal(target[key]) !== value[0]) return false; + } + if (count !== expectedCount) return false; + for (let index = 0; index < expectedCount; index++) { + if (!Object.hasOwn(target, entries[index][1])) return false; + } + return true; +} + +function LoopPropertiesTypeStrict_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const expected = instruction[5]; + for (const key in target) { + if (effectiveTypeStrictReal(target[key]) !== expected) return false; + } + return true; +} + +function LoopPropertiesTypeStrictEvaluate_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const expected = instruction[5]; + for (const key in target) { + if (effectiveTypeStrictReal(target[key]) !== expected) return false; + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopPropertiesTypeStrictAny_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const bitmask = instruction[5]; + for (const key in target) { + if (!typeSetTest(bitmask, effectiveTypeStrictReal(target[key]))) return false; + } + return true; +} + +function LoopPropertiesTypeStrictAnyEvaluate_fast(instruction, instance, depth, template, evaluator) { + const relInstance = instruction[2]; + const target = relInstance.length === 0 ? instance : resolveInstance(instance, relInstance); + if (!isObject(target)) return true; + const bitmask = instruction[5]; + for (const key in target) { + if (!typeSetTest(bitmask, effectiveTypeStrictReal(target[key]))) return false; + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopKeys_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!isObject(target)) return true; + const children = instruction[6]; + for (const key in target) { + const previousPropertyTarget = evaluator.propertyTarget; + evaluator.propertyTarget = key; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], null, depth + 1, template, evaluator)) { + evaluator.propertyTarget = previousPropertyTarget; + return false; + } + } + } + evaluator.propertyTarget = previousPropertyTarget; + } + return true; +} + +function LoopItemsFrom_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + const startIndex = instruction[5]; + if (!Array.isArray(target) || startIndex >= target.length) return true; + const children = instruction[6]; + for (let index = startIndex; index < target.length; index++) { + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[index], depth + 1, template, evaluator)) return false; + } + } + } + return true; +} + +function LoopItemsUnevaluated_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return true; + if (evaluator.trackMode && evaluator.isEvaluated(target)) return true; + const children = instruction[6]; + for (let index = 0; index < target.length; index++) { + if (evaluator.trackMode && evaluator.isEvaluated(target[index], target, index)) continue; + if (children) { + for (let childIndex = 0; childIndex < children.length; childIndex++) { + if (!evaluateInstruction(children[childIndex], target[index], depth + 1, template, evaluator)) return false; + } + } + } + if (evaluator.trackMode) evaluator.markEvaluated(target); + return true; +} + +function LoopItemsPropertiesExactlyTypeStrictHash_fast(instruction, instance, depth, template, evaluator) { + const target = resolveInstance(instance, instruction[2]); + if (!Array.isArray(target)) return false; + const expectedType = instruction[5][0]; + const entries = instruction[5][1][0]; + const expectedCount = entries.length; + for (let index = 0; index < target.length; index++) { + const item = target[index]; + if (!isObject(item)) return false; + let count = 0; + for (const key in item) { + count++; + if (effectiveTypeStrictReal(item[key]) !== expectedType) return false; + } + if (count !== expectedCount) return false; + for (let entry = 0; entry < expectedCount; entry++) { + if (!Object.hasOwn(item, entries[entry][1])) return false; + } + } + return true; +} + +function ControlDynamicAnchorJump_fast(instruction, instance, depth, template, evaluator) { + const resolved = resolveInstance(instance, instruction[2]); + const anchor = instruction[5]; + if (!evaluator.resources) return false; + const anchors = template[5]; + for (let index = 0; index < evaluator.resources.length; index++) { + const jumpTarget = anchors.get(evaluator.resources[index] + ':' + anchor); + if (jumpTarget !== undefined) { + for (let childIndex = 0; childIndex < jumpTarget.length; childIndex++) { + if (!evaluateInstruction(jumpTarget[childIndex], resolved, depth + 1, template, evaluator)) return false; + } + return true; + } + } + return false; +} + +const fastHandlers = handlers.slice(); +fastHandlers[15] = AssertionTypeArrayBounded_fast; +fastHandlers[81] = LoopItemsTypeStrictAny_fast; +fastHandlers[38] = AssertionPropertyTypeStrict_fast; +fastHandlers[11] = AssertionTypeStrict_fast; +fastHandlers[4] = AssertionDefinesAllStrict_fast; +fastHandlers[26] = AssertionEqual_fast; +fastHandlers[59] = LoopPropertiesMatch_fast; +fastHandlers[50] = LogicalOr_fast; +fastHandlers[91] = ControlJump_fast; +fastHandlers[28] = AssertionEqualsAnyStringHash_fast; +fastHandlers[52] = LogicalXor_fast; +fastHandlers[2] = AssertionDefinesStrict_fast; +fastHandlers[76] = LoopItems_fast; +fastHandlers[60] = LoopPropertiesMatchClosed_fast; +fastHandlers[13] = AssertionTypeStringBounded_fast; +fastHandlers[51] = LogicalAnd_fast; +fastHandlers[8] = AssertionPropertyDependencies_fast; +fastHandlers[10] = AssertionTypeAny_fast; +fastHandlers[53] = LogicalCondition_fast; +fastHandlers[66] = LoopPropertiesExcept_fast; +fastHandlers[19] = AssertionRegex_fast; +fastHandlers[61] = LoopProperties_fast; +fastHandlers[1] = AssertionDefines_fast; +fastHandlers[54] = LogicalWhenType_fast; +fastHandlers[55] = LogicalWhenDefines_fast; +fastHandlers[0] = AssertionFail_fast; +fastHandlers[84] = LoopContains_fast; +fastHandlers[48] = LogicalNot_fast; +fastHandlers[79] = LoopItemsType_fast; +fastHandlers[80] = LoopItemsTypeStrict_fast; +fastHandlers[27] = AssertionEqualsAny_fast; +fastHandlers[3] = AssertionDefinesAll_fast; +fastHandlers[5] = AssertionDefinesExactly_fast; +fastHandlers[6] = AssertionDefinesExactlyStrict_fast; +fastHandlers[7] = AssertionDefinesExactlyStrictHash3_fast; +fastHandlers[9] = AssertionType_fast; +fastHandlers[12] = AssertionTypeStrictAny_fast; +fastHandlers[14] = AssertionTypeStringUpper_fast; +fastHandlers[16] = AssertionTypeArrayUpper_fast; +fastHandlers[17] = AssertionTypeObjectBounded_fast; +fastHandlers[18] = AssertionTypeObjectUpper_fast; +fastHandlers[20] = AssertionStringSizeLess_fast; +fastHandlers[21] = AssertionStringSizeGreater_fast; +fastHandlers[22] = AssertionArraySizeLess_fast; +fastHandlers[23] = AssertionArraySizeGreater_fast; +fastHandlers[24] = AssertionObjectSizeLess_fast; +fastHandlers[25] = AssertionObjectSizeGreater_fast; +fastHandlers[29] = AssertionGreaterEqual_fast; +fastHandlers[30] = AssertionLessEqual_fast; +fastHandlers[31] = AssertionGreater_fast; +fastHandlers[32] = AssertionLess_fast; +fastHandlers[33] = AssertionUnique_fast; +fastHandlers[34] = AssertionDivisible_fast; +fastHandlers[35] = AssertionStringType_fast; +fastHandlers[36] = AssertionPropertyType_fast; +fastHandlers[37] = AssertionPropertyTypeEvaluate_fast; +fastHandlers[39] = AssertionPropertyTypeStrictEvaluate_fast; +fastHandlers[40] = AssertionPropertyTypeStrictAny_fast; +fastHandlers[41] = AssertionPropertyTypeStrictAnyEvaluate_fast; +fastHandlers[42] = AssertionArrayPrefix_fast; +fastHandlers[43] = AssertionArrayPrefixEvaluate_fast; +fastHandlers[44] = AnnotationEmit_fast; +fastHandlers[45] = AnnotationToParent_fast; +fastHandlers[46] = AnnotationBasenameToParent_fast; +fastHandlers[47] = Evaluate_fast; +fastHandlers[49] = LogicalNotEvaluate_fast; +fastHandlers[56] = LogicalWhenArraySizeGreater_fast; +fastHandlers[57] = LoopPropertiesUnevaluated_fast; +fastHandlers[58] = LoopPropertiesUnevaluatedExcept_fast; +fastHandlers[62] = LoopPropertiesEvaluate_fast; +fastHandlers[63] = LoopPropertiesRegex_fast; +fastHandlers[64] = LoopPropertiesRegexClosed_fast; +fastHandlers[65] = LoopPropertiesStartsWith_fast; +fastHandlers[67] = LoopPropertiesType_fast; +fastHandlers[68] = LoopPropertiesTypeEvaluate_fast; +fastHandlers[69] = LoopPropertiesExactlyTypeStrict_fast; +fastHandlers[70] = LoopPropertiesExactlyTypeStrictHash_fast; +fastHandlers[71] = LoopPropertiesTypeStrict_fast; +fastHandlers[72] = LoopPropertiesTypeStrictEvaluate_fast; +fastHandlers[73] = LoopPropertiesTypeStrictAny_fast; +fastHandlers[74] = LoopPropertiesTypeStrictAnyEvaluate_fast; +fastHandlers[75] = LoopKeys_fast; +fastHandlers[77] = LoopItemsFrom_fast; +fastHandlers[78] = LoopItemsUnevaluated_fast; +fastHandlers[82] = LoopItemsPropertiesExactlyTypeStrictHash_fast; +fastHandlers[83] = LoopItemsPropertiesExactlyTypeStrictHash_fast; +fastHandlers[90] = ControlDynamicAnchorJump_fast; + export { Blaze }; diff --git a/vendor/blaze/ports/javascript/package-lock.json b/vendor/blaze/ports/javascript/package-lock.json index edd16080..66bc1463 100644 --- a/vendor/blaze/ports/javascript/package-lock.json +++ b/vendor/blaze/ports/javascript/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sourcemeta/blaze", - "version": "0.0.1", + "version": "0.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sourcemeta/blaze", - "version": "0.0.1" + "version": "0.0.2" } } } diff --git a/vendor/blaze/ports/javascript/package.json b/vendor/blaze/ports/javascript/package.json index 31f61255..ef08b215 100644 --- a/vendor/blaze/ports/javascript/package.json +++ b/vendor/blaze/ports/javascript/package.json @@ -1,10 +1,71 @@ { "name": "@sourcemeta/blaze", - "version": "0.0.1", - "private": true, + "version": "0.0.2", + "description": "A pure JavaScript port of the evaluator from Blaze, a high-performance C++ JSON Schema validator. Zero dependencies. Supports Draft 4, Draft 6, Draft 7, 2019-09, and 2020-12 with schema-specific code generation for near-native speed", "type": "module", - "scripts": { - "test": "node --test test.mjs trace.mjs", - "benchmark": "node benchmark.mjs" - } + "main": "./index.mjs", + "module": "./index.mjs", + "exports": { + ".": { + "import": "./index.mjs", + "default": "./index.mjs" + } + }, + "types": "./index.d.mts", + "license": "LGPL-3.0-or-later", + "homepage": "https://github.com/sourcemeta/blaze", + "author": { + "email": "hello@sourcemeta.com", + "name": "Sourcemeta", + "url": "https://www.sourcemeta.com" + }, + "engines": { + "node": ">=18" + }, + "funding": "https://github.com/sponsors/sourcemeta", + "keywords": [ + "jsonschema", + "json", + "schema", + "json-schema", + "validator", + "validation", + "json-schema-validator", + "json-schema-validation", + "blaze", + "sourcemeta", + "fast", + "performance", + "codegen", + "draft-04", + "draft-06", + "draft-07", + "draft4", + "draft6", + "draft7", + "2019-09", + "2020-12", + "ajv", + "ajv-alternative", + "$ref", + "validate", + "evaluator" + ], + "bugs": { + "url": "https://github.com/sourcemeta/blaze/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sourcemeta/blaze.git", + "directory": "ports/javascript" + }, + "publishConfig": { + "access": "public" + }, + "files": [ + "index.mjs", + "index.d.mts", + "README.md", + "LICENSE" + ] } diff --git a/vendor/blaze/src/compiler/compile_json.cc b/vendor/blaze/src/compiler/compile_json.cc index 4b2583c2..89a847b0 100644 --- a/vendor/blaze/src/compiler/compile_json.cc +++ b/vendor/blaze/src/compiler/compile_json.cc @@ -53,6 +53,8 @@ auto to_json(const Template &schema_template) -> sourcemeta::core::JSON { // Note that we purposely avoid objects to help consumers avoid potentially // expensive hash-map or flat-map lookups when parsing back auto result{sourcemeta::core::JSON::make_array()}; + result.push_back(sourcemeta::core::JSON{ + static_cast(sourcemeta::blaze::JSON_VERSION)}); result.push_back(sourcemeta::core::JSON{schema_template.dynamic}); result.push_back(sourcemeta::core::JSON{schema_template.track}); diff --git a/vendor/blaze/src/evaluator/evaluator_json.cc b/vendor/blaze/src/evaluator/evaluator_json.cc index dc9720ea..62ef8159 100644 --- a/vendor/blaze/src/evaluator/evaluator_json.cc +++ b/vendor/blaze/src/evaluator/evaluator_json.cc @@ -119,18 +119,24 @@ auto instructions_from_json( namespace sourcemeta::blaze { auto from_json(const sourcemeta::core::JSON &json) -> std::optional