Commit 62727eb1 authored by mtytel@chromium.org's avatar mtytel@chromium.org

Allow omitting optional parameters for Extensions API functions

BUG=29215
TEST=Existing browser tests that call API functions with omitted parameters. Still need to add browser tests and possibly some unit tests


Review URL: http://codereview.chromium.org/9317072

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124898 0039d316-1c4b-4281-b951-d872f2087c98
parent 48cd61c9
......@@ -152,7 +152,6 @@
'renderer/resources/extensions/tts_engine_custom_bindings.js',
'renderer/resources/extensions/types_custom_bindings.js',
'renderer/resources/extensions/web_request_custom_bindings.js',
'renderer/resources/extensions/windows_custom_bindings.js',
'renderer/resources/require.js',
'renderer/chrome_content_renderer_client.cc',
'renderer/chrome_content_renderer_client.h',
......
......@@ -76,67 +76,6 @@
"parameters": []
}
]
},
{
"name": "setLaunchIcon",
"nodoc": true,
"type": "function",
"parameters": [
{
"type": "object",
"name": "details",
"optional": true,
"properties": {
"extensionId": {
"type": "string",
"optional": true,
"description": "An optional id to do notifications for an app other than the calling app. This is just to allow prototyping with an extension that sends notifications on behalf of apps that don't support notifications yet; this will be removed before the API becomes stable."
}
}
},
{
"type": "object",
"name": "iconData",
"isInstanceOf": "ImageData",
"optional": true,
"additionalProperties": { "type": "any" },
"description": "Pixel data for an image to replace the launch icon on the New Tab Page. Must be an ImageData object (for example, from a canvas element). See http://code.google.com/chrome/webstore/docs/images.html for more details."
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "A callback when the function is complete. Any errors will be reported in <a href='extension.html#property-lastError'>chrome.extension.lastError</a>.",
"parameters": []
}
]
},
{
"name": "resetLaunchIcon",
"nodoc": true,
"type": "function",
"description": "Resets the app's launch icon to its default value as specified in the manifest.json file.",
"parameters": [
{
"type": "object",
"name": "details",
"optional": true,
"properties": {
"extensionId": {
"type": "string",
"optional": true,
"description": "An optional id to do notifications for an app other than the calling app. This is just to allow prototyping with an extension that sends notifications on behalf of apps that don't support notifications yet; this will be removed before the API becomes stable."
}
}
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "A callback when the function is complete. Any errors will be reported in <a href='extension.html#property-lastError'>chrome.extension.lastError</a>.",
"parameters": []
}
]
}
]
}
......
......@@ -21,6 +21,7 @@ const char kChromeHidden[] = "chromeHidden";
#ifndef NDEBUG
const char kValidateCallbacks[] = "validateCallbacks";
const char kValidateAPI[] = "validateAPI";
#endif
std::string GetContextTypeDescription(
......@@ -69,8 +70,11 @@ v8::Handle<v8::Value> ChromeV8Context::GetOrCreateChromeHidden(
#ifndef NDEBUG
// Tell schema_generated_bindings.js to validate callbacks and events
// against their schema definitions.
v8::Local<v8::Object>::Cast(hidden)
->Set(v8::String::New(kValidateCallbacks), v8::True());
v8::Local<v8::Object>::Cast(hidden)->Set(
v8::String::New(kValidateCallbacks), v8::True());
// Tell schema_generated_bindings.js to validate API for ambiguity.
v8::Local<v8::Object>::Cast(hidden)->Set(
v8::String::New(kValidateAPI), v8::True());
#endif
}
......
......@@ -44,7 +44,6 @@ std::vector<v8::Extension*> GetAll(ExtensionDispatcher* extension_dispatcher) {
"extensions/storage_custom_bindings.js",
"extensions/tts_engine_custom_bindings.js",
"extensions/types_custom_bindings.js",
"extensions/windows_custom_bindings.js",
};
static const size_t kJavascriptFilesSize = arraysize(kJavascriptFiles);
......@@ -60,7 +59,6 @@ std::vector<v8::Extension*> GetAll(ExtensionDispatcher* extension_dispatcher) {
IDR_STORAGE_CUSTOM_BINDINGS_JS,
IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS,
IDR_TYPES_CUSTOM_BINDINGS_JS,
IDR_WINDOWS_CUSTOM_BINDINGS_JS,
};
static const size_t kResourceIDsSize = arraysize(kResourceIDs);
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -94,3 +94,15 @@ TEST_F(JsonSchemaTest, TestType) {
TEST_F(JsonSchemaTest, TestTypeReference) {
TestFunction("testTypeReference");
}
TEST_F(JsonSchemaTest, TestGetAllTypesForSchema) {
TestFunction("testGetAllTypesForSchema");
}
TEST_F(JsonSchemaTest, TestIsValidSchemaType) {
TestFunction("testIsValidSchemaType");
}
TEST_F(JsonSchemaTest, TestCheckSchemaOverlap) {
TestFunction("testCheckSchemaOverlap");
}
......@@ -51,7 +51,6 @@ without changes to the corresponding grd file. fb9 -->
<include name="IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS" file="resources\extensions\tts_engine_custom_bindings.js" type="BINDATA" />
<include name="IDR_TYPES_CUSTOM_BINDINGS_JS" file="resources\extensions\types_custom_bindings.js" type="BINDATA" />
<include name="IDR_WEB_REQUEST_CUSTOM_BINDINGS_JS" file="resources\extensions\web_request_custom_bindings.js" type="BINDATA" />
<include name="IDR_WINDOWS_CUSTOM_BINDINGS_JS" file="resources\extensions\windows_custom_bindings.js" type="BINDATA" />
</includes>
</release>
</grit>
......@@ -143,13 +143,64 @@ chromeHidden.JSONSchemaValidator.prototype.addTypes = function(typeOrTypeList) {
}
}
/**
* Returns a list of strings of the types that this schema accepts.
*/
chromeHidden.JSONSchemaValidator.prototype.getAllTypesForSchema =
function(schema) {
var schemaTypes = [];
if (schema.type)
schemaTypes.push(schema.type);
if (schema.choices) {
for (var i = 0; i < schema.choices.length; i++) {
var choiceTypes = this.getAllTypesForSchema(schema.choices[i]);
schemaTypes = schemaTypes.concat(choiceTypes);
}
}
if (schema['$ref']) {
var refTypes = this.getAllTypesForSchema(this.types[schema['$ref']]);
schemaTypes = schemaTypes.concat(refTypes);
}
return schemaTypes;
};
/**
* Returns true if |schema| would accept an argument of type |type|.
*/
chromeHidden.JSONSchemaValidator.prototype.isValidSchemaType =
function(type, schema) {
if (schema.optional && (type == "null" || type == "undefined"))
return true;
schemaTypes = this.getAllTypesForSchema(schema);
for (var i = 0; i < schemaTypes.length; i++) {
if (schemaTypes[i] == "any" || type == schemaTypes[i])
return true;
}
return type == "any";
};
/**
* Returns true if there is a non-null argument that both |schema1| and
* |schema2| would accept.
*/
chromeHidden.JSONSchemaValidator.prototype.checkSchemaOverlap =
function(schema1, schema2) {
var schema1Types = this.getAllTypesForSchema(schema1);
for (var i = 0; i < schema1Types.length; i++) {
if (this.isValidSchemaType(schema1Types[i], schema2))
return true;
}
return false;
};
/**
* Validates an instance against a schema. The instance can be any JavaScript
* value and will be validated recursively. When this method returns, the
* |errors| property will contain a list of errors, if any.
*/
chromeHidden.JSONSchemaValidator.prototype.validate = function(
instance, schema, opt_path) {
chromeHidden.JSONSchemaValidator.prototype.validate =
function(instance, schema, opt_path) {
var path = opt_path || "";
if (!schema) {
......@@ -216,8 +267,8 @@ chromeHidden.JSONSchemaValidator.prototype.validate = function(
* Validates an instance against a choices schema. The instance must match at
* least one of the provided choices.
*/
chromeHidden.JSONSchemaValidator.prototype.validateChoices = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateChoices =
function(instance, schema, path) {
var originalErrors = this.errors;
for (var i = 0; i < schema.choices.length; i++) {
......@@ -238,8 +289,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateChoices = function(
* |errors| property, and returns a boolean indicating whether the instance
* validates.
*/
chromeHidden.JSONSchemaValidator.prototype.validateEnum = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateEnum =
function(instance, schema, path) {
for (var i = 0; i < schema.enum.length; i++) {
if (instance === schema.enum[i])
return true;
......@@ -253,8 +304,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateEnum = function(
* Validates an instance against an object schema and populates the errors
* property.
*/
chromeHidden.JSONSchemaValidator.prototype.validateObject = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateObject =
function(instance, schema, path) {
if (schema.properties) {
for (var prop in schema.properties) {
// It is common in JavaScript to add properties to Object.prototype. This
......@@ -316,8 +367,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateObject = function(
* Validates an instance against an array schema and populates the errors
* property.
*/
chromeHidden.JSONSchemaValidator.prototype.validateArray = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateArray =
function(instance, schema, path) {
var typeOfItems = chromeHidden.JSONSchemaValidator.getType(schema.items);
if (typeOfItems == 'object') {
......@@ -363,8 +414,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateArray = function(
/**
* Validates a string and populates the errors property.
*/
chromeHidden.JSONSchemaValidator.prototype.validateString = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateString =
function(instance, schema, path) {
if (schema.minLength && instance.length < schema.minLength)
this.addError(path, "stringMinLength", [schema.minLength]);
......@@ -379,8 +430,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateString = function(
* Validates a number and populates the errors property. The instance is
* assumed to be a number.
*/
chromeHidden.JSONSchemaValidator.prototype.validateNumber = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateNumber =
function(instance, schema, path) {
// Forbid NaN, +Infinity, and -Infinity. Our APIs don't use them, and
// JSON serialization encodes them as 'null'. Re-evaluate supporting
......@@ -408,8 +459,8 @@ chromeHidden.JSONSchemaValidator.prototype.validateNumber = function(
* Validates the primitive type of an instance and populates the errors
* property. Returns true if the instance validates, false otherwise.
*/
chromeHidden.JSONSchemaValidator.prototype.validateType = function(
instance, schema, path) {
chromeHidden.JSONSchemaValidator.prototype.validateType =
function(instance, schema, path) {
var actualType = chromeHidden.JSONSchemaValidator.getType(instance);
if (schema.type != actualType && !(schema.type == "number" &&
actualType == "integer")) {
......@@ -425,12 +476,19 @@ chromeHidden.JSONSchemaValidator.prototype.validateType = function(
* |replacements| is an array of values to replace '*' characters in the
* message.
*/
chromeHidden.JSONSchemaValidator.prototype.addError = function(
path, key, replacements) {
chromeHidden.JSONSchemaValidator.prototype.addError =
function(path, key, replacements) {
this.errors.push({
path: path,
message: chromeHidden.JSONSchemaValidator.formatError(key, replacements)
});
};
/**
* Resets errors to an empty list so you can call 'validate' again.
*/
chromeHidden.JSONSchemaValidator.prototype.resetErrors = function() {
this.errors = [];
};
})();
......@@ -32,21 +32,20 @@ var chrome = chrome || {};
}
// Validate arguments.
chromeHidden.validationTypes = [];
chromeHidden.validate = function(args, schemas) {
if (args.length > schemas.length)
var schemaValidator = new chromeHidden.JSONSchemaValidator();
chromeHidden.validate = function(args, parameterSchemas) {
if (args.length > parameterSchemas.length)
throw new Error("Too many arguments.");
for (var i = 0; i < schemas.length; i++) {
for (var i = 0; i < parameterSchemas.length; i++) {
if (i in args && args[i] !== null && args[i] !== undefined) {
var validator = new chromeHidden.JSONSchemaValidator();
validator.addTypes(chromeHidden.validationTypes);
validator.validate(args[i], schemas[i]);
if (validator.errors.length == 0)
schemaValidator.resetErrors();
schemaValidator.validate(args[i], parameterSchemas[i]);
if (schemaValidator.errors.length == 0)
continue;
var message = "Invalid value for argument " + (i + 1) + ". ";
for (var i = 0, err; err = validator.errors[i]; i++) {
for (var i = 0, err; err = schemaValidator.errors[i]; i++) {
if (err.path) {
message += "Property '" + err.path + "': ";
}
......@@ -58,12 +57,121 @@ var chrome = chrome || {};
message += ".";
throw new Error(message);
} else if (!schemas[i].optional) {
} else if (!parameterSchemas[i].optional) {
throw new Error("Parameter " + (i + 1) + " is required.");
}
}
};
// Generate all possible signatures for a given API function.
function getSignatures(parameterSchemas) {
if (parameterSchemas.length === 0)
return [[]];
var signatures = [];
var remaining = getSignatures(parameterSchemas.slice(1));
for (var i = 0; i < remaining.length; i++)
signatures.push([parameterSchemas[0]].concat(remaining[i]))
if (parameterSchemas[0].optional)
return signatures.concat(remaining);
return signatures;
};
// Return true if arguments match a given signature's schema.
function argumentsMatchSignature(args, candidateSignature) {
if (args.length != candidateSignature.length)
return false;
for (var i = 0; i < candidateSignature.length; i++) {
var argType = chromeHidden.JSONSchemaValidator.getType(args[i]);
if (!schemaValidator.isValidSchemaType(argType, candidateSignature[i]))
return false;
}
return true;
};
// Finds the function signature for the given arguments.
function resolveSignature(args, definedSignature) {
var candidateSignatures = getSignatures(definedSignature);
for (var i = 0; i < candidateSignatures.length; i++) {
if (argumentsMatchSignature(args, candidateSignatures[i]))
return candidateSignatures[i];
}
return null;
};
// Returns a string representing the defined signature of the API function.
// Example return value for chrome.windows.getCurrent:
// "windows.getCurrent(optional object populate, function callback)"
function getParameterSignatureString(name, definedSignature) {
var getSchemaTypeString = function(schema) {
var schemaTypes = schemaValidator.getAllTypesForSchema(schema);
var typeName = schemaTypes.join(" or ") + " " + schema.name;
if (schema.optional)
return "optional " + typeName;
return typeName;
};
var typeNames = definedSignature.map(getSchemaTypeString);
return name + "(" + typeNames.join(", ") + ")";
};
// Returns a string representing a call to an API function.
// Example return value for call: chrome.windows.get(1, callback) is:
// "windows.get(int, function)"
function getArgumentSignatureString(name, args) {
var typeNames = args.map(chromeHidden.JSONSchemaValidator.getType);
return name + "(" + typeNames.join(", ") + ")";
};
// Finds the correct signature for the given arguments, then validates the
// arguments against that signature. Returns a 'normalized' arguments list
// where nulls are inserted where optional parameters were omitted.
chromeHidden.updateArgumentsValidate = function(args, funDef) {
var definedSignature = funDef.definition.parameters;
var resolvedSignature = resolveSignature(args, definedSignature);
if (!resolvedSignature)
throw new Error("Invocation of form " +
getArgumentSignatureString(funDef.name, args) +
" doesn't match definition " +
getParameterSignatureString(funDef.name, definedSignature));
chromeHidden.validate(args, resolvedSignature);
var normalizedArgs = [];
var ai = 0;
for (var si = 0; si < definedSignature.length; si++) {
if (definedSignature[si] === resolvedSignature[ai])
normalizedArgs.push(args[ai++]);
else
normalizedArgs.push(null);
}
return normalizedArgs;
};
// Validates that a given schema for an API function is not ambiguous.
function isDefinedSignatureAmbiguous(definedSignature) {
var signaturesAmbiguous = function(signature1, signature2) {
if (signature1.length != signature2.length)
return false;
for (var i = 0; i < signature1.length; i++) {
if (!schemaValidator.checkSchemaOverlap(signature1[i], signature2[i]))
return false;
}
return true;
};
var candidateSignatures = getSignatures(definedSignature);
for (var i = 0; i < candidateSignatures.length; i++) {
for (var j = i + 1; j < candidateSignatures.length; j++) {
if (signaturesAmbiguous(candidateSignatures[i], candidateSignatures[j]))
return true;
}
}
return false;
};
// Callback handling.
var requests = [];
chromeHidden.handleResponse = function(requestId, name,
......@@ -435,13 +543,13 @@ var chrome = chrome || {};
mod = mod[name];
}
// Add types to global validationTypes
// Add types to global schemaValidator
if (apiDef.types) {
apiDef.types.forEach(function(t) {
if (!isSchemaNodeSupported(t, platform, manifestVersion))
return;
chromeHidden.validationTypes.push(t);
schemaValidator.addTypes(t);
if (t.type == 'object' && customTypes[t.id]) {
customTypes[t.id].prototype.setSchema(t);
}
......@@ -490,13 +598,25 @@ var chrome = chrome || {};
var apiFunction = {};
apiFunction.definition = functionDef;
apiFunction.name = apiFunctionName;
apiFunctions.register(apiFunctionName, apiFunction);
// Validate API for ambiguity only in DEBUG mode.
// We do not validate 'extension.sendRequest' because we know it is
// ambiguous. We disambiguate calls in 'updateArgumentsPrevalidate'.
// TODO(aa): It would be best to run this in a unit test, but in order
// to do that we would need to better factor this code so that it
// didn't depend on so much v8::Extension machinery.
if (chromeHidden.validateAPI &&
apiFunction.name != "extension.sendRequest" &&
isDefinedSignatureAmbiguous(apiFunction.definition.parameters))
throw new Error(apiFunction.name + " is ambiguous");
apiFunctions.register(apiFunction.name, apiFunction);
mod[functionDef.name] = (function() {
var args = arguments;
var args = Array.prototype.slice.call(arguments);
if (this.updateArgumentsPreValidate)
args = this.updateArgumentsPreValidate.apply(this, args);
chromeHidden.validate(args, this.definition.parameters);
args = chromeHidden.updateArgumentsValidate(args, this);
if (this.updateArgumentsPostValidate)
args = this.updateArgumentsPostValidate.apply(this, args);
......
......@@ -43,25 +43,6 @@ chromeHidden.registerCustomHook('tabs', function(bindingsAPI, extensionId) {
}
});
});
// TODO(skerner,mtytel): The next step to omitting optional arguments is the
// replacement of this code with code that matches arguments by type.
// Once this is working for captureVisibleTab() it can be enabled for
// the rest of the API. See crbug/29215 .
apiFunctions.setUpdateArgumentsPreValidate('captureVisibleTab', function() {
// Old signature:
// captureVisibleTab(int windowId, function callback);
// New signature:
// captureVisibleTab(int windowId, object details, function callback);
var newArgs;
if (arguments.length == 2 && typeof(arguments[1]) == 'function') {
// If the old signature is used, add a null details object.
newArgs = [arguments[0], null, arguments[1]];
} else {
newArgs = arguments;
}
return newArgs;
});
});
})();
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Custom bindings for the windows API.
(function() {
native function GetChromeHidden();
GetChromeHidden().registerCustomHook('windows', function(api) {
var apiFunctions = api.apiFunctions;
apiFunctions.setUpdateArgumentsPreValidate('get', function() {
// Old signature:
// get(int windowId, function callback);
// New signature:
// get(int windowId, object populate, function callback);
if (arguments.length == 2 && typeof(arguments[1]) == 'function') {
// If the old signature is used, add a null populate object.
newArgs = [arguments[0], null, arguments[1]];
} else {
newArgs = arguments;
}
return newArgs;
});
apiFunctions.setUpdateArgumentsPreValidate('getCurrent', function() {
// Old signature:
// getCurrent(function callback);
// New signature:
// getCurrent(object populate, function callback);
if (arguments.length == 1 && typeof(arguments[0]) == 'function') {
// If the old signature is used, add a null populate object.
newArgs = [null, arguments[0]];
} else {
newArgs = arguments;
}
return newArgs;
});
apiFunctions.setUpdateArgumentsPreValidate('getLastFocused', function() {
// Old signature:
// getLastFocused(function callback);
// New signature:
// getLastFocused(object populate, function callback);
if (arguments.length == 1 && typeof(arguments[0]) == 'function') {
// If the old signature is used, add a null populate object.
newArgs = [null, arguments[0]];
} else {
newArgs = arguments;
}
return newArgs;
});
apiFunctions.setUpdateArgumentsPreValidate('getAll', function() {
// Old signature:
// getAll(function callback);
// New signature:
// getAll(object populate, function callback);
if (arguments.length == 1 && typeof(arguments[0]) == 'function') {
// If the old signature is used, add a null populate object.
newArgs = [null, arguments[0]];
} else {
newArgs = arguments;
}
return newArgs;
});
});
})();
......@@ -39,6 +39,21 @@ function assertNotValid(type, instance, schema, errors, types) {
}
}
function assertListConsistsOfElements(list, elements) {
for (var li = 0; li < list.length; li++) {
for (var ei = 0; ei < elements.length && list[li] != elements[ei]; ei++) { }
if (ei == elements.length) {
log("Expected type not found: " + list[li]);
assert(false);
}
}
}
function assertEqualSets(set1, set2) {
assertListConsistsOfElements(set1, set2);
assertListConsistsOfElements(set2, set1);
}
function formatError(key, replacements) {
return chromeHidden.JSONSchemaValidator.formatError(key, replacements);
}
......@@ -449,3 +464,147 @@ function testType() {
assertNotValid("Type", {}, {type: "function"},
[formatError("invalidType", ["function", "object"])]);
}
function testGetAllTypesForSchema() {
var referencedTypes = [
{
id: "ChoicesRef",
choices: [
{ type: "integer" },
{ type: "string" }
]
},
{
id: "ObjectRef",
type: "object",
}
];
var arraySchema = {
type: "array"
};
var choicesSchema = {
choices: [
{ type: "object" },
{ type: "function" }
]
};
var objectRefSchema = {
$ref: "ObjectRef"
};
var complexSchema = {
choices: [
{ $ref: "ChoicesRef" },
{ type: "function" },
{ $ref: "ObjectRef" }
]
};
var validator = new chromeHidden.JSONSchemaValidator();
validator.addTypes(referencedTypes);
var arraySchemaTypes = validator.getAllTypesForSchema(arraySchema);
assertEqualSets(arraySchemaTypes, ["array"]);
var choicesSchemaTypes = validator.getAllTypesForSchema(choicesSchema);
assertEqualSets(choicesSchemaTypes, ["object", "function"]);
var objectRefSchemaTypes = validator.getAllTypesForSchema(objectRefSchema);
assertEqualSets(objectRefSchemaTypes, ["object"]);
var complexSchemaTypes = validator.getAllTypesForSchema(complexSchema);
assertEqualSets(complexSchemaTypes,
["integer", "string", "function", "object"]);
}
function testIsValidSchemaType() {
var referencedTypes = [
{
id: "ChoicesRef",
choices: [
{ type: "integer" },
{ type: "string" }
]
}
];
var objectSchema = {
type: "object",
optional: true
};
var complexSchema = {
choices: [
{ $ref: "ChoicesRef" },
{ type: "function" },
]
};
var validator = new chromeHidden.JSONSchemaValidator();
validator.addTypes(referencedTypes);
assert(validator.isValidSchemaType("object", objectSchema));
assert(!validator.isValidSchemaType("integer", objectSchema));
assert(!validator.isValidSchemaType("array", objectSchema));
assert(validator.isValidSchemaType("null", objectSchema));
assert(validator.isValidSchemaType("undefined", objectSchema));
assert(validator.isValidSchemaType("integer", complexSchema));
assert(validator.isValidSchemaType("function", complexSchema));
assert(validator.isValidSchemaType("string", complexSchema));
assert(!validator.isValidSchemaType("object", complexSchema));
assert(!validator.isValidSchemaType("null", complexSchema));
assert(!validator.isValidSchemaType("undefined", complexSchema));
}
function testCheckSchemaOverlap() {
var referencedTypes = [
{
id: "ChoicesRef",
choices: [
{ type: "integer" },
{ type: "string" }
]
},
{
id: "ObjectRef",
type: "object",
}
];
var arraySchema = {
type: "array"
};
var choicesSchema = {
choices: [
{ type: "object" },
{ type: "function" }
]
};
var objectRefSchema = {
$ref: "ObjectRef"
};
var complexSchema = {
choices: [
{ $ref: "ChoicesRef" },
{ type: "function" },
{ $ref: "ObjectRef" }
]
};
var validator = new chromeHidden.JSONSchemaValidator();
validator.addTypes(referencedTypes);
assert(!validator.checkSchemaOverlap(arraySchema, choicesSchema));
assert(!validator.checkSchemaOverlap(arraySchema, objectRefSchema));
assert(!validator.checkSchemaOverlap(arraySchema, complexSchema));
assert(validator.checkSchemaOverlap(choicesSchema, objectRefSchema));
assert(validator.checkSchemaOverlap(choicesSchema, complexSchema));
assert(validator.checkSchemaOverlap(objectRefSchema, complexSchema));
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment