forked from mirrors/gecko-dev
240 lines
5.1 KiB
JavaScript
240 lines
5.1 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
const { SchemaRoot } = ChromeUtils.import("resource://gre/modules/Schemas.jsm");
|
|
|
|
let { SchemaAPIInterface } = ExtensionCommon;
|
|
|
|
const global = this;
|
|
|
|
let baseSchemaJSON = [
|
|
{
|
|
namespace: "base",
|
|
|
|
properties: {
|
|
PROP1: { value: 42 },
|
|
},
|
|
|
|
types: [
|
|
{
|
|
id: "type1",
|
|
type: "string",
|
|
enum: ["value1", "value2", "value3"],
|
|
},
|
|
],
|
|
|
|
functions: [
|
|
{
|
|
name: "foo",
|
|
type: "function",
|
|
parameters: [{ name: "arg1", $ref: "type1" }],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
let experimentFooJSON = [
|
|
{
|
|
namespace: "experiments.foo",
|
|
types: [
|
|
{
|
|
id: "typeFoo",
|
|
type: "string",
|
|
enum: ["foo1", "foo2", "foo3"],
|
|
},
|
|
],
|
|
|
|
functions: [
|
|
{
|
|
name: "foo",
|
|
type: "function",
|
|
parameters: [
|
|
{ name: "arg1", $ref: "typeFoo" },
|
|
{ name: "arg2", $ref: "base.type1" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
let experimentBarJSON = [
|
|
{
|
|
namespace: "experiments.bar",
|
|
types: [
|
|
{
|
|
id: "typeBar",
|
|
type: "string",
|
|
enum: ["bar1", "bar2", "bar3"],
|
|
},
|
|
],
|
|
|
|
functions: [
|
|
{
|
|
name: "bar",
|
|
type: "function",
|
|
parameters: [
|
|
{ name: "arg1", $ref: "typeBar" },
|
|
{ name: "arg2", $ref: "base.type1" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
let tallied = null;
|
|
|
|
function tally(kind, ns, name, args) {
|
|
tallied = [kind, ns, name, args];
|
|
}
|
|
|
|
function verify(...args) {
|
|
equal(JSON.stringify(tallied), JSON.stringify(args));
|
|
tallied = null;
|
|
}
|
|
|
|
let talliedErrors = [];
|
|
|
|
let permissions = new Set();
|
|
|
|
class TallyingAPIImplementation extends SchemaAPIInterface {
|
|
constructor(namespace, name) {
|
|
super();
|
|
this.namespace = namespace;
|
|
this.name = name;
|
|
}
|
|
|
|
callFunction(args) {
|
|
tally("call", this.namespace, this.name, args);
|
|
if (this.name === "sub_foo") {
|
|
return 13;
|
|
}
|
|
}
|
|
|
|
callFunctionNoReturn(args) {
|
|
tally("call", this.namespace, this.name, args);
|
|
}
|
|
|
|
getProperty() {
|
|
tally("get", this.namespace, this.name);
|
|
}
|
|
|
|
setProperty(value) {
|
|
tally("set", this.namespace, this.name, value);
|
|
}
|
|
|
|
addListener(listener, args) {
|
|
tally("addListener", this.namespace, this.name, [listener, args]);
|
|
}
|
|
|
|
removeListener(listener) {
|
|
tally("removeListener", this.namespace, this.name, [listener]);
|
|
}
|
|
|
|
hasListener(listener) {
|
|
tally("hasListener", this.namespace, this.name, [listener]);
|
|
}
|
|
}
|
|
|
|
let wrapper = {
|
|
url: "moz-extension://b66e3509-cdb3-44f6-8eb8-c8b39b3a1d27/",
|
|
manifestVersion: 2,
|
|
|
|
cloneScope: global,
|
|
|
|
checkLoadURL(url) {
|
|
return !url.startsWith("chrome:");
|
|
},
|
|
|
|
preprocessors: {
|
|
localize(value, context) {
|
|
return value.replace(/__MSG_(.*?)__/g, (m0, m1) => `${m1.toUpperCase()}`);
|
|
},
|
|
},
|
|
|
|
logError(message) {
|
|
talliedErrors.push(message);
|
|
},
|
|
|
|
hasPermission(permission) {
|
|
return permissions.has(permission);
|
|
},
|
|
|
|
shouldInject(ns, name) {
|
|
return name != "do-not-inject";
|
|
},
|
|
|
|
getImplementation(namespace, name) {
|
|
return new TallyingAPIImplementation(namespace, name);
|
|
},
|
|
};
|
|
|
|
add_task(async function() {
|
|
let baseSchemas = new Map([["resource://schemas/base.json", baseSchemaJSON]]);
|
|
let experimentSchemas = new Map([
|
|
["resource://experiment-foo/schema.json", experimentFooJSON],
|
|
["resource://experiment-bar/schema.json", experimentBarJSON],
|
|
]);
|
|
|
|
let baseSchema = new SchemaRoot(null, baseSchemas);
|
|
let schema = new SchemaRoot(baseSchema, experimentSchemas);
|
|
|
|
baseSchema.parseSchemas();
|
|
schema.parseSchemas();
|
|
|
|
let root = {};
|
|
let base = {};
|
|
|
|
tallied = null;
|
|
|
|
baseSchema.inject(base, wrapper);
|
|
schema.inject(root, wrapper);
|
|
|
|
equal(typeof base.base, "object", "base.base exists");
|
|
equal(typeof root.base, "object", "root.base exists");
|
|
equal(typeof base.experiments, "undefined", "base.experiments exists not");
|
|
equal(typeof root.experiments, "object", "root.experiments exists");
|
|
equal(typeof root.experiments.foo, "object", "root.experiments.foo exists");
|
|
equal(typeof root.experiments.bar, "object", "root.experiments.bar exists");
|
|
|
|
equal(tallied, null);
|
|
|
|
equal(root.base.PROP1, 42, "root.base.PROP1");
|
|
equal(base.base.PROP1, 42, "root.base.PROP1");
|
|
|
|
root.base.foo("value2");
|
|
verify("call", "base", "foo", ["value2"]);
|
|
|
|
base.base.foo("value3");
|
|
verify("call", "base", "foo", ["value3"]);
|
|
|
|
root.experiments.foo.foo("foo2", "value1");
|
|
verify("call", "experiments.foo", "foo", ["foo2", "value1"]);
|
|
|
|
root.experiments.bar.bar("bar2", "value1");
|
|
verify("call", "experiments.bar", "bar", ["bar2", "value1"]);
|
|
|
|
Assert.throws(
|
|
() => root.base.foo("Meh."),
|
|
/Type error for parameter arg1/,
|
|
"root.base.foo()"
|
|
);
|
|
|
|
Assert.throws(
|
|
() => base.base.foo("Meh."),
|
|
/Type error for parameter arg1/,
|
|
"base.base.foo()"
|
|
);
|
|
|
|
Assert.throws(
|
|
() => root.experiments.foo.foo("Meh."),
|
|
/Incorrect argument types/,
|
|
"root.experiments.foo.foo()"
|
|
);
|
|
|
|
Assert.throws(
|
|
() => root.experiments.bar.bar("Meh."),
|
|
/Incorrect argument types/,
|
|
"root.experiments.bar.bar()"
|
|
);
|
|
});
|