.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / dist / compile / validate / index.js
1 "use strict";
2 Object.defineProperty(exports, "__esModule", { value: true });
3 exports.getData = exports.KeywordCxt = exports.validateFunctionCode = void 0;
4 const boolSchema_1 = require("./boolSchema");
5 const dataType_1 = require("./dataType");
6 const applicability_1 = require("./applicability");
7 const dataType_2 = require("./dataType");
8 const defaults_1 = require("./defaults");
9 const keyword_1 = require("./keyword");
10 const subschema_1 = require("./subschema");
11 const codegen_1 = require("../codegen");
12 const names_1 = require("../names");
13 const resolve_1 = require("../resolve");
14 const util_1 = require("../util");
15 const errors_1 = require("../errors");
16 // schema compilation - generates validation function, subschemaCode (below) is used for subschemas
17 function validateFunctionCode(it) {
18     if (isSchemaObj(it)) {
19         checkKeywords(it);
20         if (schemaCxtHasRules(it)) {
21             topSchemaObjCode(it);
22             return;
23         }
24     }
25     validateFunction(it, () => boolSchema_1.topBoolOrEmptySchema(it));
26 }
27 exports.validateFunctionCode = validateFunctionCode;
28 function validateFunction({ gen, validateName, schema, schemaEnv, opts }, body) {
29     if (opts.code.es5) {
30         gen.func(validateName, codegen_1._ `${names_1.default.data}, ${names_1.default.valCxt}`, schemaEnv.$async, () => {
31             gen.code(codegen_1._ `"use strict"; ${funcSourceUrl(schema, opts)}`);
32             destructureValCxtES5(gen, opts);
33             gen.code(body);
34         });
35     }
36     else {
37         gen.func(validateName, codegen_1._ `${names_1.default.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () => gen.code(funcSourceUrl(schema, opts)).code(body));
38     }
39 }
40 function destructureValCxt(opts) {
41     return codegen_1._ `{${names_1.default.instancePath}="", ${names_1.default.parentData}, ${names_1.default.parentDataProperty}, ${names_1.default.rootData}=${names_1.default.data}${opts.dynamicRef ? codegen_1._ `, ${names_1.default.dynamicAnchors}={}` : codegen_1.nil}}={}`;
42 }
43 function destructureValCxtES5(gen, opts) {
44     gen.if(names_1.default.valCxt, () => {
45         gen.var(names_1.default.instancePath, codegen_1._ `${names_1.default.valCxt}.${names_1.default.instancePath}`);
46         gen.var(names_1.default.parentData, codegen_1._ `${names_1.default.valCxt}.${names_1.default.parentData}`);
47         gen.var(names_1.default.parentDataProperty, codegen_1._ `${names_1.default.valCxt}.${names_1.default.parentDataProperty}`);
48         gen.var(names_1.default.rootData, codegen_1._ `${names_1.default.valCxt}.${names_1.default.rootData}`);
49         if (opts.dynamicRef)
50             gen.var(names_1.default.dynamicAnchors, codegen_1._ `${names_1.default.valCxt}.${names_1.default.dynamicAnchors}`);
51     }, () => {
52         gen.var(names_1.default.instancePath, codegen_1._ `""`);
53         gen.var(names_1.default.parentData, codegen_1._ `undefined`);
54         gen.var(names_1.default.parentDataProperty, codegen_1._ `undefined`);
55         gen.var(names_1.default.rootData, names_1.default.data);
56         if (opts.dynamicRef)
57             gen.var(names_1.default.dynamicAnchors, codegen_1._ `{}`);
58     });
59 }
60 function topSchemaObjCode(it) {
61     const { schema, opts, gen } = it;
62     validateFunction(it, () => {
63         if (opts.$comment && schema.$comment)
64             commentKeyword(it);
65         checkNoDefault(it);
66         gen.let(names_1.default.vErrors, null);
67         gen.let(names_1.default.errors, 0);
68         if (opts.unevaluated)
69             resetEvaluated(it);
70         typeAndKeywords(it);
71         returnResults(it);
72     });
73     return;
74 }
75 function resetEvaluated(it) {
76     // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
77     const { gen, validateName } = it;
78     it.evaluated = gen.const("evaluated", codegen_1._ `${validateName}.evaluated`);
79     gen.if(codegen_1._ `${it.evaluated}.dynamicProps`, () => gen.assign(codegen_1._ `${it.evaluated}.props`, codegen_1._ `undefined`));
80     gen.if(codegen_1._ `${it.evaluated}.dynamicItems`, () => gen.assign(codegen_1._ `${it.evaluated}.items`, codegen_1._ `undefined`));
81 }
82 function funcSourceUrl(schema, opts) {
83     return typeof schema == "object" && schema.$id && (opts.code.source || opts.code.process)
84         ? codegen_1._ `/*# sourceURL=${schema.$id} */`
85         : codegen_1.nil;
86 }
87 // schema compilation - this function is used recursively to generate code for sub-schemas
88 function subschemaCode(it, valid) {
89     if (isSchemaObj(it)) {
90         checkKeywords(it);
91         if (schemaCxtHasRules(it)) {
92             subSchemaObjCode(it, valid);
93             return;
94         }
95     }
96     boolSchema_1.boolOrEmptySchema(it, valid);
97 }
98 function schemaCxtHasRules({ schema, self }) {
99     if (typeof schema == "boolean")
100         return !schema;
101     for (const key in schema)
102         if (self.RULES.all[key])
103             return true;
104     return false;
105 }
106 function isSchemaObj(it) {
107     return typeof it.schema != "boolean";
108 }
109 function subSchemaObjCode(it, valid) {
110     const { schema, gen, opts } = it;
111     if (opts.$comment && schema.$comment)
112         commentKeyword(it);
113     updateContext(it);
114     checkAsyncSchema(it);
115     const errsCount = gen.const("_errs", names_1.default.errors);
116     typeAndKeywords(it, errsCount);
117     // TODO var
118     gen.var(valid, codegen_1._ `${errsCount} === ${names_1.default.errors}`);
119 }
120 function checkKeywords(it) {
121     util_1.checkUnknownRules(it);
122     checkRefsAndKeywords(it);
123 }
124 function typeAndKeywords(it, errsCount) {
125     if (it.opts.jtd)
126         return schemaKeywords(it, [], false, errsCount);
127     const types = dataType_1.getSchemaTypes(it.schema);
128     const checkedTypes = dataType_1.coerceAndCheckDataType(it, types);
129     schemaKeywords(it, types, !checkedTypes, errsCount);
130 }
131 function checkRefsAndKeywords(it) {
132     const { schema, errSchemaPath, opts, self } = it;
133     if (schema.$ref && opts.ignoreKeywordsWithRef && util_1.schemaHasRulesButRef(schema, self.RULES)) {
134         self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
135     }
136 }
137 function checkNoDefault(it) {
138     const { schema, opts } = it;
139     if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) {
140         util_1.checkStrictMode(it, "default is ignored in the schema root");
141     }
142 }
143 function updateContext(it) {
144     if (it.schema.$id)
145         it.baseId = resolve_1.resolveUrl(it.baseId, it.schema.$id);
146 }
147 function checkAsyncSchema(it) {
148     if (it.schema.$async && !it.schemaEnv.$async)
149         throw new Error("async schema in sync schema");
150 }
151 function commentKeyword({ gen, schemaEnv, schema, errSchemaPath, opts }) {
152     const msg = schema.$comment;
153     if (opts.$comment === true) {
154         gen.code(codegen_1._ `${names_1.default.self}.logger.log(${msg})`);
155     }
156     else if (typeof opts.$comment == "function") {
157         const schemaPath = codegen_1.str `${errSchemaPath}/$comment`;
158         const rootName = gen.scopeValue("root", { ref: schemaEnv.root });
159         gen.code(codegen_1._ `${names_1.default.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`);
160     }
161 }
162 function returnResults(it) {
163     const { gen, schemaEnv, validateName, ValidationError, opts } = it;
164     if (schemaEnv.$async) {
165         // TODO assign unevaluated
166         gen.if(codegen_1._ `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw(codegen_1._ `new ${ValidationError}(${names_1.default.vErrors})`));
167     }
168     else {
169         gen.assign(codegen_1._ `${validateName}.errors`, names_1.default.vErrors);
170         if (opts.unevaluated)
171             assignEvaluated(it);
172         gen.return(codegen_1._ `${names_1.default.errors} === 0`);
173     }
174 }
175 function assignEvaluated({ gen, evaluated, props, items }) {
176     if (props instanceof codegen_1.Name)
177         gen.assign(codegen_1._ `${evaluated}.props`, props);
178     if (items instanceof codegen_1.Name)
179         gen.assign(codegen_1._ `${evaluated}.items`, items);
180 }
181 function schemaKeywords(it, types, typeErrors, errsCount) {
182     const { gen, schema, data, allErrors, opts, self } = it;
183     const { RULES } = self;
184     if (schema.$ref && (opts.ignoreKeywordsWithRef || !util_1.schemaHasRulesButRef(schema, RULES))) {
185         gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast
186         return;
187     }
188     if (!opts.jtd)
189         checkStrictTypes(it, types);
190     gen.block(() => {
191         for (const group of RULES.rules)
192             groupKeywords(group);
193         groupKeywords(RULES.post);
194     });
195     function groupKeywords(group) {
196         if (!applicability_1.shouldUseGroup(schema, group))
197             return;
198         if (group.type) {
199             gen.if(dataType_2.checkDataType(group.type, data, opts.strictNumbers));
200             iterateKeywords(it, group);
201             if (types.length === 1 && types[0] === group.type && typeErrors) {
202                 gen.else();
203                 dataType_2.reportTypeError(it);
204             }
205             gen.endIf();
206         }
207         else {
208             iterateKeywords(it, group);
209         }
210         // TODO make it "ok" call?
211         if (!allErrors)
212             gen.if(codegen_1._ `${names_1.default.errors} === ${errsCount || 0}`);
213     }
214 }
215 function iterateKeywords(it, group) {
216     const { gen, schema, opts: { useDefaults }, } = it;
217     if (useDefaults)
218         defaults_1.assignDefaults(it, group.type);
219     gen.block(() => {
220         for (const rule of group.rules) {
221             if (applicability_1.shouldUseRule(schema, rule)) {
222                 keywordCode(it, rule.keyword, rule.definition, group.type);
223             }
224         }
225     });
226 }
227 function checkStrictTypes(it, types) {
228     if (it.schemaEnv.meta || !it.opts.strictTypes)
229         return;
230     checkContextTypes(it, types);
231     if (!it.opts.allowUnionTypes)
232         checkMultipleTypes(it, types);
233     checkKeywordTypes(it, it.dataTypes);
234 }
235 function checkContextTypes(it, types) {
236     if (!types.length)
237         return;
238     if (!it.dataTypes.length) {
239         it.dataTypes = types;
240         return;
241     }
242     types.forEach((t) => {
243         if (!includesType(it.dataTypes, t)) {
244             strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`);
245         }
246     });
247     it.dataTypes = it.dataTypes.filter((t) => includesType(types, t));
248 }
249 function checkMultipleTypes(it, ts) {
250     if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
251         strictTypesError(it, "use allowUnionTypes to allow union type keyword");
252     }
253 }
254 function checkKeywordTypes(it, ts) {
255     const rules = it.self.RULES.all;
256     for (const keyword in rules) {
257         const rule = rules[keyword];
258         if (typeof rule == "object" && applicability_1.shouldUseRule(it.schema, rule)) {
259             const { type } = rule.definition;
260             if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
261                 strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
262             }
263         }
264     }
265 }
266 function hasApplicableType(schTs, kwdT) {
267     return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer"));
268 }
269 function includesType(ts, t) {
270     return ts.includes(t) || (t === "integer" && ts.includes("number"));
271 }
272 function strictTypesError(it, msg) {
273     const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
274     msg += ` at "${schemaPath}" (strictTypes)`;
275     util_1.checkStrictMode(it, msg, it.opts.strictTypes);
276 }
277 class KeywordCxt {
278     constructor(it, def, keyword) {
279         keyword_1.validateKeywordUsage(it, def, keyword);
280         this.gen = it.gen;
281         this.allErrors = it.allErrors;
282         this.keyword = keyword;
283         this.data = it.data;
284         this.schema = it.schema[keyword];
285         this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data;
286         this.schemaValue = util_1.schemaRefOrVal(it, this.schema, keyword, this.$data);
287         this.schemaType = def.schemaType;
288         this.parentSchema = it.schema;
289         this.params = {};
290         this.it = it;
291         this.def = def;
292         if (this.$data) {
293             this.schemaCode = it.gen.const("vSchema", getData(this.$data, it));
294         }
295         else {
296             this.schemaCode = this.schemaValue;
297             if (!keyword_1.validSchemaType(this.schema, def.schemaType, def.allowUndefined)) {
298                 throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`);
299             }
300         }
301         if ("code" in def ? def.trackErrors : def.errors !== false) {
302             this.errsCount = it.gen.const("_errs", names_1.default.errors);
303         }
304     }
305     result(condition, successAction, failAction) {
306         this.gen.if(codegen_1.not(condition));
307         if (failAction)
308             failAction();
309         else
310             this.error();
311         if (successAction) {
312             this.gen.else();
313             successAction();
314             if (this.allErrors)
315                 this.gen.endIf();
316         }
317         else {
318             if (this.allErrors)
319                 this.gen.endIf();
320             else
321                 this.gen.else();
322         }
323     }
324     pass(condition, failAction) {
325         this.result(condition, undefined, failAction);
326     }
327     fail(condition) {
328         if (condition === undefined) {
329             this.error();
330             if (!this.allErrors)
331                 this.gen.if(false); // this branch will be removed by gen.optimize
332             return;
333         }
334         this.gen.if(condition);
335         this.error();
336         if (this.allErrors)
337             this.gen.endIf();
338         else
339             this.gen.else();
340     }
341     fail$data(condition) {
342         if (!this.$data)
343             return this.fail(condition);
344         const { schemaCode } = this;
345         this.fail(codegen_1._ `${schemaCode} !== undefined && (${codegen_1.or(this.invalid$data(), condition)})`);
346     }
347     error(append, errorParams, errorPaths) {
348         if (errorParams) {
349             this.setParams(errorParams);
350             this._error(append, errorPaths);
351             this.setParams({});
352             return;
353         }
354         this._error(append, errorPaths);
355     }
356     _error(append, errorPaths) {
357         ;
358         (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error, errorPaths);
359     }
360     $dataError() {
361         errors_1.reportError(this, this.def.$dataError || errors_1.keyword$DataError);
362     }
363     reset() {
364         if (this.errsCount === undefined)
365             throw new Error('add "trackErrors" to keyword definition');
366         errors_1.resetErrorsCount(this.gen, this.errsCount);
367     }
368     ok(cond) {
369         if (!this.allErrors)
370             this.gen.if(cond);
371     }
372     setParams(obj, assign) {
373         if (assign)
374             Object.assign(this.params, obj);
375         else
376             this.params = obj;
377     }
378     block$data(valid, codeBlock, $dataValid = codegen_1.nil) {
379         this.gen.block(() => {
380             this.check$data(valid, $dataValid);
381             codeBlock();
382         });
383     }
384     check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) {
385         if (!this.$data)
386             return;
387         const { gen, schemaCode, schemaType, def } = this;
388         gen.if(codegen_1.or(codegen_1._ `${schemaCode} === undefined`, $dataValid));
389         if (valid !== codegen_1.nil)
390             gen.assign(valid, true);
391         if (schemaType.length || def.validateSchema) {
392             gen.elseIf(this.invalid$data());
393             this.$dataError();
394             if (valid !== codegen_1.nil)
395                 gen.assign(valid, false);
396         }
397         gen.else();
398     }
399     invalid$data() {
400         const { gen, schemaCode, schemaType, def, it } = this;
401         return codegen_1.or(wrong$DataType(), invalid$DataSchema());
402         function wrong$DataType() {
403             if (schemaType.length) {
404                 /* istanbul ignore if */
405                 if (!(schemaCode instanceof codegen_1.Name))
406                     throw new Error("ajv implementation error");
407                 const st = Array.isArray(schemaType) ? schemaType : [schemaType];
408                 return codegen_1._ `${dataType_2.checkDataTypes(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`;
409             }
410             return codegen_1.nil;
411         }
412         function invalid$DataSchema() {
413             if (def.validateSchema) {
414                 const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone
415                 return codegen_1._ `!${validateSchemaRef}(${schemaCode})`;
416             }
417             return codegen_1.nil;
418         }
419     }
420     subschema(appl, valid) {
421         const subschema = subschema_1.getSubschema(this.it, appl);
422         subschema_1.extendSubschemaData(subschema, this.it, appl);
423         subschema_1.extendSubschemaMode(subschema, appl);
424         const nextContext = { ...this.it, ...subschema, items: undefined, props: undefined };
425         subschemaCode(nextContext, valid);
426         return nextContext;
427     }
428     mergeEvaluated(schemaCxt, toName) {
429         const { it, gen } = this;
430         if (!it.opts.unevaluated)
431             return;
432         if (it.props !== true && schemaCxt.props !== undefined) {
433             it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName);
434         }
435         if (it.items !== true && schemaCxt.items !== undefined) {
436             it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName);
437         }
438     }
439     mergeValidEvaluated(schemaCxt, valid) {
440         const { it, gen } = this;
441         if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
442             gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name));
443             return true;
444         }
445     }
446 }
447 exports.KeywordCxt = KeywordCxt;
448 function keywordCode(it, keyword, def, ruleType) {
449     const cxt = new KeywordCxt(it, def, keyword);
450     if ("code" in def) {
451         def.code(cxt, ruleType);
452     }
453     else if (cxt.$data && def.validate) {
454         keyword_1.funcKeywordCode(cxt, def);
455     }
456     else if ("macro" in def) {
457         keyword_1.macroKeywordCode(cxt, def);
458     }
459     else if (def.compile || def.validate) {
460         keyword_1.funcKeywordCode(cxt, def);
461     }
462 }
463 const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
464 const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
465 function getData($data, { dataLevel, dataNames, dataPathArr }) {
466     let jsonPointer;
467     let data;
468     if ($data === "")
469         return names_1.default.rootData;
470     if ($data[0] === "/") {
471         if (!JSON_POINTER.test($data))
472             throw new Error(`Invalid JSON-pointer: ${$data}`);
473         jsonPointer = $data;
474         data = names_1.default.rootData;
475     }
476     else {
477         const matches = RELATIVE_JSON_POINTER.exec($data);
478         if (!matches)
479             throw new Error(`Invalid JSON-pointer: ${$data}`);
480         const up = +matches[1];
481         jsonPointer = matches[2];
482         if (jsonPointer === "#") {
483             if (up >= dataLevel)
484                 throw new Error(errorMsg("property/index", up));
485             return dataPathArr[dataLevel - up];
486         }
487         if (up > dataLevel)
488             throw new Error(errorMsg("data", up));
489         data = dataNames[dataLevel - up];
490         if (!jsonPointer)
491             return data;
492     }
493     let expr = data;
494     const segments = jsonPointer.split("/");
495     for (const segment of segments) {
496         if (segment) {
497             data = codegen_1._ `${data}${codegen_1.getProperty(util_1.unescapeJsonPointer(segment))}`;
498             expr = codegen_1._ `${expr} && ${data}`;
499         }
500     }
501     return expr;
502     function errorMsg(pointerType, up) {
503         return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`;
504     }
505 }
506 exports.getData = getData;
507 //# sourceMappingURL=index.js.map