Skip to content

Commit

Permalink
fix: traverse only schema objects, fixes #521
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Jun 15, 2017
1 parent daf7d6b commit 0d6ae42
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 33 deletions.
67 changes: 34 additions & 33 deletions lib/compile/resolve.js
Expand Up @@ -3,7 +3,8 @@
var url = require('url')
, equal = require('./equal')
, util = require('./util')
, SchemaObject = require('./schema_obj');
, SchemaObject = require('./schema_obj')
, traverse = require('json-schema-traverse');

module.exports = resolve;

Expand Down Expand Up @@ -230,41 +231,41 @@ function resolveUrl(baseId, id) {

/* @this Ajv */
function resolveIds(schema) {
/* eslint no-shadow: 0 */
/* jshint validthis: true */
var id = normalizeId(this._getId(schema));
var schemaId = normalizeId(this._getId(schema));
var baseIds = {'': schemaId};
var fullPaths = {'': getFullPath(schemaId, false)};
var localRefs = {};
_resolveIds.call(this, schema, getFullPath(id, false), id);
return localRefs;

/* @this Ajv */
function _resolveIds(schema, fullPath, baseId) {
/* jshint validthis: true */
if (Array.isArray(schema)) {
for (var i=0; i<schema.length; i++)
_resolveIds.call(this, schema[i], fullPath+'/'+i, baseId);
} else if (schema && typeof schema == 'object') {
var id = this._getId(schema);
if (typeof id == 'string') {
id = baseId = normalizeId(baseId ? url.resolve(baseId, id) : id);

var refVal = this._refs[id];
if (typeof refVal == 'string') refVal = this._refs[refVal];
if (refVal && refVal.schema) {
if (!equal(schema, refVal.schema))
var self = this;

traverse(schema, {allKeys: true}, function(sch, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex) {
if (jsonPtr === '') return;
var id = self._getId(sch);
var baseId = baseIds[parentJsonPtr];
var fullPath = fullPaths[parentJsonPtr] + '/' + parentKeyword;
if (keyIndex !== undefined)
fullPath += '/' + (typeof keyIndex == 'number' ? keyIndex : util.escapeFragment(keyIndex));

if (typeof id == 'string') {
id = baseId = normalizeId(baseId ? url.resolve(baseId, id) : id);

var refVal = self._refs[id];
if (typeof refVal == 'string') refVal = self._refs[refVal];
if (refVal && refVal.schema) {
if (!equal(sch, refVal.schema))
throw new Error('id "' + id + '" resolves to more than one schema');
} else if (id != normalizeId(fullPath)) {
if (id[0] == '#') {
if (localRefs[id] && !equal(sch, localRefs[id]))
throw new Error('id "' + id + '" resolves to more than one schema');
} else if (id != normalizeId(fullPath)) {
if (id[0] == '#') {
if (localRefs[id] && !equal(schema, localRefs[id]))
throw new Error('id "' + id + '" resolves to more than one schema');
localRefs[id] = schema;
} else {
this._refs[id] = fullPath;
}
localRefs[id] = sch;
} else {
self._refs[id] = fullPath;
}
}
for (var key in schema)
_resolveIds.call(this, schema[key], fullPath+'/'+util.escapeFragment(key), baseId);
}
}
baseIds[jsonPtr] = baseId;
fullPaths[jsonPtr] = fullPath;
});

return localRefs;
}
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -64,6 +64,7 @@
"tonicExampleFilename": ".tonic_example.js",
"dependencies": {
"co": "^4.6.0",
"json-schema-traverse": "^0.3.0",
"json-stable-stringify": "^1.0.1"
},
"devDependencies": {
Expand Down
24 changes: 24 additions & 0 deletions spec/issues.spec.js
Expand Up @@ -576,3 +576,27 @@ describe('issue #485, order of type validation', function() {
}
});
});


describe('issue #521, incorrect warning with "id" property', function() {
it('should not log warning', function() {
var ajv = new Ajv({schemaId: '$id'});
var consoleWarn = console.warn;
console.warn = function() {
throw new Error('should not log warning');
};

try {
ajv.compile({
"$id": "http://example.com/schema.json",
"type": "object",
"properties": {
"id": {"type": "string"},
},
"required": [ "id"]
});
} finally {
console.warn = consoleWarn;
}
});
});

0 comments on commit 0d6ae42

Please sign in to comment.