You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					510 lines
				
				20 KiB
			
		
		
			
		
	
	
					510 lines
				
				20 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | Object.defineProperty(exports, "__esModule", { value: true }); | ||
|  | exports.getData = exports.KeywordCxt = exports.validateFunctionCode = void 0; | ||
|  | const boolSchema_1 = require("./boolSchema"); | ||
|  | const dataType_1 = require("./dataType"); | ||
|  | const applicability_1 = require("./applicability"); | ||
|  | const dataType_2 = require("./dataType"); | ||
|  | const defaults_1 = require("./defaults"); | ||
|  | const keyword_1 = require("./keyword"); | ||
|  | const subschema_1 = require("./subschema"); | ||
|  | const codegen_1 = require("../codegen"); | ||
|  | const names_1 = require("../names"); | ||
|  | const resolve_1 = require("../resolve"); | ||
|  | const util_1 = require("../util"); | ||
|  | const errors_1 = require("../errors"); | ||
|  | // schema compilation - generates validation function, subschemaCode (below) is used for subschemas
 | ||
|  | function validateFunctionCode(it) { | ||
|  |     if (isSchemaObj(it)) { | ||
|  |         checkKeywords(it); | ||
|  |         if (schemaCxtHasRules(it)) { | ||
|  |             topSchemaObjCode(it); | ||
|  |             return; | ||
|  |         } | ||
|  |     } | ||
|  |     validateFunction(it, () => (0, boolSchema_1.topBoolOrEmptySchema)(it)); | ||
|  | } | ||
|  | exports.validateFunctionCode = validateFunctionCode; | ||
|  | function validateFunction({ gen, validateName, schema, schemaEnv, opts }, body) { | ||
|  |     if (opts.code.es5) { | ||
|  |         gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${names_1.default.valCxt}`, schemaEnv.$async, () => { | ||
|  |             gen.code((0, codegen_1._) `"use strict"; ${funcSourceUrl(schema, opts)}`); | ||
|  |             destructureValCxtES5(gen, opts); | ||
|  |             gen.code(body); | ||
|  |         }); | ||
|  |     } | ||
|  |     else { | ||
|  |         gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () => gen.code(funcSourceUrl(schema, opts)).code(body)); | ||
|  |     } | ||
|  | } | ||
|  | function destructureValCxt(opts) { | ||
|  |     return (0, codegen_1._) `{${names_1.default.instancePath}="", ${names_1.default.parentData}, ${names_1.default.parentDataProperty}, ${names_1.default.rootData}=${names_1.default.data}${opts.dynamicRef ? (0, codegen_1._) `, ${names_1.default.dynamicAnchors}={}` : codegen_1.nil}}={}`; | ||
|  | } | ||
|  | function destructureValCxtES5(gen, opts) { | ||
|  |     gen.if(names_1.default.valCxt, () => { | ||
|  |         gen.var(names_1.default.instancePath, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.instancePath}`); | ||
|  |         gen.var(names_1.default.parentData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentData}`); | ||
|  |         gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentDataProperty}`); | ||
|  |         gen.var(names_1.default.rootData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.rootData}`); | ||
|  |         if (opts.dynamicRef) | ||
|  |             gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.dynamicAnchors}`); | ||
|  |     }, () => { | ||
|  |         gen.var(names_1.default.instancePath, (0, codegen_1._) `""`); | ||
|  |         gen.var(names_1.default.parentData, (0, codegen_1._) `undefined`); | ||
|  |         gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `undefined`); | ||
|  |         gen.var(names_1.default.rootData, names_1.default.data); | ||
|  |         if (opts.dynamicRef) | ||
|  |             gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `{}`); | ||
|  |     }); | ||
|  | } | ||
|  | function topSchemaObjCode(it) { | ||
|  |     const { schema, opts, gen } = it; | ||
|  |     validateFunction(it, () => { | ||
|  |         if (opts.$comment && schema.$comment) | ||
|  |             commentKeyword(it); | ||
|  |         checkNoDefault(it); | ||
|  |         gen.let(names_1.default.vErrors, null); | ||
|  |         gen.let(names_1.default.errors, 0); | ||
|  |         if (opts.unevaluated) | ||
|  |             resetEvaluated(it); | ||
|  |         typeAndKeywords(it); | ||
|  |         returnResults(it); | ||
|  |     }); | ||
|  |     return; | ||
|  | } | ||
|  | function resetEvaluated(it) { | ||
|  |     // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
 | ||
|  |     const { gen, validateName } = it; | ||
|  |     it.evaluated = gen.const("evaluated", (0, codegen_1._) `${validateName}.evaluated`); | ||
|  |     gen.if((0, codegen_1._) `${it.evaluated}.dynamicProps`, () => gen.assign((0, codegen_1._) `${it.evaluated}.props`, (0, codegen_1._) `undefined`)); | ||
|  |     gen.if((0, codegen_1._) `${it.evaluated}.dynamicItems`, () => gen.assign((0, codegen_1._) `${it.evaluated}.items`, (0, codegen_1._) `undefined`)); | ||
|  | } | ||
|  | function funcSourceUrl(schema, opts) { | ||
|  |     const schId = typeof schema == "object" && schema[opts.schemaId]; | ||
|  |     return schId && (opts.code.source || opts.code.process) ? (0, codegen_1._) `/*# sourceURL=${schId} */` : codegen_1.nil; | ||
|  | } | ||
|  | // schema compilation - this function is used recursively to generate code for sub-schemas
 | ||
