Bug 1262250 - Add a defaultValue property to the web extension schema, r=aswan

MozReview-Commit-ID: 175Nxr39NKw

--HG--
extra : rebase_source : 0e912eb54e8179a22ee97c731885cd8d2715db1b
This commit is contained in:
Bob Silverberg 2016-10-03 14:55:17 -04:00
Родитель a7ad6a382a
Коммит 4e2ac40f90
2 изменённых файлов: 76 добавлений и 10 удалений

Просмотреть файл

@ -9,6 +9,8 @@ const Cc = Components.classes;
const Cu = Components.utils;
const Cr = Components.results;
const global = this;
Cu.importGlobalProperties(["URL"]);
Cu.import("resource://gre/modules/NetUtil.jsm");
@ -1291,9 +1293,10 @@ class FunctionType extends Type {
let isCallback = isAsync && param.name == schema.async;
parameters.push({
type: Schemas.parseSchema(param, path, ["name", "optional"]),
type: Schemas.parseSchema(param, path, ["name", "optional", "default"]),
name: param.name,
optional: param.optional == null ? isCallback : param.optional,
default: param.default == undefined ? null : param.default,
});
}
}
@ -1461,8 +1464,7 @@ class CallEntry extends Entry {
let fixedArgs = [];
// First we create a new array, fixedArgs, that is the same as
// |args| but with null values in place of omitted optional
// parameters.
// |args| but with default values in place of omitted optional parameters.
let check = (parameterIndex, argIndex) => {
if (parameterIndex == this.parameters.length) {
if (argIndex == args.length) {
@ -1474,7 +1476,7 @@ class CallEntry extends Entry {
let parameter = this.parameters[parameterIndex];
if (parameter.optional) {
// Try skipping it.
fixedArgs[parameterIndex] = null;
fixedArgs[parameterIndex] = parameter.default;
if (check(parameterIndex + 1, argIndex)) {
return true;
}
@ -1486,8 +1488,10 @@ class CallEntry extends Entry {
let arg = args[argIndex];
if (!parameter.type.checkBaseType(getValueBaseType(arg))) {
// For Chrome compatibility, use the default value if null or undefined
// is explicitly passed but is not a valid argument in this position.
if (parameter.optional && (arg === null || arg === undefined)) {
fixedArgs[parameterIndex] = null;
fixedArgs[parameterIndex] = Cu.cloneInto(parameter.default, global);
} else {
return false;
}
@ -1757,9 +1761,10 @@ this.Schemas = {
let extras = event.extraParameters || [];
extras = extras.map(param => {
return {
type: this.parseSchema(param, [namespaceName], ["name", "optional"]),
type: this.parseSchema(param, [namespaceName], ["name", "optional", "default"]),
name: param.name,
optional: param.optional || false,
default: param.default == undefined ? null : param.default,
};
});

Просмотреть файл

@ -85,7 +85,7 @@ let json = [
name: "foo",
type: "function",
parameters: [
{name: "arg1", type: "integer", optional: true},
{name: "arg1", type: "integer", optional: true, default: 99},
{name: "arg2", type: "boolean", optional: true},
],
},
@ -341,6 +341,8 @@ let json = [
extraParameters: [{
name: "filter",
type: "integer",
optional: true,
default: 1,
}],
},
],
@ -476,13 +478,13 @@ add_task(function* () {
verify("call", "testing", "foo", [11, true]);
root.testing.foo(true);
verify("call", "testing", "foo", [null, true]);
verify("call", "testing", "foo", [99, true]);
root.testing.foo(null, true);
verify("call", "testing", "foo", [null, true]);
verify("call", "testing", "foo", [99, true]);
root.testing.foo(undefined, true);
verify("call", "testing", "foo", [null, true]);
verify("call", "testing", "foo", [99, true]);
root.testing.foo(11);
verify("call", "testing", "foo", [11, null]);
@ -734,6 +736,12 @@ add_task(function* () {
do_check_eq(JSON.stringify(tallied[3][1]), JSON.stringify([10]));
tallied = null;
root.testing.onBar.addListener(f);
do_check_eq(JSON.stringify(tallied.slice(0, -1)), JSON.stringify(["addListener", "testing", "onBar"]));
do_check_eq(tallied[3][0], f);
do_check_eq(JSON.stringify(tallied[3][1]), JSON.stringify([1]));
tallied = null;
Assert.throws(() => root.testing.onBar.addListener(f, "hi"),
/Incorrect argument types/,
"addListener with wrong extra parameter should throw");
@ -1364,3 +1372,56 @@ add_task(function* testLocalAPIImplementation() {
do_check_eq(root.testing.prop3.sub_foo(), "overwritten again");
do_check_eq(countProp3SubFoo, 2);
});
let defaultsJson = [
{namespace: "defaultsJson",
types: [],
functions: [
{
name: "defaultFoo",
type: "function",
parameters: [
{name: "arg", type: "object", optional: true, properties: {
prop1: {type: "integer", optional: true},
}, default: {prop1: 1}},
],
returns: {
type: "object",
},
},
]},
];
add_task(function* testDefaults() {
let url = "data:," + JSON.stringify(defaultsJson);
yield Schemas.load(url);
let testingApiObj = {
defaultFoo: function(arg) {
if (Object.keys(arg) != "prop1") {
throw new Error(`Received the expected default object, default: ${JSON.stringify(arg)}`);
}
arg.newProp = 1;
return arg;
},
};
let localWrapper = {
shouldInject(ns) {
return true;
},
getImplementation(ns, name) {
return new LocalAPIImplementation(testingApiObj, name, null);
},
};
let root = {};
Schemas.inject(root, localWrapper);
deepEqual(root.defaultsJson.defaultFoo(), {prop1: 1, newProp: 1});
deepEqual(root.defaultsJson.defaultFoo({prop1: 2}), {prop1: 2, newProp: 1});
deepEqual(root.defaultsJson.defaultFoo(), {prop1: 1, newProp: 1});
});