From 34a98e273a573f1b5f0a5948fcaaa788a2d5a5c3 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Wed, 3 Jun 2015 01:36:59 +0100 Subject: [PATCH] refactor with defs; use numbered variable names in different levels --- lib/compile/index.js | 24 +++--- lib/compile/rules/$ref.dot.js | 20 ++--- lib/compile/rules/allOf.dot.js | 24 ++---- lib/compile/rules/anyOf.dot.js | 21 ++--- lib/compile/rules/definitions.def.js | 104 +++++++++++++++++++++++ lib/compile/rules/dependencies.dot.js | 63 ++++++-------- lib/compile/rules/enum.dot.js | 18 ++-- lib/compile/rules/format.dot.js | 22 +++-- lib/compile/rules/index.js | 3 +- lib/compile/rules/items.dot.js | 80 +++++++----------- lib/compile/rules/maxItems.dot.js | 12 ++- lib/compile/rules/maxLength.dot.js | 12 ++- lib/compile/rules/maxProperties.dot.js | 13 ++- lib/compile/rules/maximum.dot.js | 13 ++- lib/compile/rules/minItems.dot.js | 12 ++- lib/compile/rules/minLength.dot.js | 12 ++- lib/compile/rules/minProperties.dot.js | 13 ++- lib/compile/rules/minimum.dot.js | 12 ++- lib/compile/rules/multipleOf.dot.js | 14 ++-- lib/compile/rules/not.dot.js | 24 +++--- lib/compile/rules/oneOf.dot.js | 37 ++++----- lib/compile/rules/pattern.dot.js | 14 ++-- lib/compile/rules/properties.dot.js | 108 +++++++++--------------- lib/compile/rules/required.dot.js | 31 +++---- lib/compile/rules/type.dot.js | 17 ++-- lib/compile/rules/uniqueItems.dot.js | 22 ++--- lib/compile/validate.dot.js | 54 +++++++----- package.json | 2 +- spec/json-schema.spec.js | 20 +++-- try.js | 109 +++++++++++-------------- 30 files changed, 458 insertions(+), 472 deletions(-) create mode 100644 lib/compile/rules/definitions.def.js diff --git a/lib/compile/index.js b/lib/compile/index.js index 53fa262..b7fa319 100644 --- a/lib/compile/index.js +++ b/lib/compile/index.js @@ -64,34 +64,36 @@ function copy(o, to) { } -function checkDataType(dataType) { +function checkDataType(dataType, lvl) { + var data = 'data' + lvl; switch (dataType) { - case 'null': return 'data === null'; - case 'array': return 'Array.isArray(data)'; - case 'object': return '(data && typeof data == "object" && !Array.isArray(data))'; - case 'integer': return '(typeof data == "number" && !(data % 1))' - default: return 'typeof data == "' + dataType + '"'; + case 'null': return data + ' === null'; + case 'array': return 'Array.isArray(' + data + ')'; + case 'object': return '(' + data + ' && typeof ' + data + ' == "object" && !Array.isArray(' + data + '))'; + case 'integer': return '(typeof ' + data + ' == "number" && !(' + data + ' % 1))' + default: return 'typeof ' + data + ' == "' + dataType + '"'; } } -function checkDataTypes(dataTypes) { +function checkDataTypes(dataTypes, lvl) { + var data = 'data' + lvl; switch (dataTypes.length) { case 0: return 'true'; - case 1: return checkDataType(dataTypes[0]); + case 1: return checkDataType(dataTypes[0], lvl); default: var code = '' var types = toHash(dataTypes); if (types.array && types.object) { - code = types.null ? '(': '(data && ' - code += 'typeof data == "object")'; + code = types.null ? '(': '(' + data + ' && ' + code += 'typeof ' + data + ' == "object")'; delete types.null; delete types.array; delete types.object; } if (types.number) delete types.integer; for (var t in types) - code += (code ? '||' : '' ) + checkDataType(t); + code += (code ? '||' : '' ) + checkDataType(t, lvl); return code; } diff --git a/lib/compile/rules/$ref.dot.js b/lib/compile/rules/$ref.dot.js index 3587576..fd88763 100644 --- a/lib/compile/rules/$ref.dot.js +++ b/lib/compile/rules/$ref.dot.js @@ -1,13 +1,11 @@ -{{? it.resolveRef(it.schema.$ref) }} - var result = validateRef('{{= it.schema.$ref }}', data, dataPath); - if (!result.valid) validate.errors.push.apply(validate.errors, result.errors); - var valid = result.valid; +{{# def.definitions }} +{{# def.setup:'$ref' }} + +{{? it.resolveRef($schema) }} + var result{{=$lvl}} = validateRef('{{=$schema}}', data{{=$dataLvl}}, dataPath{{=$dataLvl}}); + valid = result{{=$lvl}}.valid; + if (!valid) validate.errors.push.apply(validate.errors, result{{=$lvl}}.errors); {{??}} - validate.errors.push({ - keyword: '$ref', - dataPath: dataPath, - message: 'can\'t resolve reference {{= it.schema.$ref}}' - {{? it.opts.verbose }}, schema: '{{= it.schema.$ref }}', data: data{{?}} - }); - var valid = false; + {{# def.error:'$ref' }} + valid = false; {{?}} diff --git a/lib/compile/rules/allOf.dot.js b/lib/compile/rules/allOf.dot.js index 03f211b..121a660 100644 --- a/lib/compile/rules/allOf.dot.js +++ b/lib/compile/rules/allOf.dot.js @@ -1,24 +1,18 @@ +{{# def.definitions }} +{{# def.setup:'allOf' }} +{{# def.setupNextLevel }} + var valid = true; -{{ - var $it = it.copy(it) - , $closingBraces = '' - , $level = it.level; - $it.level++; -}} - -{{~ it.schema.allOf:$schema:$i }} - {{? !it.opts.allErrors && $i }} - {{ $closingBraces += '}'; }} - if (valid) { - {{?}} +{{~ $schema:$sch:$i }} + {{? $i}} {{# def.ifValid }} {{?}} {{ - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.allOf[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; }} - valid = valid && ({{= it.validate($it) }})(data, dataPath); + valid = valid && ({{= it.validate($it) }})(data{{=$dataLvl}}, dataPath{{=$dataLvl}}); {{~}} {{= $closingBraces }} diff --git a/lib/compile/rules/anyOf.dot.js b/lib/compile/rules/anyOf.dot.js index d02b823..0dfa554 100644 --- a/lib/compile/rules/anyOf.dot.js +++ b/lib/compile/rules/anyOf.dot.js @@ -1,27 +1,24 @@ -{{ - var $it = it.copy(it) - , $closingBraces = '' - , $level = it.level; - $it.level++; -}} +{{# def.definitions }} +{{# def.setup:'anyOf' }} +{{# def.setupNextLevel }} -var errs{{= $level}} = validate.errors.length; +var errs{{=$lvl}} = validate.errors.length; var valid = false; -{{~ it.schema.anyOf:$schema:$i }} +{{~ $schema:$sch:$i }} {{? $i }} {{ $closingBraces += '}'; }} if (!valid) { {{?}} {{ - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.anyOf[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; }} - valid = valid || ({{= it.validate($it) }})(data, dataPath); + valid = valid || ({{= it.validate($it) }})(data{{=$dataLvl}}, dataPath{{=$dataLvl}}); {{~}} {{= $closingBraces }} -if (valid) validate.errors.length = errs{{= $level}}; +if (valid) validate.errors.length = errs{{=$lvl}}; diff --git a/lib/compile/rules/definitions.def.js b/lib/compile/rules/definitions.def.js new file mode 100644 index 0000000..22d20e9 --- /dev/null +++ b/lib/compile/rules/definitions.def.js @@ -0,0 +1,104 @@ +{{## def.setup:keyword: + {{ + var $lvl = it.level + , $dataLvl = it.dataLevel + , $schema = it.schema[keyword] + , $schemaPath = it.schemaPath + '.' + keyword; + }} +#}} + + +{{## def.setupNextLevel: + {{ + var $it = it.copy(it) + , $closingBraces = '' + , $breakOnError = !it.opts.allErrors; + $it.level++; + }} +#}} + + +{{## def.ifValid: + {{? $breakOnError }} + if (valid) { + {{ $closingBraces += '}'; }} + {{?}} +#}} + + +{{## def.elseIfValid: + {{? $breakOnError }} + {{ $closingBraces += '}'; }} + else { + {{?}} +#}} + + +{{## def.cleanUp: + {{ out = out.replace(/if \(valid\) \{\s*\}/g, ''); }} +#}} + + +{{## def.error:keyword: + validate.errors.push({ + keyword: '{{=keyword}}', + dataPath: dataPath{{=$dataLvl}}, + message: {{# def._errorMessages[keyword] }} + {{? it.opts.verbose }}, schema: {{# def._errorSchemas[keyword] }}, data: data{{=$dataLvl}}{{?}} + }); +#}} + + +{{## def.checkError:keyword: + if (!valid) {{# def.error:keyword }} +#}} + + +{{## def._errorMessages = { + $ref: "'can\\\'t resolve reference {{=$schema}}'", + additionalItems: "'should NOT have more than {{=$schema.length}} items'", + additionalProperties: "'additional properties NOT allowed'", + dependencies: "'{{? $deps.length == 1 }}property {{= $deps[0] }} is{{??}}properties {{= $deps.join(\", \") }} are{{?}} required when property {{= $property }} is present'", + enum: "'should be equal to one of values'", + format: "'should match format {{=$schema}}'", + maximum: "'should be {{=$op}} {{=$schema}}'", + minimum: "'should be {{=$op}} {{=$schema}}'", + maxItems: "'should NOT have more than {{=$schema}} items'", + minItems: "'should NOT have less than {{=$schema}} items'", + maxLength: "'should NOT be longer than {{=$schema}} characters'", + minLength: "'should NOT be shorter than {{=$schema}} characters'", + maxProperties: "'should NOT have more than {{=$schema}} properties'", + minProperties: "'should NOT have less than {{=$schema}} properties'", + multipleOf: "'should be multiple of {{=$schema}}'", + not: "'should NOT be valid'", + oneOf: "'should match exactly one schema in oneOf'", + pattern: "'should match pattern \"{{=$schema}}\"'", + required: "'properties {{=$schema.slice(0,7).join(\", \") }}{{? $schema.length > 7}}...{{?}} are required'", + type: "'should be {{? $isArray }}{{= $schema.join(\",\") }}{{??}}{{=$schema}}{{?}}'", + uniqueItems: "'items ## ' + j{{=$lvl}} + ' and ' + i{{=$lvl}} + ' are duplicate'" +} #}} + + +{{## def._errorSchemas = { + $ref: "'{{=$schema}}'", + additionalItems: "false", + additionalProperties: "false", + dependencies: "validate.schema{{=$schemaPath}}", + enum: "validate.schema{{=$schemaPath}}", + format: "'{{=$schema}}'", + maximum: "{{=$schema}}", + minimum: "{{=$schema}}", + maxItems: "{{=$schema}}", + minItems: "{{=$schema}}", + maxLength: "{{=$schema}}", + minLength: "{{=$schema}}", + maxProperties: "{{=$schema}}", + minProperties: "{{=$schema}}", + multipleOf: "{{=$schema}}", + not: "validate.schema{{=$schemaPath}}", + oneOf: "validate.schema{{=$schemaPath}}", + pattern: "'{{=$schema}}'", + required: "validate.schema{{=$schemaPath}}", + type: "{{? $isArray }}validate.schema{{=$schemaPath}}{{??}}'{{=$schema}}'{{?}}", + uniqueItems: "{{=$schema}}" +} #}} diff --git a/lib/compile/rules/dependencies.dot.js b/lib/compile/rules/dependencies.dot.js index 37e0ecd..74353f4 100644 --- a/lib/compile/rules/dependencies.dot.js +++ b/lib/compile/rules/dependencies.dot.js @@ -1,63 +1,48 @@ -{{ - var $it = it.copy(it) - , $breakOnError = !it.opts.allErrors - , $closingBraces = '' - , $schemaDeps = {} - , $propertyDeps = {} - , $level = it.level; - $it.level++; +{{# def.definitions }} +{{# def.setup:'dependencies' }} +{{# def.setupNextLevel }} - for ($property in it.schema.dependencies) { - var $schema = it.schema.dependencies[$property]; - var $deps = Array.isArray($schema) ? $propertyDeps : $schemaDeps; - $deps[$property] = $schema; + +{{ + var $schemaDeps = {} + , $propertyDeps = {}; + + for ($property in $schema) { + var $sch = $schema[$property]; + var $deps = Array.isArray($sch) ? $propertyDeps : $schemaDeps; + $deps[$property] = $sch; } }} -var errs{{= $level}} = validate.errors.length; +var errs{{=$lvl}} = validate.errors.length; var valid; {{ for ($property in $propertyDeps) { }} - if (data.hasOwnProperty('{{= $property }}')) { + if (data{{=$dataLvl}}.hasOwnProperty('{{= $property }}')) { {{ $deps = $propertyDeps[$property]; }} - valid = {{~ $deps:$dep:$i }}{{?$i}} && {{?}}data.hasOwnProperty('{{= $dep}}'){{~}}; - if (!valid) { - validate.errors.push({ - keyword: 'dependencies', - dataPath: dataPath, - message: '{{? $deps.length == 1 }}property {{= $deps[0] }} is{{??}}properties {{= $deps.join(",") }} are{{?}} required when property {{= $property }} is present' - {{? it.opts.verbose }}, schema: validate.schema{{= it.schemaPath + '.dependencies' }}, data: data{{?}} - }); - } - {{? $breakOnError }} - {{ $closingBraces += '}'; }} - else { - {{?}} + valid = {{~ $deps:$dep:$i }}{{?$i}} && {{?}}data{{=$dataLvl}}.hasOwnProperty('{{= $dep}}'){{~}}; + {{# def.checkError:'dependencies' }} + {{# def.elseIfValid }} } {{ } }} {{ for ($property in $schemaDeps) { }} - if (data.hasOwnProperty('{{= $property }}')) { + if (data{{=$dataLvl}}.hasOwnProperty('{{= $property }}')) { {{ - var $schema = $schemaDeps[$property]; - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.dependencies["' + it.escapeQuotes($property) + '"]'; + $it.schema = $schemaDeps[$property]; + $it.schemaPath = $schemaPath + '[\'' + it.escapeQuotes($property) + '\']'; }} - {{? $breakOnError }} valid = {{?}} - ({{= it.validate($it) }})(data, dataPath); + valid = ({{= it.validate($it) }})(data{{=$dataLvl}}, dataPath{{=$dataLvl}}); } - {{? $breakOnError }} - {{ $closingBraces += '}'; }} - if (valid) { - {{?}} + {{# def.ifValid }} {{ } }} {{? $breakOnError }}{{= $closingBraces }}{{?}} -valid = errs{{= $level}} == validate.errors.length; +valid = errs{{=$lvl}} == validate.errors.length; -{{ out = out.replace(/if \(valid\) \{\s*\}/g, ''); }} +{{# def.cleanUp }} diff --git a/lib/compile/rules/enum.dot.js b/lib/compile/rules/enum.dot.js index 5be2d00..068a974 100644 --- a/lib/compile/rules/enum.dot.js +++ b/lib/compile/rules/enum.dot.js @@ -1,11 +1,11 @@ -{{ var $itemsHash = it.toHash(it.schema.enum, it.stableStringify); }} +{{# def.definitions }} +{{# def.setup:'enum' }} -var itemsHash{{= it.level }} = {{= JSON.stringify($itemsHash) }}; -var valid = itemsHash{{= it.level }}[stableStringify(data)] || false; +{{ + var $itemsHash = it.toHash($schema, it.stableStringify); +}} -if (!valid) validate.errors.push({ - keyword: 'enum', - dataPath: dataPath, - message: 'should be equal to one of values' - {{? it.opts.verbose }}, schema: validate.schema{{= it.schemaPath + '.enum' }}, data: data{{?}} -}); +var itemsHash{{=$lvl}} = {{= JSON.stringify($itemsHash) }}; +var valid = itemsHash{{=$lvl}}[stableStringify(data{{=$dataLvl}})] || false; + +{{# def.checkError:'enum' }} diff --git a/lib/compile/rules/format.dot.js b/lib/compile/rules/format.dot.js index b6a4c5c..2cfa373 100644 --- a/lib/compile/rules/format.dot.js +++ b/lib/compile/rules/format.dot.js @@ -1,16 +1,14 @@ -{{? it.opts.format !== false }} - {{ var $format = 'format' + it.level; }} - var {{=$format}} = formats['{{= it.schema.format }}']; - var valid = typeof {{=$format}} == 'function' - ? {{=$format}}(data) - : !{{=$format}} || {{=$format}}.test(data); +{{# def.definitions }} - if (!valid) validate.errors.push({ - keyword: 'format', - dataPath: dataPath, - message: 'should match format "{{= it.schema.format }}"' - {{? it.opts.verbose }}, schema: '{{= it.schema.format }}', data: data{{?}} - }); +{{? it.opts.format !== false }} + {{# def.setup:'format' }} + + var format{{=$lvl}} = formats['{{=$schema}}']; + var valid = typeof format{{=$lvl}} == 'function' + ? format{{=$lvl}}(data{{=$dataLvl}}) + : !format{{=$lvl}} || format{{=$lvl}}.test(data{{=$dataLvl}}); + + {{# def.checkError:'format' }} {{??}} var valid = true; {{?}} diff --git a/lib/compile/rules/index.js b/lib/compile/rules/index.js index f60ddeb..4c17960 100644 --- a/lib/compile/rules/index.js +++ b/lib/compile/rules/index.js @@ -3,6 +3,7 @@ var fs = require('fs') , doT = require('dot'); +var defs = fs.readFileSync(__dirname + '/definitions.def.js'); var RULES = module.exports = [ { type: 'number', @@ -22,7 +23,7 @@ RULES.forEach(function (group) { var template = fs.readFileSync(__dirname + '/' + keyword + '.dot.js'); return { keyword: keyword, - code: doT.compile(template) + code: doT.compile(template, { definitions: defs }) }; }); }); diff --git a/lib/compile/rules/items.dot.js b/lib/compile/rules/items.dot.js index 52bdab5..bbd711d 100644 --- a/lib/compile/rules/items.dot.js +++ b/lib/compile/rules/items.dot.js @@ -1,66 +1,47 @@ -{{## def.ifValid: - {{? $breakOnError }} - if (valid) { - {{ $closingBraces += '}'; }} - {{?}} -#}} +{{# def.definitions }} +{{# def.setup:'items' }} +{{# def.setupNextLevel }} + {{## def.validateItems:startFrom: - for (var i = {{= startFrom }}; i < data.length; i++) { - var data{{=$level}} = data[i] - , dataPath{{=$level}} = dataPath + '[' + i + ']'; + for (var i = {{= startFrom }}; i < data{{=$dataLvl}}.length; i++) { + var data{{=$dataNxt}} = data{{=$dataLvl}}[i] + , dataPath{{=$dataNxt}} = dataPath{{=$dataLvl}} + '[' + i + ']'; {{? $breakOnError }} valid = {{?}} - validateItems(data{{=$level}}, dataPath{{=$level}}); + validateItems(data{{=$dataNxt}}, dataPath{{=$dataNxt}}); {{? $breakOnError }} if (!valid) break; {{?}} } #}} -{{ - var $it = it.copy(it) - , $level = it.level - , $breakOnError = !it.opts.allErrors - , $closingBraces = '' - , $itemsSchema = it.schema.items; - $it.level++; -}} +{{ var $dataNxt = $it.dataLevel = it.dataLevel + 1; }} -var errs{{=$level}} = validate.errors.length; +var errs{{=$lvl}} = validate.errors.length; var valid; -{{? Array.isArray($itemsSchema) }} +{{? Array.isArray($schema) }} + {{ /* 'items' is an array of schemas */}} {{ var $additionalItems = it.schema.additionalItems; }} {{? $additionalItems === false }} - valid = data.length <= {{= $itemsSchema.length }}; - if (!valid) { - validate.errors.push({ - keyword: 'additionalItems', - dataPath: dataPath, - message: 'should NOT have more than {{= $itemsSchema.length }} items' - {{? it.opts.verbose }}, schema: false, data: data{{?}} - }); - } - {{? $breakOnError }} - {{ $closingBraces += '}'; }} - else { - {{?}} + valid = data{{=$dataLvl}}.length <= {{= $schema.length }}; + {{# def.checkError:'additionalItems' }} + {{# def.elseIfValid}} {{?}} - {{~ $itemsSchema:$schema:$index }} - {{? Object.keys($schema).length }} + {{~ $schema:$sch:$i }} + {{? Object.keys($sch).length }} valid = true; - if (data.length > {{= $index }}) { + if (data{{=$dataLvl}}.length > {{=$i}}) { {{ - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.items[' + $index + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; }} - var data{{=$level}} = data[{{= $index }}] - , dataPath{{=$level}} = dataPath + '[{{= $index }}]'; + var data{{=$dataNxt}} = data{{=$dataLvl}}[{{= $i }}] + , dataPath{{=$dataNxt}} = dataPath{{=$dataLvl}} + '[{{=$i}}]'; - {{? $breakOnError }} valid = {{?}} - ({{= it.validate($it) }})(data{{=$level}}, dataPath{{=$level}}); + valid = ({{= it.validate($it) }})(data{{=$dataNxt}}, dataPath{{=$dataNxt}}); } {{# def.ifValid }} @@ -73,18 +54,19 @@ var valid; $it.schemaPath = it.schemaPath + '.additionalItems'; }} - if (data.length > {{= $itemsSchema.length }}) { + if (data{{=$dataLvl}}.length > {{= $schema.length }}) { var validateItems = ({{= it.validate($it) }}); - {{# def.validateItems: $itemsSchema.length }} + {{# def.validateItems: $schema.length }} } {{# def.ifValid }} {{?}} -{{?? Object.keys($itemsSchema).length }} +{{?? Object.keys($schema).length }} + {{ /* 'items' is a single schema */}} {{ - $it.schema = $itemsSchema; - $it.schemaPath = it.schemaPath + '.items'; + $it.schema = $schema; + $it.schemaPath = $schemaPath; }} var validateItems = ({{= it.validate($it) }}); {{# def.validateItems: 0 }} @@ -94,6 +76,6 @@ var valid; {{? $breakOnError }} {{= $closingBraces }} {{?}} -valid = errs{{=$level}} == validate.errors.length; +valid = errs{{=$lvl}} == validate.errors.length; -{{ out = out.replace(/if \(valid\) \{\s*\}/g, ''); }} +{{# def.cleanUp }} diff --git a/lib/compile/rules/maxItems.dot.js b/lib/compile/rules/maxItems.dot.js index 1a3e34a..4f5c2f2 100644 --- a/lib/compile/rules/maxItems.dot.js +++ b/lib/compile/rules/maxItems.dot.js @@ -1,8 +1,6 @@ -var valid = data.length <= {{= it.schema.maxItems }}; +{{# def.definitions }} +{{# def.setup:'maxItems' }} -if (!valid) validate.errors.push({ - keyword: 'maxItems', - dataPath: dataPath, - message: 'should NOT have more than {{= it.schema.maxItems }} items' - {{? it.opts.verbose }}, schema: {{= it.schema.maxItems }}, data: data{{?}} -}); +var valid = data{{=$dataLvl}}.length <= {{=$schema}}; + +{{# def.checkError:'maxItems' }} diff --git a/lib/compile/rules/maxLength.dot.js b/lib/compile/rules/maxLength.dot.js index 9d8bdab..adbb705 100644 --- a/lib/compile/rules/maxLength.dot.js +++ b/lib/compile/rules/maxLength.dot.js @@ -1,8 +1,6 @@ -var valid = data.length <= {{= it.schema.maxLength }}; +{{# def.definitions }} +{{# def.setup:'maxLength' }} -if (!valid) validate.errors.push({ - keyword: 'maxLength', - dataPath: dataPath, - message: 'should NOT be longer than {{= it.schema.maxLength }} characters' - {{? it.opts.verbose }}, schema: {{= it.schema.maxLength }}, data: data{{?}} -}); +var valid = data{{=$dataLvl}}.length <= {{=$schema}}; + +{{# def.checkError:'maxLength' }} diff --git a/lib/compile/rules/maxProperties.dot.js b/lib/compile/rules/maxProperties.dot.js index c361c05..59803c0 100644 --- a/lib/compile/rules/maxProperties.dot.js +++ b/lib/compile/rules/maxProperties.dot.js @@ -1,9 +1,6 @@ -var propertiesNum = Object.keys(data).length; -var valid = propertiesNum <= {{= it.schema.maxProperties }}; +{{# def.definitions }} +{{# def.setup:'maxProperties' }} -if (!valid) validate.errors.push({ - keyword: 'maxProperties', - dataPath: dataPath, - message: 'should NOT have more than {{= it.schema.maxProperties }} properties' - {{? it.opts.verbose }}, schema: {{= it.schema.maxProperties }}, data: data{{?}} -}); +var valid = Object.keys(data{{=$dataLvl}}).length <= {{=$schema}}; + +{{# def.checkError:'maxProperties' }} diff --git a/lib/compile/rules/maximum.dot.js b/lib/compile/rules/maximum.dot.js index 8e21662..4fa9958 100644 --- a/lib/compile/rules/maximum.dot.js +++ b/lib/compile/rules/maximum.dot.js @@ -1,13 +1,12 @@ +{{# def.definitions }} +{{# def.setup:'maximum' }} + {{ var $exclusive = it.schema.exclusiveMaximum === true , $op = $exclusive ? '<' : '<='; }} -var valid = data {{= $op }} {{= it.schema.maximum }}; +var valid = data{{=$dataLvl}} {{=$op}} {{=$schema}}; + +{{# def.checkError:'maximum' }} -if (!valid) validate.errors.push({ - keyword: 'maximum', - dataPath: dataPath, - message: 'should be {{= $op }} {{= it.schema.maximum }}' - {{? it.opts.verbose }}, schema: {{= it.schema.maximum }}, data: data{{?}} -}); diff --git a/lib/compile/rules/minItems.dot.js b/lib/compile/rules/minItems.dot.js index 3f5d7c1..75d89d8 100644 --- a/lib/compile/rules/minItems.dot.js +++ b/lib/compile/rules/minItems.dot.js @@ -1,8 +1,6 @@ -var valid = data.length >= {{= it.schema.minItems }}; +{{# def.definitions }} +{{# def.setup:'minItems' }} -if (!valid) validate.errors.push({ - keyword: 'minItems', - dataPath: dataPath, - message: 'should NOT have less than {{= it.schema.minItems }} items' - {{? it.opts.verbose }}, schema: {{= it.schema.minItems }}, data: data{{?}} -}); +var valid = data{{=$dataLvl}}.length >= {{=$schema}}; + +{{# def.checkError:'minItems' }} diff --git a/lib/compile/rules/minLength.dot.js b/lib/compile/rules/minLength.dot.js index e15a32e..aea554a 100644 --- a/lib/compile/rules/minLength.dot.js +++ b/lib/compile/rules/minLength.dot.js @@ -1,8 +1,6 @@ -var valid = data.length >= {{= it.schema.minLength }}; +{{# def.definitions }} +{{# def.setup:'minLength' }} -if (!valid) validate.errors.push({ - keyword: 'minLength', - dataPath: dataPath, - message: 'should NOT be shorter than {{= it.schema.minLength }} characters' - {{? it.opts.verbose }}, schema: {{= it.schema.minLength }}, data: data{{?}} -}); +var valid = data{{=$dataLvl}}.length >= {{=$schema}}; + +{{# def.checkError:'minLength' }} diff --git a/lib/compile/rules/minProperties.dot.js b/lib/compile/rules/minProperties.dot.js index 2111e69..b30c410 100644 --- a/lib/compile/rules/minProperties.dot.js +++ b/lib/compile/rules/minProperties.dot.js @@ -1,9 +1,6 @@ -var propertiesNum = Object.keys(data).length; -var valid = propertiesNum >= {{= it.schema.minProperties }}; +{{# def.definitions }} +{{# def.setup:'minProperties' }} -if (!valid) validate.errors.push({ - keyword: 'minProperties', - dataPath: dataPath, - message: 'should NOT have less than {{= it.schema.minProperties }} properties' - {{? it.opts.verbose }}, schema: {{= it.schema.minProperties }}, data: data{{?}} -}); +var valid = Object.keys(data{{=$dataLvl}}).length >= {{=$schema}}; + +{{# def.checkError:'minProperties' }} \ No newline at end of file diff --git a/lib/compile/rules/minimum.dot.js b/lib/compile/rules/minimum.dot.js index c6cfea0..2772451 100644 --- a/lib/compile/rules/minimum.dot.js +++ b/lib/compile/rules/minimum.dot.js @@ -1,13 +1,11 @@ +{{# def.definitions }} +{{# def.setup:'minimum' }} + {{ var $exclusive = it.schema.exclusiveMinimum === true , $op = $exclusive ? '>' : '>='; }} -var valid = data {{= $op }} {{= it.schema.minimum }}; +var valid = data {{=$op}} {{=$schema}}; -if (!valid) validate.errors.push({ - keyword: 'minimum', - dataPath: dataPath, - message: 'should be {{= $op }} {{= it.schema.minimum }}' - {{? it.opts.verbose }}, schema: {{= it.schema.minimum }}, data: data{{?}} -}); +{{# def.checkError:'minimum' }} diff --git a/lib/compile/rules/multipleOf.dot.js b/lib/compile/rules/multipleOf.dot.js index 42fb3c6..7e3e314 100644 --- a/lib/compile/rules/multipleOf.dot.js +++ b/lib/compile/rules/multipleOf.dot.js @@ -1,9 +1,7 @@ -var division = data / {{= it.schema.multipleOf }}; -var valid = division === parseInt(division); +{{# def.definitions }} +{{# def.setup:'multipleOf' }} -if (!valid) validate.errors.push({ - keyword: 'multipleOf', - dataPath: dataPath, - message: 'should be multiple of {{= it.schema.multipleOf }}' - {{? it.opts.verbose }}, schema: {{= it.schema.multipleOf }}, data: data{{?}} -}); +var division{{=$lvl}} = data{{=$dataLvl}} / {{=$schema}}; +var valid = division{{=$lvl}} === parseInt(division{{=$lvl}}); + +{{# def.checkError:'multipleOf' }} diff --git a/lib/compile/rules/not.dot.js b/lib/compile/rules/not.dot.js index cc4e7b7..f7ae3fa 100644 --- a/lib/compile/rules/not.dot.js +++ b/lib/compile/rules/not.dot.js @@ -1,20 +1,16 @@ +{{# def.definitions }} +{{# def.setup:'not' }} +{{# def.setupNextLevel }} + {{ - var $it = it.copy(it) - , $level = it.level; - $it.level++; - $it.schema = it.schema.not; - $it.schemaPath = it.schemaPath + '.not'; + $it.schema = $schema; + $it.schemaPath = $schemaPath; }} -var errs{{= $level }} = validate.errors.length; +var errs{{=$lvl}} = validate.errors.length; -var valid = ({{= it.validate($it) }})(data, dataPath); +var valid = ({{= it.validate($it) }})(data{{=$dataLvl}}, dataPath{{=$dataLvl}}); valid = !valid; -if (valid) validate.errors.length = errs{{= $level }}; -else validate.errors.push({ - keyword: 'not', - dataPath: dataPath, - message: 'should NOT be valid' - {{? it.opts.verbose }}, schema: validate.schema{{= it.schemaPath + '.not' }}, data: data{{?}} -}); +if (valid) validate.errors.length = errs{{=$lvl}}; +else {{# def.error:'not' }} diff --git a/lib/compile/rules/oneOf.dot.js b/lib/compile/rules/oneOf.dot.js index d6e3372..441c7df 100644 --- a/lib/compile/rules/oneOf.dot.js +++ b/lib/compile/rules/oneOf.dot.js @@ -1,36 +1,29 @@ -{{ - var $it = it.copy(it) - , $level = it.level - , $closingBraces = ''; - $it.level++; -}} +{{# def.definitions }} +{{# def.setup:'oneOf' }} +{{# def.setupNextLevel }} -var errs{{= $level }} = validate.errors.length; -var validCount{{= $level }} = 0; -{{~ it.schema.oneOf:$schema:$i }} +var errs{{=$lvl}} = validate.errors.length; +var validCount{{=$lvl}} = 0; + +{{~ $schema:$sch:$i }} {{? $i }} {{ $closingBraces += '}'; }} - if (validCount{{= $level }} < 2) { + if (validCount{{=$lvl}} < 2) { {{?}} {{ - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.oneOf[' + $i + ']'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '[' + $i + ']'; }} - var valid = ({{= it.validate($it) }})(data, dataPath); - if (valid) validCount{{= $level }}++; + var valid = ({{= it.validate($it) }})(data{{=$dataLvl}}, dataPath{{=$dataLvl}}); + if (valid) validCount{{=$lvl}}++; {{~}} {{= $closingBraces }} -if (validCount{{= $level }} == 1) validate.errors.length = errs{{= $level }}; -else validate.errors.push({ - keyword: 'oneOf', - dataPath: dataPath, - message: 'should match exactly one schema in oneOf' - {{? it.opts.verbose }}, schema: validate.schema{{= it.schemaPath + '.oneOf'}}, data: data{{?}} -}); +var valid = validCount{{=$lvl}} == 1; -var valid = validCount{{= $level }} == 1; +if (valid) validate.errors.length = errs{{=$lvl}}; +else {{# def.error:'oneOf' }} diff --git a/lib/compile/rules/pattern.dot.js b/lib/compile/rules/pattern.dot.js index 58123e6..8ffb745 100644 --- a/lib/compile/rules/pattern.dot.js +++ b/lib/compile/rules/pattern.dot.js @@ -1,9 +1,7 @@ -{{ new RegExp(it.schema.pattern); /* test if regexp is valid to fail at compile time rather than in eval */}} -var valid = /{{= it.schema.pattern }}/.test(data); +{{# def.definitions }} +{{# def.setup:'pattern' }} -if (!valid) validate.errors.push({ - keyword: 'minimum', - dataPath: dataPath, - message: 'should match pattern "{{= it.schema.pattern }}"' - {{? it.opts.verbose }}, schema: '{{= it.schema.pattern }}', data: data{{?}} -}); +{{ new RegExp($schema); /* test if regexp is valid to fail at compile time rather than in eval */}} +var valid = /{{=$schema}}/.test(data); + +{{# def.checkError:'pattern' }} diff --git a/lib/compile/rules/properties.dot.js b/lib/compile/rules/properties.dot.js index a3c7652..6e082f4 100644 --- a/lib/compile/rules/properties.dot.js +++ b/lib/compile/rules/properties.dot.js @@ -1,60 +1,40 @@ -{{## def.ifValid: - {{? $breakOnError }} - if (valid) { - {{ $closingBraces += '}'; }} - {{?}} -#}} +{{# def.definitions }} +{{# def.setup:'properties' }} +{{# def.setupNextLevel }} + {{## def.validateProperty:useKey: - var data{{=$lvl}} = data[{{= useKey }}] - , dataPath{{=$lvl}} = dataPath + '.' + {{= useKey }}; + var data{{=$dataNxt}} = data{{=$dataLvl}}[{{= useKey }}] + , dataPath{{=$dataNxt}} = dataPath{{=$dataLvl}} + '.' + {{= useKey }}; {{? $breakOnError }} var valid = {{?}} - ({{= it.validate($it) }})(data{{=$lvl}}, dataPath{{=$lvl}}); + ({{= it.validate($it) }})(data{{=$dataNxt}}, dataPath{{=$dataNxt}}); #}} {{ - var $it = it.copy(it) - , $lvl = it.level - , $breakOnError = !it.opts.allErrors - , $closingBraces = '' - , $pProperties = it.schema.patternProperties || {} + var $dataNxt = $it.dataLevel = it.dataLevel + 1; + + var $pProperties = it.schema.patternProperties || {} , $pPropertyKeys = Object.keys($pProperties) , $aProperties = it.schema.additionalProperties , $noAdditional = $aProperties === false , $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length , $checkAdditional = $noAdditional || $additionalIsSchema; - - $it.level++; }} + var errs{{=$lvl}} = validate.errors.length; var valid = true; {{? $checkAdditional }} - var propertiesSchema{{=$lvl}} = validate.schema{{= it.schemaPath + '.properties' }} || {}; + var propertiesSchema{{=$lvl}} = validate.schema{{=$schemaPath}} || {}; {{?}} {{? $noAdditional }} - var propertiesSchemaKeys{{=$lvl}} = Object.keys(propertiesSchema{{=$lvl}}); - - var dataKeys{{=$lvl}} = Object.keys(data); - - var valid = dataKeys{{=$lvl}}.length <= propertiesSchemaKeys{{=$lvl}}.length; - if (!valid) { - validate.errors.push({ - keyword: 'properties', - dataPath: dataPath, - message: 'additional properties NOT allowed' - {{? it.opts.verbose }}, schema: propertiesSchema{{=$lvl}}, data: data{{?}} - }); - - } - {{? $breakOnError }} - {{ $closingBraces += '}'; }} - else { - {{?}} + var valid = Object.keys(data{{=$dataLvl}}).length <= Object.keys(propertiesSchema{{=$lvl}}).length; + {{# def.checkError:'additionalProperties' }} + {{# def.elseIfValid }} {{?}} {{? $pPropertyKeys.length }} @@ -67,41 +47,34 @@ var valid = true; {{? $checkAdditional }} - for (var key in data) { - var isAdditional = !propertiesSchema{{=$lvl}}.hasOwnProperty(key); + for (var key{{=$lvl}} in data{{=$dataLvl}}) { + var isAdditional{{=$lvl}} = !propertiesSchema{{=$lvl}}.hasOwnProperty(key{{=$lvl}}); {{? $pPropertyKeys.length }} - if (isAdditional) { + if (isAdditional{{=$lvl}}) { for (var pProperty{{=$lvl}} in pPropertiesSchema{{=$lvl}}) { - var keyMatches = pPropertiesRegexps{{=$lvl}}[pProperty{{=$lvl}}].test(key); - if (keyMatches) { - isAdditional = false; + var keyMatches{{=$lvl}} = pPropertiesRegexps{{=$lvl}}[pProperty{{=$lvl}}].test(key{{=$lvl}}); + if (keyMatches{{=$lvl}}) { + isAdditional{{=$lvl}} = false; break; } } } {{?}} - if (isAdditional) { + if (isAdditional{{=$lvl}}) { {{? $noAdditional }} valid = false; - - validate.errors.push({ - keyword: 'properties', - dataPath: dataPath, - message: 'property ' + key + ' NOT allowed' - {{? it.opts.verbose }}, schema: propertiesSchema{{=$lvl}}, data: data{{?}} - }); - + {{# def.error:'additionalProperties' }} {{? $breakOnError }} break; {{?}} {{??}} - {{ - /* additionalProperties is schema */ + {{ /* additionalProperties is schema */ $it.schema = $aProperties; $it.schemaPath = it.schemaPath + '.additionalProperties'; }} - {{# def.validateProperty:'key' }} + {{ var $useKey = 'key' + $lvl; }} + {{# def.validateProperty:$useKey }} {{? $breakOnError }} if (!valid) break; {{?}} {{?}} } @@ -110,18 +83,18 @@ var valid = true; {{# def.ifValid }} {{?}} -{{? it.schema.properties }} - {{ for (var $propertyKey in it.schema.properties) { }} - {{ var $schema = it.schema.properties[$propertyKey]; }} +{{? $schema }} + {{ for (var $propertyKey in $schema) { }} + {{ var $sch = $schema[$propertyKey]; }} - {{? Object.keys($schema).length }} + {{? Object.keys($sch).length }} {{ - $it.schema = $schema; - $it.schemaPath = it.schemaPath + '.properties["' + it.escapeQuotes($propertyKey) + '"]'; + $it.schema = $sch; + $it.schemaPath = $schemaPath + '["' + it.escapeQuotes($propertyKey) + '"]'; }} {{? $breakOnError }} valid = true; {{?}} - if (data.hasOwnProperty('{{= $propertyKey }}')) { + if (data{{=$dataLvl}}.hasOwnProperty('{{= $propertyKey }}')) { {{ /* TODO cache data types and paths by keys for patternProperties */ }} {{ var $useKey = '"' + $propertyKey + '"'; }} {{# def.validateProperty:$useKey }} @@ -133,18 +106,18 @@ var valid = true; {{?}} {{~ $pPropertyKeys:$propertyKey }} - {{ var $schema = $pProperties[$propertyKey]; }} + {{ var $sch = $pProperties[$propertyKey]; }} - {{? Object.keys($schema).length }} + {{? Object.keys($sch).length }} {{ - $it.schema = $schema; + $it.schema = $sch; $it.schemaPath = it.schemaPath + '.patternProperties.' + $propertyKey; }} - for (var key{{=$lvl}} in data) { - var keyMatches = pPropertiesRegexps{{=$lvl}}['{{= $propertyKey }}'].test(key{{=$lvl}}); + for (var key{{=$lvl}} in data{{=$dataLvl}}) { + var keyMatches{{=$lvl}} = pPropertiesRegexps{{=$lvl}}['{{= $propertyKey }}'].test(key{{=$lvl}}); - if (keyMatches) { + if (keyMatches{{=$lvl}}) { {{ var $useKey = 'key' + $lvl; }} {{# def.validateProperty:$useKey }} {{? $breakOnError }} if (!valid) break; {{?}} @@ -159,5 +132,4 @@ var valid = true; var valid = errs{{=$lvl}} == validate.errors.length; -{{ out = out.replace(/if \(valid\) \{\s*\}/g, ''); }} - +{{# def.cleanUp }} diff --git a/lib/compile/rules/required.dot.js b/lib/compile/rules/required.dot.js index 7ba6e60..df4f4e3 100644 --- a/lib/compile/rules/required.dot.js +++ b/lib/compile/rules/required.dot.js @@ -1,25 +1,18 @@ -{{ var $schema = it.schema.required; }} +{{# def.definitions }} +{{# def.setup:'required' }} + {{? $schema.length <= 100 }} - var valid = {{~ $schema:$property:$i }} - {{? $i}} && {{?}} - data.hasOwnProperty('{{= it.escapeQuotes($property) }}') - {{~}}; + valid = {{~ $schema:$property:$i }} + {{? $i}} && {{?}} + data{{=$dataLvl}}.hasOwnProperty('{{= it.escapeQuotes($property) }}') + {{~}}; {{??}} - {{ var $lvl = it.level; }} - var valid = true; - var schema{{=$lvl}} = validate.schema{{= it.schemaPath + '.required' }}; + var schema{{=$lvl}} = validate.schema{{=$schemaPath}}; - for (var i = 0; i < schema{{=$lvl}}.length; i++) { - var property = schema{{=$lvl}}[i] - , valid = valid && data.hasOwnProperty(schema{{=$lvl}}[i]); - - {{? !it.opts.allErrors }} if (!valid) break; {{?}} + for (var i{{=$lvl}} = 0; i{{=$lvl}} < schema{{=$lvl}}.length; i{{=$lvl}}++) { + valid = data.hasOwnProperty(schema{{=$lvl}}[i{{=$lvl}}]); + if (!valid) break; } {{?}} -if (!valid) validate.errors.push({ - keyword: 'required', - dataPath: dataPath, - message: 'properties {{= $schema.slice(0, 7).join(",") }}{{? $schema.length > 7}}...{{?}} are required' - {{? it.opts.verbose }}, schema: validate.schema{{= it.schemaPath + '.required' }}, data: data{{?}} -}); +{{# def.checkError:'required' }} diff --git a/lib/compile/rules/type.dot.js b/lib/compile/rules/type.dot.js index 1780f47..1a93760 100644 --- a/lib/compile/rules/type.dot.js +++ b/lib/compile/rules/type.dot.js @@ -1,15 +1,12 @@ -{{ var $isArray = Array.isArray(it.schema.type); }} +{{# def.definitions }} +{{# def.setup:'type' }} + +{{ var $isArray = Array.isArray($schema); }} {{? $isArray }} - var valid = {{= it.checkDataTypes(it.schema.type) }}; + var valid = {{= it.checkDataTypes($schema, $dataLvl) }}; {{??}} - var valid = {{= it.checkDataType(it.schema.type) }}; + var valid = {{= it.checkDataType($schema, $dataLvl) }}; {{?}} - -if (!valid) validate.errors.push({ - keyword: 'type', - dataPath: dataPath, - message: 'should be {{? $isArray }}{{= it.schema.type.join(",") }}{{??}}{{= it.schema.type }}{{?}}' - {{? it.opts.verbose }}, schema: {{? $isArray }}validate.schema{{= it.schemaPath + '.type' }}{{??}}'{{= it.schema.type }}'{{?}}, data: data{{?}} -}); +{{# def.checkError:'type' }} diff --git a/lib/compile/rules/uniqueItems.dot.js b/lib/compile/rules/uniqueItems.dot.js index c9b9ec9..3f1f0b6 100644 --- a/lib/compile/rules/uniqueItems.dot.js +++ b/lib/compile/rules/uniqueItems.dot.js @@ -1,27 +1,21 @@ +{{# def.definitions }} +{{# def.setup:'uniqueItems' }} + var valid = true; -{{ var $lvl = it.level; }} - -{{? it.schema.uniqueItems && it.opts.uniqueItems !== false }} - if (data.length > 1) { - var i{{=$lvl}} = data.length, j{{=$lvl}}; +{{? $schema && it.opts.uniqueItems !== false }} + if (data{{=$dataLvl}}.length > 1) { + var i{{=$lvl}} = data{{=$dataLvl}}.length, j{{=$lvl}}; outer: for (;i{{=$lvl}}--;) { for (j{{=$lvl}} = i{{=$lvl}}; j{{=$lvl}}--;) { - if (equal(data[i{{=$lvl}}], data[j{{=$lvl}}])) { + if (equal(data{{=$dataLvl}}[i{{=$lvl}}], data{{=$dataLvl}}[j{{=$lvl}}])) { valid = false; break outer; } } } - if (!valid) { - validate.errors.push({ - keyword: 'uniqueItems', - dataPath: dataPath, - message: 'items ## ' + i{{=$lvl}} + ' and ' + j{{=$lvl}} + ' are duplicate' - {{? it.opts.verbose }}, schema: {{= it.schema.uniqueItems }}, data: data{{?}} - }); - } + if (!valid) {{# def.error:'uniqueItems' }} } {{?}} diff --git a/lib/compile/validate.dot.js b/lib/compile/validate.dot.js index 8443bc9..b8c2a17 100644 --- a/lib/compile/validate.dot.js +++ b/lib/compile/validate.dot.js @@ -9,33 +9,46 @@ * validateRef etc. are defined in the parent scope in index.js */ }} -function ( data {{? !it.isRoot }}, dataPath {{?}}) { - 'use strict'; - +{{? it.isRoot}} {{ - var $breakOnErrors = !it.opts.allErrors - , $closingBraces1 = '' - , $closingBraces2 = ''; + it.isRoot = false; + var $lvl = 0; + it.level = 1; + var $dataLvl = it.dataLevel = 0; }} - {{? it.isRoot }} - {{ - it.isRoot = false; - var $level = 0; - it.level = 1; - }} - var dataPath = ''; - var errs{{= $level }} = validate.errors.length = 0; - {{??}} - {{ var $level = it.level++; }} - var errs{{= $level }} = validate.errors.length; - {{?}} + function ( data0 ) { + var dataPath0 = ''; + var errs{{=$lvl}} = validate.errors.length = 0; + + /* remove when all use dataLevel */ + var data = data0; + var dataPath = dataPath0; +{{??}} + {{ + var $lvl = it.level++ + , $dataLvl = it.dataLevel; + }} + + function ( data{{=$dataLvl}}, dataPath{{=$dataLvl}} ) { + var errs{{=$lvl}} = validate.errors.length; + + /* remove when all use dataLevel */ + /* var data = data{{=$dataLvl}}; + var dataPath = dataPath{{=$dataLvl}}; */ +{{?}} + +{{ + var $breakOnErrors = !it.opts.allErrors + , $closingBraces1 = '' + , $closingBraces2 = ''; +}} var valid = true; {{~ it.RULES:$rulesGroup }} {{? $shouldUseGroup($rulesGroup) }} - {{? $rulesGroup.type }} if ({{= it.checkDataType($rulesGroup.type) }}) { {{?}} + {{? $rulesGroup.type }} if ({{= it.checkDataType($rulesGroup.type, $dataLvl) }}) { {{?}} {{~ $rulesGroup.rules:$rule }} {{? $shouldUseRule($rule) }} {{= $rule.code(it) }} @@ -60,7 +73,7 @@ function ( data {{? !it.isRoot }}, dataPath {{?}}) { {{? $breakOnErrors }} {{= $closingBraces2 }} {{?}} - return errs{{= $level }} == validate.errors.length; + return errs{{=$lvl}} == validate.errors.length; } {{ @@ -83,4 +96,3 @@ function ( data {{? !it.isRoot }}, dataPath {{?}}) { }} {{ out = out.replace(/if \(valid\) \{\s*\}/g, ''); }} - diff --git a/package.json b/package.json index a8cbc72..c7d6c70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ajv", - "version": "0.1.12", + "version": "0.1.13", "description": "Another JSON schema Validator", "main": "lib/ajv.js", "scripts": { diff --git a/spec/json-schema.spec.js b/spec/json-schema.spec.js index 9fbef23..fc389d0 100644 --- a/spec/json-schema.spec.js +++ b/spec/json-schema.spec.js @@ -7,15 +7,17 @@ var glob = require('glob') var ONLY_RULES, SKIP_RULES; // ONLY_RULES = [ // 'type', -'not', +// 'not', // 'allOf', // 'anyOf', // 'oneOf', // 'enum', -// 'maximum', 'minimum', 'multipleOf', +// 'maximum', 'minimum', +'multipleOf', // 'maxLength', 'minLength', 'pattern', // 'properties', 'patternProperties', 'additionalProperties', -// 'dependencies', 'required', +// 'dependencies', +// 'required', // 'maxProperties', 'minProperties', 'maxItems', 'minItems', // 'items', 'additionalItems', 'uniqueItems', // 'optional/format', 'optional/bignum', @@ -58,27 +60,27 @@ describe('JSON-Schema tests', function () { describe(file.name, function() { var testSets = require(file.path); testSets.forEach(function (testSet) { - // if (testSet.description != 'not more complex schema') return; + // if (testSet.description != 'invalid string value for default') return; describe(testSet.description, function() { // it(testSet.description, function() { var validate = ajv.compile(testSet.schema); var fullValidate = fullAjv.compile(testSet.schema); testSet.tests.forEach(function (test) { - // if (test.description != 'match') return; + // if (test.description != 'valid when property is specified') return; // console.log(testSet.schema, '\n\n***\n\n', validate.toString()); it(test.description, function() { var valid = validate(test.data); - // console.log('result', result); + // console.log('result', valid, validate.errors); assert.equal(valid, test.valid); if (valid) assert(validate.errors.length == 0); else assert(validate.errors.length > 0); var valid = fullValidate(test.data); - // console.log('full result', result); + // console.log('full result', valid, fullValidate.errors); assert.equal(valid, test.valid); - if (valid) assert(validate.errors.length == 0); - else assert(validate.errors.length > 0); + if (valid) assert(fullValidate.errors.length == 0); + else assert(fullValidate.errors.length > 0); }); }); }); diff --git a/try.js b/try.js index bfef23f..ce82a46 100644 --- a/try.js +++ b/try.js @@ -1,62 +1,49 @@ -var out = ''; -out += 'function (data, dataType, dataPath) { \'use strict\'; '; -if (it.opts.allErrors) { - out += ' var errors = []; '; -} -out += ' '; -var $schemaKeys = Object.keys(it.schema); -$schemaKeys.sort(compareRules); -out += ' '; -var $checkProperties = !it.schema.properties && (it.schema.patternProperties || it.schema.hasOwnProperty('additionalProperties')); -if ($checkProperties) $schemaKeys.push('properties'); -out += ' '; -var arr1 = $schemaKeys; -if (arr1) { - var $key, i1 = -1, - l1 = arr1.length - 1; - while (i1 < l1) { - $key = arr1[i1 += 1]; - out += ' '; - var $rule = it.RULES[$key]; - out += ' '; - if ($rule) { - out += ' var rule = RULES.' + ($key) + '; if ( !rule.type || rule.type == dataType ) { '; - if ($rule.inline) { - out += ' ' + ($rule.code(it)) + ' '; - } else { - out += ' '; - var $it = it.copy(it); - $it.schema = it.schema[$key]; - $it.schemaPath = it.schemaPath + '.' + $key; - $it.parentSchema = it.schema; - $it.parentSchemaPath = it.schemaPath; - out += ' var result = (' + ($rule.code($it)) + ')(data, dataType, dataPath); '; - } - out += ' if (!result.valid) { '; - if (it.opts.allErrors) { - out += ' errors.push.apply(errors, result.errors); '; - } else { - out += ' return result; '; - } - out += ' } } '; - } - out += ' '; - } -} -out += ' '; -if (it.opts.allErrors) { - out += ' return { valid: !errors.length, errors: errors }; '; -} else { - out += ' return { valid: true, errors: [] }; '; -} -out += ' '; +function(it) { -function compareRules(key1, key2) { - var order1 = it.RULES[key1].order, - order2 = it.RULES[key2].order; - if (order1 < order2) return -1; - if (order1 > order2) return +1; - if (order1 == order2) return 0; -} -} -return out \ No newline at end of file +var $lvl = it.level, + $dataLvl = it.dataLevel, + $schema = it.schema['required'], + $schemaPath = it.schemaPath + '.' + 'required'; +if ($schema.length <= 100) { + out += ' valid = '; + var arr1 = $schema; + if (arr1) { + var $property, $i = -1, + l1 = arr1.length - 1; + while ($i < l1) { + $property = arr1[$i += 1]; + out += ' '; + if ($i) { + out += ' && '; + } + out += ' data' + ($dataLvl) + '.hasOwnProperty(\'' + (it.escapeQuotes($property)) + '\') '; + } + } + out += '; if (!valid) validate.errors.push({ \'required\': \'' + ('required') + '\', dataPath: dataPath' + ($dataLvl) + ', message: \'properties ' + ($schema.slice(0, 7).join(", ")); + if ($schema.length > 7) { + out += '...'; + } + out += ' are required\' '; + if (it.opts.verbose) { + out += ', schema: validate.schema' + ($schemaPath) + ', data: data' + ($dataLvl); + } + out += ' });'; +} else { + out += ' var errs' + ($lvl) + ' = validate.errors.length; var schema' + ($lvl) + ' = validate.schema' + ($schemaPath) + '; for (var i' + ($lvl) + ' = 0; i' + ($lvl) + ' < schema' + ($lvl) + '.length; i' + ($lvl) + '++) { valid = data.hasOwnProperty(schema' + ($lvl) + '[i' + ($lvl) + ']); if (!valid) { validate.errors.push({ \'required\': \'' + ('required') + '\', dataPath: dataPath' + ($dataLvl) + ', message: \'properties ' + ($schema.slice(0, 7).join(", ")); + if ($schema.length > 7) { + out += '...'; + } + out += ' are required\' '; + if (it.opts.verbose) { + out += ', schema: validate.schema' + ($schemaPath) + ', data: data' + ($dataLvl); + } + out += ' }); '; + if (!it.opts.allErrors) { + out += ' break; '; + } + out += ' } } '; + if (it.opts.allErrors) { + out += ' valid = errs' + ($lvl) + ' == validate.errors.length; {{}}'; + } + return out; +} \ No newline at end of file