Bug 1293298 - Implement events in SubTypes defined in the WebExtensions API schema files.
MozReview-Commit-ID: CAYaenfSih1
--- a/toolkit/components/extensions/Schemas.jsm
+++ b/toolkit/components/extensions/Schemas.jsm
@@ -1348,16 +1348,17 @@ class StringType extends Type {
return {
descriptor: {value: obj},
};
}
}
}
let FunctionEntry;
+let Event;
let SubModuleType;
class ObjectType extends Type {
static get EXTRA_PROPERTIES() {
return ["properties", "patternProperties", ...super.EXTRA_PROPERTIES];
}
static parseSchema(schema, path, extraProperties = []) {
@@ -1611,22 +1612,30 @@ SubModuleType = class SubModuleType exte
static parseSchema(schema, path, extraProperties = []) {
this.checkSchemaProperties(schema, path, extraProperties);
// The path we pass in here is only used for error messages.
path = [...path, schema.id];
let functions = schema.functions.filter(fun => !fun.unsupported)
.map(fun => FunctionEntry.parseSchema(fun, path));
- return new this(functions);
+ let events = [];
+
+ if (schema.events) {
+ events = schema.events.filter(event => !event.unsupported)
+ .map(event => Event.parseSchema(event, path));
+ }
+
+ return new this(functions, events);
}
- constructor(functions) {
+ constructor(functions, events) {
super();
this.functions = functions;
+ this.events = events;
}
};
class NumberType extends Type {
normalize(value, context) {
let r = this.normalizeBase("number", value, context);
if (r.error) {
return r;
@@ -1939,16 +1948,21 @@ class SubModuleProperty extends Entry {
}
let subpath = [...path, this.name];
let functions = type.functions;
for (let fun of functions) {
context.injectInto(fun, obj, fun.name, subpath, ns);
}
+ let events = type.events;
+ for (let event of events) {
+ context.injectInto(event, obj, event.name, subpath, ns);
+ }
+
// TODO: Inject this.properties.
return {
descriptor: {value: obj},
revoke() {
let unwrapped = Cu.waiveXrays(obj);
for (let fun of functions) {
try {
@@ -2116,17 +2130,20 @@ FunctionEntry = class FunctionEntry exte
apiImpl.revoke();
apiImpl = null;
},
};
}
};
// Represents an "event" defined in a schema namespace.
-class Event extends CallEntry {
+//
+// TODO(rpl): we should be able to remove the eslint-disable-line that follows
+// once Bug 1369722 has been fixed.
+Event = class Event extends CallEntry { // eslint-disable-line no-native-reassign
static parseSchema(event, path) {
let extraParameters = Array.from(event.extraParameters || [], param => ({
type: Schemas.parseSchema(param, path, ["name", "optional", "default"]),
name: param.name,
optional: param.optional || false,
default: param.default == undefined ? null : param.default,
}));
@@ -2189,17 +2206,17 @@ class Event extends CallEntry {
let unwrapped = Cu.waiveXrays(obj);
delete unwrapped.addListener;
delete unwrapped.removeListener;
delete unwrapped.hasListener;
},
};
}
-}
+};
const TYPES = Object.freeze(Object.assign(Object.create(null), {
any: AnyType,
array: ArrayType,
boolean: BooleanType,
function: FunctionType,
integer: IntegerType,
number: NumberType,
--- a/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_schemas.js
@@ -1217,16 +1217,17 @@ let nestedNamespaceJson = [
"namespace": "nested.namespace",
"types": [
{
"id": "CustomType",
"type": "object",
"events": [
{
"name": "onEvent",
+ "type": "function",
},
],
"properties": {
"url": {
"type": "string",
},
},
"functions": [
@@ -1281,27 +1282,37 @@ add_task(async function testNestedNamesp
"The property is a function as expected");
let {instanceOfCustomType} = root.nested.namespace;
ok(instanceOfCustomType,
"Got the expected instance of the CustomType defined in the schema");
ok(instanceOfCustomType.functionOnCustomType,
"Got the expected method in the CustomType instance");
+ ok(instanceOfCustomType.onEvent &&
+ instanceOfCustomType.onEvent.addListener &&
+ typeof instanceOfCustomType.onEvent.addListener == "function",
+ "Got the expected event defined in the CustomType instance");
- // TODO: test support events and properties in a SubModuleType defined in the schema,
+ instanceOfCustomType.functionOnCustomType("param_value");
+ verify("call", "nested.namespace.instanceOfCustomType",
+ "functionOnCustomType", ["param_value"]);
+
+ let fakeListener = () => {};
+ instanceOfCustomType.onEvent.addListener(fakeListener);
+ verify("addListener", "nested.namespace.instanceOfCustomType",
+ "onEvent", [fakeListener, []]);
+ instanceOfCustomType.onEvent.removeListener(fakeListener);
+ verify("removeListener", "nested.namespace.instanceOfCustomType",
+ "onEvent", [fakeListener]);
+
+ // TODO: test support properties in a SubModuleType defined in the schema,
// once implemented, e.g.:
- //
- // ok(instanceOfCustomType.url,
- // "Got the expected property defined in the CustomType instance)
- //
- // ok(instanceOfCustomType.onEvent &&
- // instanceOfCustomType.onEvent.addListener &&
- // typeof instanceOfCustomType.onEvent.addListener == "function",
- // "Got the expected event defined in the CustomType instance");
+ // ok("url" in instanceOfCustomType,
+ // "Got the expected property defined in the CustomType instance");
});
let $importJson = [
{
namespace: "from_the",
$import: "future",
},
{