Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/ajv/lib/dotjs/validate.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
482 lines (479 sloc)
19.5 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
module.exports = function generate_validate(it, $keyword, $ruleType) { | |
var out = ''; | |
var $async = it.schema.$async === true, | |
$refKeywords = it.util.schemaHasRulesExcept(it.schema, it.RULES.all, '$ref'), | |
$id = it.self._getId(it.schema); | |
if (it.opts.strictKeywords) { | |
var $unknownKwd = it.util.schemaUnknownRules(it.schema, it.RULES.keywords); | |
if ($unknownKwd) { | |
var $keywordsMsg = 'unknown keyword: ' + $unknownKwd; | |
if (it.opts.strictKeywords === 'log') it.logger.warn($keywordsMsg); | |
else throw new Error($keywordsMsg); | |
} | |
} | |
if (it.isTop) { | |
out += ' var validate = '; | |
if ($async) { | |
it.async = true; | |
out += 'async '; | |
} | |
out += 'function(data, dataPath, parentData, parentDataProperty, rootData) { \'use strict\'; '; | |
if ($id && (it.opts.sourceCode || it.opts.processCode)) { | |
out += ' ' + ('/\*# sourceURL=' + $id + ' */') + ' '; | |
} | |
} | |
if (typeof it.schema == 'boolean' || !($refKeywords || it.schema.$ref)) { | |
var $keyword = 'false schema'; | |
var $lvl = it.level; | |
var $dataLvl = it.dataLevel; | |
var $schema = it.schema[$keyword]; | |
var $schemaPath = it.schemaPath + it.util.getProperty($keyword); | |
var $errSchemaPath = it.errSchemaPath + '/' + $keyword; | |
var $breakOnError = !it.opts.allErrors; | |
var $errorKeyword; | |
var $data = 'data' + ($dataLvl || ''); | |
var $valid = 'valid' + $lvl; | |
if (it.schema === false) { | |
if (it.isTop) { | |
$breakOnError = true; | |
} else { | |
out += ' var ' + ($valid) + ' = false; '; | |
} | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'false schema') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: {} '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'boolean schema is false\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
} else { | |
if (it.isTop) { | |
if ($async) { | |
out += ' return data; '; | |
} else { | |
out += ' validate.errors = null; return true; '; | |
} | |
} else { | |
out += ' var ' + ($valid) + ' = true; '; | |
} | |
} | |
if (it.isTop) { | |
out += ' }; return validate; '; | |
} | |
return out; | |
} | |
if (it.isTop) { | |
var $top = it.isTop, | |
$lvl = it.level = 0, | |
$dataLvl = it.dataLevel = 0, | |
$data = 'data'; | |
it.rootId = it.resolve.fullPath(it.self._getId(it.root.schema)); | |
it.baseId = it.baseId || it.rootId; | |
delete it.isTop; | |
it.dataPathArr = [""]; | |
if (it.schema.default !== undefined && it.opts.useDefaults && it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored in the schema root'; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
out += ' var vErrors = null; '; | |
out += ' var errors = 0; '; | |
out += ' if (rootData === undefined) rootData = data; '; | |
} else { | |
var $lvl = it.level, | |
$dataLvl = it.dataLevel, | |
$data = 'data' + ($dataLvl || ''); | |
if ($id) it.baseId = it.resolve.url(it.baseId, $id); | |
if ($async && !it.async) throw new Error('async schema in sync schema'); | |
out += ' var errs_' + ($lvl) + ' = errors;'; | |
} | |
var $valid = 'valid' + $lvl, | |
$breakOnError = !it.opts.allErrors, | |
$closingBraces1 = '', | |
$closingBraces2 = ''; | |
var $errorKeyword; | |
var $typeSchema = it.schema.type, | |
$typeIsArray = Array.isArray($typeSchema); | |
if ($typeSchema && it.opts.nullable && it.schema.nullable === true) { | |
if ($typeIsArray) { | |
if ($typeSchema.indexOf('null') == -1) $typeSchema = $typeSchema.concat('null'); | |
} else if ($typeSchema != 'null') { | |
$typeSchema = [$typeSchema, 'null']; | |
$typeIsArray = true; | |
} | |
} | |
if ($typeIsArray && $typeSchema.length == 1) { | |
$typeSchema = $typeSchema[0]; | |
$typeIsArray = false; | |
} | |
if (it.schema.$ref && $refKeywords) { | |
if (it.opts.extendRefs == 'fail') { | |
throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)'); | |
} else if (it.opts.extendRefs !== true) { | |
$refKeywords = false; | |
it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"'); | |
} | |
} | |
if (it.schema.$comment && it.opts.$comment) { | |
out += ' ' + (it.RULES.all.$comment.code(it, '$comment')); | |
} | |
if ($typeSchema) { | |
if (it.opts.coerceTypes) { | |
var $coerceToTypes = it.util.coerceToTypes(it.opts.coerceTypes, $typeSchema); | |
} | |
var $rulesGroup = it.RULES.types[$typeSchema]; | |
if ($coerceToTypes || $typeIsArray || $rulesGroup === true || ($rulesGroup && !$shouldUseGroup($rulesGroup))) { | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type'; | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type', | |
$method = $typeIsArray ? 'checkDataTypes' : 'checkDataType'; | |
out += ' if (' + (it.util[$method]($typeSchema, $data, it.opts.strictNumbers, true)) + ') { '; | |
if ($coerceToTypes) { | |
var $dataType = 'dataType' + $lvl, | |
$coerced = 'coerced' + $lvl; | |
out += ' var ' + ($dataType) + ' = typeof ' + ($data) + '; var ' + ($coerced) + ' = undefined; '; | |
if (it.opts.coerceTypes == 'array') { | |
out += ' if (' + ($dataType) + ' == \'object\' && Array.isArray(' + ($data) + ') && ' + ($data) + '.length == 1) { ' + ($data) + ' = ' + ($data) + '[0]; ' + ($dataType) + ' = typeof ' + ($data) + '; if (' + (it.util.checkDataType(it.schema.type, $data, it.opts.strictNumbers)) + ') ' + ($coerced) + ' = ' + ($data) + '; } '; | |
} | |
out += ' if (' + ($coerced) + ' !== undefined) ; '; | |
var arr1 = $coerceToTypes; | |
if (arr1) { | |
var $type, $i = -1, | |
l1 = arr1.length - 1; | |
while ($i < l1) { | |
$type = arr1[$i += 1]; | |
if ($type == 'string') { | |
out += ' else if (' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\') ' + ($coerced) + ' = \'\' + ' + ($data) + '; else if (' + ($data) + ' === null) ' + ($coerced) + ' = \'\'; '; | |
} else if ($type == 'number' || $type == 'integer') { | |
out += ' else if (' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' === null || (' + ($dataType) + ' == \'string\' && ' + ($data) + ' && ' + ($data) + ' == +' + ($data) + ' '; | |
if ($type == 'integer') { | |
out += ' && !(' + ($data) + ' % 1)'; | |
} | |
out += ')) ' + ($coerced) + ' = +' + ($data) + '; '; | |
} else if ($type == 'boolean') { | |
out += ' else if (' + ($data) + ' === \'false\' || ' + ($data) + ' === 0 || ' + ($data) + ' === null) ' + ($coerced) + ' = false; else if (' + ($data) + ' === \'true\' || ' + ($data) + ' === 1) ' + ($coerced) + ' = true; '; | |
} else if ($type == 'null') { | |
out += ' else if (' + ($data) + ' === \'\' || ' + ($data) + ' === 0 || ' + ($data) + ' === false) ' + ($coerced) + ' = null; '; | |
} else if (it.opts.coerceTypes == 'array' && $type == 'array') { | |
out += ' else if (' + ($dataType) + ' == \'string\' || ' + ($dataType) + ' == \'number\' || ' + ($dataType) + ' == \'boolean\' || ' + ($data) + ' == null) ' + ($coerced) + ' = [' + ($data) + ']; '; | |
} | |
} | |
} | |
out += ' else { '; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } if (' + ($coerced) + ' !== undefined) { '; | |
var $parentData = $dataLvl ? 'data' + (($dataLvl - 1) || '') : 'parentData', | |
$parentDataProperty = $dataLvl ? it.dataPathArr[$dataLvl] : 'parentDataProperty'; | |
out += ' ' + ($data) + ' = ' + ($coerced) + '; '; | |
if (!$dataLvl) { | |
out += 'if (' + ($parentData) + ' !== undefined)'; | |
} | |
out += ' ' + ($parentData) + '[' + ($parentDataProperty) + '] = ' + ($coerced) + '; } '; | |
} else { | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
} | |
out += ' } '; | |
} | |
} | |
if (it.schema.$ref && !$refKeywords) { | |
out += ' ' + (it.RULES.all.$ref.code(it, '$ref')) + ' '; | |
if ($breakOnError) { | |
out += ' } if (errors === '; | |
if ($top) { | |
out += '0'; | |
} else { | |
out += 'errs_' + ($lvl); | |
} | |
out += ') { '; | |
$closingBraces2 += '}'; | |
} | |
} else { | |
var arr2 = it.RULES; | |
if (arr2) { | |
var $rulesGroup, i2 = -1, | |
l2 = arr2.length - 1; | |
while (i2 < l2) { | |
$rulesGroup = arr2[i2 += 1]; | |
if ($shouldUseGroup($rulesGroup)) { | |
if ($rulesGroup.type) { | |
out += ' if (' + (it.util.checkDataType($rulesGroup.type, $data, it.opts.strictNumbers)) + ') { '; | |
} | |
if (it.opts.useDefaults) { | |
if ($rulesGroup.type == 'object' && it.schema.properties) { | |
var $schema = it.schema.properties, | |
$schemaKeys = Object.keys($schema); | |
var arr3 = $schemaKeys; | |
if (arr3) { | |
var $propertyKey, i3 = -1, | |
l3 = arr3.length - 1; | |
while (i3 < l3) { | |
$propertyKey = arr3[i3 += 1]; | |
var $sch = $schema[$propertyKey]; | |
if ($sch.default !== undefined) { | |
var $passData = $data + it.util.getProperty($propertyKey); | |
if (it.compositeRule) { | |
if (it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored for: ' + $passData; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
} else { | |
out += ' if (' + ($passData) + ' === undefined '; | |
if (it.opts.useDefaults == 'empty') { | |
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' '; | |
} | |
out += ' ) ' + ($passData) + ' = '; | |
if (it.opts.useDefaults == 'shared') { | |
out += ' ' + (it.useDefault($sch.default)) + ' '; | |
} else { | |
out += ' ' + (JSON.stringify($sch.default)) + ' '; | |
} | |
out += '; '; | |
} | |
} | |
} | |
} | |
} else if ($rulesGroup.type == 'array' && Array.isArray(it.schema.items)) { | |
var arr4 = it.schema.items; | |
if (arr4) { | |
var $sch, $i = -1, | |
l4 = arr4.length - 1; | |
while ($i < l4) { | |
$sch = arr4[$i += 1]; | |
if ($sch.default !== undefined) { | |
var $passData = $data + '[' + $i + ']'; | |
if (it.compositeRule) { | |
if (it.opts.strictDefaults) { | |
var $defaultMsg = 'default is ignored for: ' + $passData; | |
if (it.opts.strictDefaults === 'log') it.logger.warn($defaultMsg); | |
else throw new Error($defaultMsg); | |
} | |
} else { | |
out += ' if (' + ($passData) + ' === undefined '; | |
if (it.opts.useDefaults == 'empty') { | |
out += ' || ' + ($passData) + ' === null || ' + ($passData) + ' === \'\' '; | |
} | |
out += ' ) ' + ($passData) + ' = '; | |
if (it.opts.useDefaults == 'shared') { | |
out += ' ' + (it.useDefault($sch.default)) + ' '; | |
} else { | |
out += ' ' + (JSON.stringify($sch.default)) + ' '; | |
} | |
out += '; '; | |
} | |
} | |
} | |
} | |
} | |
} | |
var arr5 = $rulesGroup.rules; | |
if (arr5) { | |
var $rule, i5 = -1, | |
l5 = arr5.length - 1; | |
while (i5 < l5) { | |
$rule = arr5[i5 += 1]; | |
if ($shouldUseRule($rule)) { | |
var $code = $rule.code(it, $rule.keyword, $rulesGroup.type); | |
if ($code) { | |
out += ' ' + ($code) + ' '; | |
if ($breakOnError) { | |
$closingBraces1 += '}'; | |
} | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces1) + ' '; | |
$closingBraces1 = ''; | |
} | |
if ($rulesGroup.type) { | |
out += ' } '; | |
if ($typeSchema && $typeSchema === $rulesGroup.type && !$coerceToTypes) { | |
out += ' else { '; | |
var $schemaPath = it.schemaPath + '.type', | |
$errSchemaPath = it.errSchemaPath + '/type'; | |
var $$outStack = $$outStack || []; | |
$$outStack.push(out); | |
out = ''; /* istanbul ignore else */ | |
if (it.createErrors !== false) { | |
out += ' { keyword: \'' + ($errorKeyword || 'type') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { type: \''; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' } '; | |
if (it.opts.messages !== false) { | |
out += ' , message: \'should be '; | |
if ($typeIsArray) { | |
out += '' + ($typeSchema.join(",")); | |
} else { | |
out += '' + ($typeSchema); | |
} | |
out += '\' '; | |
} | |
if (it.opts.verbose) { | |
out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' '; | |
} | |
out += ' } '; | |
} else { | |
out += ' {} '; | |
} | |
var __err = out; | |
out = $$outStack.pop(); | |
if (!it.compositeRule && $breakOnError) { | |
/* istanbul ignore if */ | |
if (it.async) { | |
out += ' throw new ValidationError([' + (__err) + ']); '; | |
} else { | |
out += ' validate.errors = [' + (__err) + ']; return false; '; | |
} | |
} else { | |
out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; '; | |
} | |
out += ' } '; | |
} | |
} | |
if ($breakOnError) { | |
out += ' if (errors === '; | |
if ($top) { | |
out += '0'; | |
} else { | |
out += 'errs_' + ($lvl); | |
} | |
out += ') { '; | |
$closingBraces2 += '}'; | |
} | |
} | |
} | |
} | |
} | |
if ($breakOnError) { | |
out += ' ' + ($closingBraces2) + ' '; | |
} | |
if ($top) { | |
if ($async) { | |
out += ' if (errors === 0) return data; '; | |
out += ' else throw new ValidationError(vErrors); '; | |
} else { | |
out += ' validate.errors = vErrors; '; | |
out += ' return errors === 0; '; | |
} | |
out += ' }; return validate;'; | |
} else { | |
out += ' var ' + ($valid) + ' = errors === errs_' + ($lvl) + ';'; | |
} | |
function $shouldUseGroup($rulesGroup) { | |
var rules = $rulesGroup.rules; | |
for (var i = 0; i < rules.length; i++) | |
if ($shouldUseRule(rules[i])) return true; | |
} | |
function $shouldUseRule($rule) { | |
return it.schema[$rule.keyword] !== undefined || ($rule.implements && $ruleImplementsSomeKeyword($rule)); | |
} | |
function $ruleImplementsSomeKeyword($rule) { | |
var impl = $rule.implements; | |
for (var i = 0; i < impl.length; i++) | |
if (it.schema[impl[i]] !== undefined) return true; | |
} | |
return out; | |
} |