refactored schema compilation to reduce browser bundle size

master
Evgeny Poberezkin 2015-12-23 01:22:26 +00:00
parent a38bf04418
commit abff815d38
17 changed files with 50 additions and 72 deletions

View File

@ -3,8 +3,12 @@
//all requires must be explicit because browserify won't work with dynamic requires
module.exports = {
'$ref': require('../dotjs/ref'),
allOf: require('../dotjs/allOf'),
anyOf: require('../dotjs/anyOf'),
dependencies: require('../dotjs/dependencies'),
enum: require('../dotjs/enum'),
format: require('../dotjs/format'),
items: require('../dotjs/items'),
maximum: require('../dotjs/_limit'),
minimum: require('../dotjs/_limit'),
maxItems: require('../dotjs/_limitItems'),
@ -13,16 +17,12 @@ module.exports = {
minLength: require('../dotjs/_limitLength'),
maxProperties: require('../dotjs/_limitProperties'),
minProperties: require('../dotjs/_limitProperties'),
oneOf: require('../dotjs/oneOf'),
required: require('../dotjs/required'),
dependencies: require('../dotjs/dependencies'),
items: require('../dotjs/items'),
multipleOf: require('../dotjs/multipleOf'),
pattern: require('../dotjs/pattern'),
uniqueItems: require('../dotjs/uniqueItems'),
allOf: require('../dotjs/allOf'),
enum: require('../dotjs/enum'),
not: require('../dotjs/not'),
oneOf: require('../dotjs/oneOf'),
pattern: require('../dotjs/pattern'),
properties: require('../dotjs/properties'),
required: require('../dotjs/required'),
uniqueItems: require('../dotjs/uniqueItems'),
validate: require('../dotjs/validate')
};

View File

@ -159,7 +159,7 @@ function compile(schema, root, localRefs, baseId) {
if (compile)
validate = compile.call(self, schema, parentSchema);
else if (inline)
validate = inline.call(self, it, schema, parentSchema);
validate = inline.call(self, it, rule.keyword, schema, parentSchema);
else
validate = rule.definition.validate;

View File

@ -1,8 +1,8 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{
var $isMax = $keyword == 'maximum'
, $exclusiveKeyword = $isMax ? 'exclusiveMaximum' : 'exclusiveMinimum'

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxItems' ? '>' : '<'; }}

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxLength' ? '>' : '<'; }}

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $op = $keyword == 'maxProperties' ? '>' : '<'; }}

View File

@ -1,20 +1,3 @@
{{## def.setup:_keyword:
{{
var $keyword = _keyword
, $lvl = it.level
, $dataLvl = it.dataLevel
, $schema = it.schema[_keyword]
, $schemaPath = it.schemaPath + '.' + _keyword
, $errSchemaPath = it.errSchemaPath + '/' + _keyword
, $breakOnError = !it.opts.allErrors;
var $data = 'data' + ($dataLvl || '')
, $valid = 'valid' + $lvl
, $errs = 'errs__' + $lvl;
}}
#}}
{{## def.setupKeyword:
{{
var $lvl = it.level
@ -22,7 +5,8 @@
, $schema = it.schema[$keyword]
, $schemaPath = it.schemaPath + '.' + $keyword
, $errSchemaPath = it.errSchemaPath + '/' + $keyword
, $breakOnError = !it.opts.allErrors;
, $breakOnError = !it.opts.allErrors
, $errorKeyword;
var $data = 'data' + ($dataLvl || '')
, $valid = 'valid' + $lvl
@ -31,7 +15,6 @@
#}}
{{## def.setCompositeRule:
{{
var $wasComposite = it.compositeRule;

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{ var $i = 'i' + $lvl; }}

View File

@ -2,7 +2,7 @@
{{ 'istanbul ignore else'; }}
{{? it.createErrors !== false }}
{
keyword: '{{= typeof $errorKeyword == "undefined" ? _rule : $errorKeyword }}'
keyword: '{{= $errorKeyword || _rule }}'
, dataPath: (dataPath || '') + {{= it.errorPath }}
, schemaPath: "{{=$errSchemaPath}}"
, params: {{# def._errorParams[_rule] }}
@ -21,21 +21,24 @@
#}}
{{## def.addError:_rule:
var err = {{# def._error:_rule }};
{{## def._addError:_rule:
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
#}}
{{## def.addError:_rule:
var err = {{# def._error:_rule }};
{{# def._addError:_rule }}
#}}
{{## def.error:_rule:
{{? !it.compositeRule && $breakOnError }}
validate.errors = [{{# def._error:_rule }}];
return false;
{{??}}
{{# def.addError:_rule }}
{{?}}
{{ var $returnErr = !it.compositeRule && $breakOnError; }}
{{?$returnErr}} validate.errors = [ {{??}} var err = {{?}}
{{# def._error:_rule }}
{{?$returnErr}} ]; return false; {{??}} ; {{# def._addError:_rule }}{{?}}
#}}
@ -107,7 +110,7 @@
oneOf: "validate.schema{{=$schemaPath}}",
pattern: "{{#def.schemaRefOrQS}}",
required: "validate.schema{{=$schemaPath}}",
type: "{{? $isArray }}['{{= $typeSchema.join(\"','\") }}']{{??}}'{{=$typeSchema}}'{{?}}",
type: "validate.schema{{=$schemaPath}}",
uniqueItems: "{{=$schema}}",
custom: "validate.schema{{=$schemaPath}}",
patternGroups: "validate.schema{{=$schemaPath}}",
@ -123,7 +126,7 @@
additionalItems: "{ limit: {{=$schema.length}} }",
additionalProperties: "{ additionalProperty: '{{=$additionalProperty}}' }",
anyOf: "{}",
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{? $deps.length==1 }}{{= it.util.escapeQuotes($deps[0]) }}{{??}}{{= it.util.escapeQuotes($deps.join(\", \")) }}{{?}}' }",
dependencies: "{ property: '{{= it.util.escapeQuotes($property) }}', missingProperty: '{{=$missingProperty}}', depsCount: {{=$deps.length}}, deps: '{{= it.util.escapeQuotes($deps.length==1 ? $deps[0] : $deps.join(\", \")) }}' }",
enum: "{}",
format: "{ format: {{#def.schemaValueQS}} }",
_limit: "{ comparison: {{=$opExpr}}, limit: {{=$schemaValue}}, exclusive: {{=$exclusive}} }",

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
var division{{=$lvl}};

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.$data }}
{{

View File

@ -1,7 +1,6 @@
{{# def.definitions }}
{{# def.errors }}
{{# def.setup:'constant' }}
{{# def.setupKeyword }}
{{# def.$data }}
var constantSchema{{=$lvl}} = {{= $isData ? $schemaValue : 'validate.schema' + $schemaPath }};

View File

@ -1,5 +1,6 @@
{{# def.definitions }}
{{# def.setup:'switch' }}
{{# def.errors }}
{{# def.setupKeyword }}
{{# def.setupNextLevel }}

View File

@ -45,7 +45,8 @@
var $valid = 'valid' + $lvl
, $breakOnError = !it.opts.allErrors
, $closingBraces1 = ''
, $closingBraces2 = '';
, $closingBraces2 = ''
, $errorKeyword;
var $typeSchema = it.schema.type;
}}

View File

@ -15,8 +15,8 @@ function enableV5(ajv) {
}
ajv.addKeyword('constant', { inline: require('./dotjs/constant'), statements: true, errors: 'full' });
ajv.addKeyword('contains', { macro: containsMacro });
ajv.addKeyword('formatMaximum', { type: 'string', inline: formatLimit('maximum'), errors: false });
ajv.addKeyword('formatMinimum', { type: 'string', inline: formatLimit('minimum'), errors: false });
ajv.addKeyword('formatMaximum', { type: 'string', inline: formatLimit, errors: false });
ajv.addKeyword('formatMinimum', { type: 'string', inline: formatLimit, errors: false });
ajv.addKeyword('exclusiveFormatMaximum');
ajv.addKeyword('exclusiveFormatMinimum');
ajv.addKeyword('patternGroups'); // implemented in properties.jst
@ -32,21 +32,18 @@ function containsMacro(schema) {
};
}
function formatLimit(limit) {
var operation = limit == 'maximum' ? '<' : '>';
var exclusiveLimit = 'exclusiveFormat' +
(limit == 'maximum' ? 'Maximum' : 'Minimum');
return function(it, schema, parentSchema) {
var format = parentSchema.format;
var compare = it.formats[format].compare;
if (!compare) return 'true';
var exclusive = parentSchema[exclusiveLimit];
var data = 'data' + (it.dataLevel || '');
var op = operation;
if (!exclusive) op += '=';
return 'formats' + it.util.getProperty(format) + '.compare('
+ data + ', ' + it.util.toQuotedString(schema)
+ ') ' + op + ' 0';
};
function formatLimit(it, keyword, schema, parentSchema) {
var isMax = keyword == 'formatMaximum'
, operation = isMax ? '<' : '>'
, exclusiveLimit = 'exclusiveFormat' + (isMax ? 'Maximum' : 'Minimum')
, format = parentSchema.format
, compare = it.formats[format].compare;
if (!compare) return 'true';
var exclusive = parentSchema[exclusiveLimit]
, data = 'data' + (it.dataLevel || '')
, op = operation;
if (!exclusive) op += '=';
return 'formats' + it.util.getProperty(format) + '.compare('
+ data + ', ' + it.util.toQuotedString(schema)
+ ') ' + op + ' 0';
}

View File

@ -58,7 +58,7 @@ describe('Ajv', function () {
var validate = ajv.compile(schema);
});
function badEvenCode(it, schema) {
function badEvenCode(it, keyword, schema) {
var op = schema ? '===' : '!==='; // invalid on purpose
return 'data' + (it.dataLevel || '') + ' % 2 ' + op + ' 0';
}

View File

@ -421,12 +421,12 @@ describe('Custom keywords', function () {
});
function inlineEven(it, schema) {
function inlineEven(it, keyword, schema) {
var op = schema ? '===' : '!==';
return 'data' + (it.dataLevel || '') + ' % 2 ' + op + ' 0';
}
function inlineRange(it, schema, parentSchema) {
function inlineRange(it, keyword, schema, parentSchema) {
var min = schema[0]
, max = schema[1]
, data = 'data' + (it.dataLevel || '')