|  | function subschemaCode(it, valid) { | ||
|  |     if (isSchemaObj(it)) { | ||
|  |         checkKeywords(it); | ||
|  |         if (schemaCxtHasRules(it)) { | ||
|  |             subSchemaObjCode(it, valid); | ||
|  |             return; | ||
|  |         } | ||
|  |     } | ||
|  |     (0, boolSchema_1.boolOrEmptySchema)(it, valid); | ||
|  | } | ||
|  | function schemaCxtHasRules({ schema, self }) { | ||
|  |     if (typeof schema == "boolean") | ||
|  |         return !schema; | ||
|  |     for (const key in schema) | ||
|  |         if (self.RULES.all[key]) | ||
|  |             return true; | ||
|  |     return false; | ||
|  | } | ||
|  | function isSchemaObj(it) { | ||
|  |     return typeof it.schema != "boolean"; | ||
|  | } | ||
|  | function subSchemaObjCode(it, valid) { | ||
|  |     const { schema, gen, opts } = it; | ||
|  |     if (opts.$comment && schema.$comment) | ||
|  |         commentKeyword(it); | ||
|  |     updateContext(it); | ||
|  |     checkAsyncSchema(it); | ||
|  |     const errsCount = gen.const("_errs", names_1.default.errors); | ||
|  |     typeAndKeywords(it, errsCount); | ||
|  |     // TODO var
 | ||
|  |     gen.var(valid, (0, codegen_1._) `${errsCount} === ${names_1.default.errors}`); | ||
|  | } | ||
|  | function checkKeywords(it) { | ||
|  |     (0, util_1.checkUnknownRules)(it); | ||
|  |     checkRefsAndKeywords(it); | ||
|  | } | ||
|  | function typeAndKeywords(it, errsCount) { | ||
|  |     if (it.opts.jtd) | ||
|  |         return schemaKeywords(it, [], false, errsCount); | ||
|  |     const types = (0, dataType_1.getSchemaTypes)(it.schema); | ||
|  |     const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types); | ||
|  |     schemaKeywords(it, types, !checkedTypes, errsCount); | ||
|  | } | ||
|  | function checkRefsAndKeywords(it) { | ||
|  |     const { schema, errSchemaPath, opts, self } = it; | ||
|  |     if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) { | ||
|  |         self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`); | ||
|  |     } | ||
|  | } | ||
|  | function checkNoDefault(it) { | ||
|  |     const { schema, opts } = it; | ||
|  |     if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) { | ||
|  |         (0, util_1.checkStrictMode)(it, "default is ignored in the schema root"); | ||
|  |     } | ||
|  | } | ||
|  | function updateContext(it) { | ||
|  |     const schId = it.schema[it.opts.schemaId]; | ||
|  |     if (schId) | ||
|  |         it.baseId = (0, resolve_1.resolveUrl)(it.opts.uriResolver, it.baseId, schId); | ||
|  | } | ||
|  | function checkAsyncSchema(it) { | ||
|  |     if (it.schema.$async && !it.schemaEnv.$async) | ||
|  |         throw new Error("async schema in sync schema"); | ||
|  | } | ||
|  | function commentKeyword({ gen, schemaEnv, schema, errSchemaPath, opts }) { | ||
|  |     const msg = schema.$comment; | ||
|  |     if (opts.$comment === true) { | ||
|  |         gen.code((0, codegen_1._) `${names_1.default.self}.logger.log(${msg})`); | ||
|  |     } | ||
|  |     else if (typeof opts.$comment == "function") { | ||
|  |         const schemaPath = (0, codegen_1.str) `${errSchemaPath}/$comment`; | ||
|  |         const rootName = gen.scopeValue("root", { ref: schemaEnv.root }); | ||
|  |         gen.code((0, codegen_1._) `${names_1.default.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`); | ||
|  |     } | ||
|  | } | ||
|  | function returnResults(it) { | ||
|  |     const { gen, schemaEnv, validateName, ValidationError, opts } = it; | ||
|  |     if (schemaEnv.$async) { | ||
|  |         // TODO assign unevaluated
 | ||
|  |         gen.if((0, codegen_1._) `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw((0, codegen_1._) `new ${ValidationError}(${names_1.default.vErrors})`)); | ||
|  |     } | ||
|  |     else { | ||
|  |         gen.assign((0, codegen_1._) `${validateName}.errors`, names_1.default.vErrors); | ||
|  |         if (opts.unevaluated) | ||
|  |             assignEvaluated(it); | ||
|  |         gen.return((0, codegen_1._) `${names_1.default.errors} === 0`); | ||
|  |     } | ||
|  | } | ||
|  | function assignEvaluated({ gen, evaluated, props, items }) { | ||
|  |     if (props instanceof codegen_1.Name) | ||
|  |         gen.assign((0, codegen_1._) `${evaluated}.props`, props); | ||
|  |     if (items instanceof codegen_1.Name) | ||
|  |         gen.assign((0, codegen_1._) `${evaluated}.items`, items); | ||
|  | } | ||
|  | function schemaKeywords(it, types, typeErrors, errsCount) { | ||
|  |     const { gen, schema, data, allErrors, opts, self } = it; | ||
|  |     const { RULES } = self; | ||
|  |     if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) { | ||
|  |         gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast
 | ||
|  |         return; | ||
|  |     } | ||
|  |     if (!opts.jtd) | ||
|  |         checkStrictTypes(it, types); | ||
|  |     gen.block(() => { | ||
|  |         for (const group of RULES.rules) | ||
|  |             groupKeywords(group); | ||
|  |         groupKeywords(RULES.post); | ||
|  |     }); | ||
|  |     function groupKeywords(group) { | ||
|  |         if (!(0, applicability_1.shouldUseGroup)(schema, group)) | ||
|  |             return; | ||
|  |         if (group.type) { | ||
|  |             gen.if((0, dataType_2.checkDataType)(group.type, data, opts.strictNumbers)); | ||
|  |             iterateKeywords(it, group); | ||
|  |             if (types.length === 1 && types[0] === group.type && typeErrors) { | ||
|  |                 gen.else(); | ||
|  |                 (0, dataType_2.reportTypeError)(it); | ||
|  |             } | ||
|  |             gen.endIf(); | ||
|  |         } | ||
|  |         else { | ||
|  |             iterateKeywords(it, group); | ||
|  |         } | ||
|  |         // TODO make it "ok" call?
 | ||
|  |         if (!allErrors) | ||
|  |             gen.if((0, codegen_1._) `${names_1.default.errors} === ${errsCount || 0}`); | ||
|  |     } | ||
|  | } | ||
|  | function iterateKeywords(it, group) { | ||
|  |     const { gen, schema, opts: { useDefaults }, } = it; | ||
|  |     if (useDefaults) | ||
|  |         (0, defaults_1.assignDefaults)(it, group.type); | ||
|  |     gen.block(() => { | ||
|  |         for (const rule of group.rules) { | ||
|  |             if ((0, applicability_1.shouldUseRule)(schema, rule)) { | ||
|  |                 keywordCode(it, rule.keyword, rule.definition, group.type); | ||
|  |             } | ||
|  |         } | ||
|  |     }); | ||
|  | } | ||
|  | function checkStrictTypes(it, types) { | ||
|  |     if (it.schemaEnv.meta || !it.opts.strictTypes) | ||
|  |         return; | ||
|  |     checkContextTypes(it, types); | ||
|  |     if (!it.opts.allowUnionTypes) | ||
|  |         checkMultipleTypes(it, types); | ||
|  |     checkKeywordTypes(it, it.dataTypes); | ||
|  | } | ||
|  | function checkContextTypes(it, types) { | ||
|  |     if (!types.length) | ||
|  |         return; | ||
|  |     if (!it.dataTypes.length) { | ||
|  |         it.dataTypes = types; | ||
|  |         return; | ||
|  |     } | ||
|  |     types.forEach((t) => { | ||
|  |         if (!includesType(it.dataTypes, t)) { | ||
|  |             strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`); | ||
|  |         } | ||
|  |     }); | ||
|  |     it.dataTypes = it.dataTypes.filter((t) => includesType(types, t)); | ||
|  | } | ||
|  | function checkMultipleTypes(it, ts) { | ||
|  |     if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) { | ||
|  |         strictTypesError(it, "use allowUnionTypes to allow union type keyword"); | ||
|  |     } | ||
|  | } | ||
|  | function checkKeywordTypes(it, ts) { | ||
|  |     const rules = it.self.RULES.all; | ||
|  |     for (const keyword in rules) { | ||
|  |         const rule = rules[keyword]; | ||
|  |         if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) { | ||
|  |             const { type } = rule.definition; | ||
|  |             if (type.length && !type.some((t) => hasApplicableType(ts, t))) { | ||
|  |                 strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | function hasApplicableType(schTs, kwdT) { | ||
|  |     return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer")); | ||
|  | } | ||
|  | function includesType(ts, t) { | ||
|  |     return ts.includes(t) || (t === "integer" && ts.includes("number")); | ||
|  | } | ||
|  | function strictTypesError(it, msg) { | ||
|  |     const schemaPath = it.schemaEnv.baseId + it.errSchemaPath; | ||
|  |     msg += ` at "${schemaPath}" (strictTypes)`; | ||
|  |     (0, util_1.checkStrictMode)(it, msg, it.opts.strictTypes); | ||
|  | } | ||
|  | class KeywordCxt { | ||
|  |     constructor(it, def, keyword) { | ||
|  |         (0, keyword_1.validateKeywordUsage)(it, def, keyword); | ||
|  |         this.gen = it.gen; | ||
|  |         this.allErrors = it.allErrors; | ||
|  |         this.keyword = keyword; | ||
|  |         this.data = it.data; | ||
|  |         this.schema = it.schema[keyword]; | ||
|  |         this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data; | ||
|  |         this.schemaValue = (0, util_1.schemaRefOrVal)(it, this.schema, keyword, this.$data); | ||
|  |         this.schemaType = def.schemaType; | ||
|  |         this.parentSchema = it.schema; | ||
|  |         this.params = {}; | ||
|  |         this.it = it; | ||
|  |         this.def = def; | ||
|  |         if (this.$data) { | ||
|  |             this.schemaCode = it.gen.const("vSchema", getData(this.$data, it)); | ||
|  |         } | ||
|  |         else { | ||
|  |             this.schemaCode = this.schemaValue; | ||
|  |             if (!(0, keyword_1.validSchemaType)(this.schema, def.schemaType, def.allowUndefined)) { | ||
|  |                 throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`); | ||
|  |             } | ||
|  |         } | ||
|  |         if ("code" in def ? def.trackErrors : def.errors !== false) { | ||
|  |             this.errsCount = it.gen.const("_errs", names_1.default.errors); | ||
|  |         } | ||
|  |     } | ||
|  |     result(condition, successAction, failAction) { | ||
|  |         this.failResult((0, codegen_1.not)(condition), successAction, failAction); | ||
|  |     } | ||
|  |     failResult(condition, successAction, failAction) { | ||
|  |         this.gen.if(condition); | ||
|  |         if (failAction) | ||
|  |             failAction(); | ||
|  |         else | ||
|  |             this.error(); | ||
|  |         if (successAction) { | ||
|  |             this.gen.else(); | ||
|  |             successAction(); | ||
|  |             if (this.allErrors) | ||
|  |                 this.gen.endIf(); | ||
|  |         } | ||
|  |         else { | ||
|  |             if (this.allErrors) | ||
|  |                 this.gen.endIf(); | ||
|  |             else | ||
|  |                 this.gen.else(); | ||
|  |         } | ||
|  |     } | ||
|  |     pass(condition, failAction) { | ||
|  |         this.failResult((0, codegen_1.not)(condition), undefined, failAction); | ||
|  |     } | ||
|  |     fail(condition) { | ||
|  |         if (condition === undefined) { | ||
|  |             this.error(); | ||
|  |             if (!this.allErrors) | ||
|  |                 this.gen.if(false); // this branch will be removed by gen.optimize
 | ||
|  |             return; | ||
|  |         } | ||
|  |         this.gen.if(condition); | ||
|  |         this.error(); | ||
|  |         if (this.allErrors) | ||
|  |             this.gen.endIf(); | ||
|  |         else | ||
|  |             this.gen.else(); | ||
|  |     } | ||
|  |     fail$data(condition) { | ||
|  |         if (!this.$data) | ||
|  |             return this.fail(condition); | ||
|  |         const { schemaCode } = this; | ||
|  |         this.fail((0, codegen_1._) `${schemaCode} !== undefined && (${(0, codegen_1.or)(this.invalid$data(), condition)})`); | ||
|  |     } | ||
|  |     error(append, errorParams, errorPaths) { | ||
|  |         if (errorParams) { | ||
|  |             this.setParams(errorParams); | ||
|  |             this._error(append, errorPaths); | ||
|  |             this.setParams({}); | ||
|  |             return; | ||
|  |         } | ||
|  |         this._error(append, errorPaths); | ||
|  |     } | ||
|  |     _error(append, errorPaths) { | ||
|  |         ; | ||
|  |         (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error, errorPaths); | ||
|  |     } | ||
|  |     $dataError() { | ||
|  |         (0, errors_1.reportError)(this, this.def.$dataError || errors_1.keyword$DataError); | ||
|  |     } | ||
|  |     reset() { | ||
|  |         if (this.errsCount === undefined) | ||
|  |             throw new Error('add "trackErrors" to keyword definition'); | ||
|  |         (0, errors_1.resetErrorsCount)(this.gen, this.errsCount); | ||
|  |     } | ||
|  |     ok(cond) { | ||
|  |         if (!this.allErrors) | ||
|  |             this.gen.if(cond); | ||
|  |     } | ||
|  |     setParams(obj, assign) { | ||
|  |         if (assign) | ||
|  |             Object.assign(this.params, obj); | ||
|  |         else | ||
|  |             this.params = obj; | ||
|  |     } | ||
|  |     block$data(valid, codeBlock, $dataValid = codegen_1.nil) { | ||
|  |         this.gen.block(() => { | ||
|  |             this.check$data(valid, $dataValid); | ||
|  |             codeBlock(); | ||
|  |         }); | ||
|  |     } | ||
|  |     check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) { | ||
|  |         if (!this.$data) | ||
|  |             return; | ||
|  |         const { gen, schemaCode, schemaType, def } = this; | ||
|  |         gen.if((0, codegen_1.or)((0, codegen_1._) `${schemaCode} === undefined`, $dataValid)); | ||
|  |         if (valid !== codegen_1.nil) | ||
|  |             gen.assign(valid, true); | ||
|  |         if (schemaType.length || def.validateSchema) { | ||
|  |             gen.elseIf(this.invalid$data()); | ||
|  |             this.$dataError(); | ||
|  |             if (valid !== codegen_1.nil) | ||
|  |                 gen.assign(valid, false); | ||
|  |         } | ||
|  |         gen.else(); | ||
|  |     } | ||
|  |     invalid$data() { | ||
|  |         const { gen, schemaCode, schemaType, def, it } = this; | ||
|  |         return (0, codegen_1.or)(wrong$DataType(), invalid$DataSchema()); | ||
|  |         function wrong$DataType() { | ||
|  |             if (schemaType.length) { | ||
|  |                 /* istanbul ignore if */ | ||
|  |                 if (!(schemaCode instanceof codegen_1.Name)) | ||
|  |                     throw new Error("ajv implementation error"); | ||
|  |                 const st = Array.isArray(schemaType) ? schemaType : [schemaType]; | ||
|  |                 return (0, codegen_1._) `${(0, dataType_2.checkDataTypes)(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`; | ||
|  |             } | ||
|  |             return codegen_1.nil; | ||
|  |         } | ||
|  |         function invalid$DataSchema() { | ||
|  |             if (def.validateSchema) { | ||
|  |                 const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone
 | ||
|  |                 return (0, codegen_1._) `!${validateSchemaRef}(${schemaCode})`; | ||
|  |             } | ||
|  |             return codegen_1.nil; | ||
|  |         } | ||
|  |     } | ||
|  |     subschema(appl, valid) { | ||
|  |         const subschema = (0, subschema_1.getSubschema)(this.it, appl); | ||
|  |         (0, subschema_1.extendSubschemaData)(subschema, this.it, appl); | ||
|  |         (0, subschema_1.extendSubschemaMode)(subschema, appl); | ||
|  |         const nextContext = { ...this.it, ...subschema, items: undefined, props: undefined }; | ||
|  |         subschemaCode(nextContext, valid); | ||
|  |         return nextContext; | ||
|  |     } | ||
|  |     mergeEvaluated(schemaCxt, toName) { | ||
|  |         const { it, gen } = this; | ||
|  |         if (!it.opts.unevaluated) | ||
|  |             return; | ||
|  |         if (it.props !== true && schemaCxt.props !== undefined) { | ||
|  |             it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName); | ||
|  |         } | ||
|  |         if (it.items !== true && schemaCxt.items !== undefined) { | ||
|  |             it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName); | ||
|  |         } | ||
|  |     } | ||
|  |     mergeValidEvaluated(schemaCxt, valid) { | ||
|  |         const { it, gen } = this; | ||
|  |         if (it.opts.unevaluated && (it.props !== true || it.items !== true)) { | ||
|  |             gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name)); | ||
|  |             return true; | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | exports.KeywordCxt = KeywordCxt; | ||
|  | function keywordCode(it, keyword, def, ruleType) { | ||
|  |     const cxt = new KeywordCxt(it, def, keyword); | ||
|  |     if ("code" in def) { | ||
|  |         def.code(cxt, ruleType); | ||
|  |     } | ||
|  |     else if (cxt.$data && def.validate) { | ||
|  |         (0, keyword_1.funcKeywordCode)(cxt, def); | ||
|  |     } | ||
|  |     else if ("macro" in def) { | ||
|  |         (0, keyword_1.macroKeywordCode)(cxt, def); | ||
|  |     } | ||
|  |     else if (def.compile || def.validate) { | ||
|  |         (0, keyword_1.funcKeywordCode)(cxt, def); | ||
|  |     } | ||
|  | } | ||
|  | const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/; | ||
|  | const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; | ||
|  | function getData($data, { dataLevel, dataNames, dataPathArr }) { | ||
|  |     let jsonPointer; | ||
|  |     let data; | ||
|  |     if ($data === "") | ||
|  |         return names_1.default.rootData; | ||
|  |     if ($data[0] === "/") { | ||
|  |         if (!JSON_POINTER.test($data)) | ||
|  |             throw new Error(`Invalid JSON-pointer: ${$data}`); | ||
|  |         jsonPointer = $data; | ||
|  |         data = names_1.default.rootData; | ||
|  |     } | ||
|  |     else { | ||
|  |         const matches = RELATIVE_JSON_POINTER.exec($data); | ||
|  |         if (!matches) | ||
|  |             throw new Error(`Invalid JSON-pointer: ${$data}`); | ||
|  |         const up = +matches[1]; | ||
|  |         jsonPointer = matches[2]; | ||
|  |         if (jsonPointer === "#") { | ||
|  |             if (up >= dataLevel) | ||
|  |                 throw new Error(errorMsg("property/index", up)); | ||
|  |             return dataPathArr[dataLevel - up]; | ||
|  |         } | ||
|  |         if (up > dataLevel) | ||
|  |             throw new Error(errorMsg("data", up)); | ||
|  |         data = dataNames[dataLevel - up]; | ||
|  |         if (!jsonPointer) | ||
|  |             return data; | ||
|  |     } | ||
|  |     let expr = data; | ||
|  |     const segments = jsonPointer.split("/"); | ||
|  |     for (const segment of segments) { | ||
|  |         if (segment) { | ||
|  |             data = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)((0, util_1.unescapeJsonPointer)(segment))}`; | ||
|  |             expr = (0, codegen_1._) `${expr} && ${data}`; | ||
|  |         } | ||
|  |     } | ||
|  |     return expr; | ||
|  |     function errorMsg(pointerType, up) { | ||
|  |         return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`; | ||
|  |     } | ||
|  | } | ||
|  | exports.getData = getData; | ||
|  | //# sourceMappingURL=index.js.map
 |