Skip to content

Commit

Permalink
Fix more conformance issues with the JSON-Schema-Test-Suite #9
Browse files Browse the repository at this point in the history
  • Loading branch information
bugventure committed Jan 16, 2015
1 parent e53fca0 commit c9ce3cb
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 74 deletions.
158 changes: 86 additions & 72 deletions lib/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,92 @@ var util = require('util'),
not: require('./multi/not.js')
};

function refToPath(ref) {
var path = ref.split('#')[1];

if (path) {
path = path.split('/').join('.');

if (path[0] === '.') {
path = path.substr(1);
}
}

return path;
}

function SchemaResolver(rootSchema) {
this.rootSchema = rootSchema;
this.cache = {};
this.resolved = null;
}

SchemaResolver.prototype.resolveRef = function (ref) {
var err = new Error(util.format(strings.invalidReference, ref)),
root = this.rootSchema,
path,
dest;

if (!type.isString(ref) || !ref || !refRegex.test(ref)) {
throw err;
}

if (ref === metaschema.id) {
dest = metaschema;
}
else {
path = refToPath(ref);

dest = path ? collector.get(root, path) : root;
}

if (!type.isObject(dest)) {
throw err;
}

if (this.cache[ref] === dest) {
return dest;
}

this.cache[ref] = dest;

if (dest.$ref !== undefined) {
dest = this.cache[ref] = this.resolveRef(dest.$ref);
}

return dest;
};

SchemaResolver.prototype.resolve = function (schema) {
if (!type.isObject(schema)) {
return schema;
}

var ref = schema.$ref,
resolved = this.cache[ref];

if (type.isUndefined(ref)) {
return schema;
}

if (resolved) {
return resolved;
}

resolved = this.resolveRef(ref);

if (schema === this.rootSchema && schema !== resolved) {
// substitute the resolved root schema
this.rootSchema = resolved;
}

return resolved;
};

function Validator(options) {
this.rootSchema = options.schema ?
this.resolve(options.schema) :
null;
// this.rootSchema = new SchemaResolver(options.schema).resolve(options.schema);
this.rootSchema = options.schema;
this.resolver = new SchemaResolver(this.rootSchema);

this.chain = chain.apply(null, options.handlers);
this.types = options.types;
Expand Down Expand Up @@ -214,73 +296,7 @@ Validator.prototype.middleware = function () {
};

Validator.prototype.resolve = function (schema) {
var root = this.rootSchema || schema,
ref = schema.$ref,
err = new Error(util.format(strings.invalidReference, ref)),
path,
refSchema,
valid;

if (type.isUndefined(ref)) {
return schema;
}

if (!type.isString(ref) || !ref || !refRegex.test(ref)) {
throw err;
}

// resolve references ot the metaschema itself
if (ref === metaschema.id) {
return metaschema;
}

// resolve references to the schema root, or,
// if the root is missing, to the schema itself.
if (ref === '#') {
return root;
}

path = ref.split('#')[1];

if (path) {
path = path.split('/').join('.');

if (path[0] === '.') {
path = path.substr(1);
}

refSchema = collector.get(root, path);

// For a resolved schema to be valid, it needs to be an object
// and not contain another reference.
valid = type.isObject(refSchema) && !type.isString(refSchema.$ref);

if (!valid) {
throw err;
}

return refSchema;
}

return root;
};

Validator.prototype.validateReferences = function (schema) {
var inst = this;
if (type.isObject(schema)) {
if (schema.hasOwnProperty('$ref')) {
// expect to throw;
inst.resolve(schema);
}
else if (schema.hasOwnProperty('properties')) {
Object.keys(schema.properties).forEach(function forEachKey(key) {
inst.validateReferences(schema[key]);
});
}
}
// else if (type.isArray(schema)) {
// inst.validateReferences(schema.items);
// }
return this.resolver.resolve(schema);
};

Validator.prototype.validateSchema = function () {
Expand All @@ -300,8 +316,6 @@ Validator.prototype.validateSchema = function () {
});

schemaValidator.validate(metaschema, this.rootSchema);

this.validateReferences(this.rootSchema);
};

Validator.prototype.default = function (schema, value) {
Expand Down
4 changes: 2 additions & 2 deletions test/x-draft4-test-suite.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ catch (e) {
error = e;
}

testCategories = [];
// testCategories = [testCategories[23]];
// temporarily exclude remote ref tests
testCategories.splice(24, 1);

function addTestCase(schema, testCase) {
it(testCase.description, function () {
Expand Down

0 comments on commit c9ce3cb

Please sign in to comment.