Move Add-on SDK source to toolkit/jetpack

This commit is contained in:
NTD 2018-02-09 06:46:43 -05:00 committed by Roy Tam
commit 23b67db438
993 changed files with 484 additions and 100663 deletions

View file

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
module.metadata = {
'stability': 'unstable'
};
const events = require('./events.js');
exports.emit = (element, type, obj) => events.emit(element, type, obj, true);
exports.on = (element, type, listener, capture) => events.on(element, type, listener, capture, true);
exports.once = (element, type, listener, capture) => events.once(element, type, listener, capture, true);
exports.removeListener = (element, type, listener, capture) => events.removeListener(element, type, listener, capture, true);
exports.removed = events.removed;
exports.when = (element, eventName, capture) => events.when(element, eventName, capture ? capture : false, true);

View file

@ -0,0 +1,192 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "unstable"
};
const { Cu } = require("chrome");
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
// Utility function that returns copy of the given `text` with last character
// removed if it is `"s"`.
function singularify(text) {
return text[text.length - 1] === "s" ? text.substr(0, text.length - 1) : text;
}
// Utility function that takes event type, argument is passed to
// `document.createEvent` and returns name of the initializer method of the
// given event. Please note that there are some event types whose initializer
// methods can't be guessed by this function. For more details see following
// link: https://developer.mozilla.org/En/DOM/Document.createEvent
function getInitializerName(category) {
return "init" + singularify(category);
}
/**
* Registers an event `listener` on a given `element`, that will be called
* when events of specified `type` is dispatched on the `element`.
* @param {Element} element
* Dom element to register listener on.
* @param {String} type
* A string representing the
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
* listen for.
* @param {Function} listener
* Function that is called whenever an event of the specified `type`
* occurs.
* @param {Boolean} capture
* If true, indicates that the user wishes to initiate capture. After
* initiating capture, all events of the specified type will be dispatched
* to the registered listener before being dispatched to any `EventTarget`s
* beneath it in the DOM tree. Events which are bubbling upward through
* the tree will not trigger a listener designated to use capture.
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
* for a detailed explanation.
*/
function on(element, type, listener, capture, shimmed = false) {
// `capture` defaults to `false`.
capture = capture || false;
if (shimmed) {
element.addEventListener(type, listener, capture);
} else {
ShimWaiver.getProperty(element, "addEventListener")(type, listener, capture);
}
}
exports.on = on;
/**
* Registers an event `listener` on a given `element`, that will be called
* only once, next time event of specified `type` is dispatched on the
* `element`.
* @param {Element} element
* Dom element to register listener on.
* @param {String} type
* A string representing the
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
* listen for.
* @param {Function} listener
* Function that is called whenever an event of the specified `type`
* occurs.
* @param {Boolean} capture
* If true, indicates that the user wishes to initiate capture. After
* initiating capture, all events of the specified type will be dispatched
* to the registered listener before being dispatched to any `EventTarget`s
* beneath it in the DOM tree. Events which are bubbling upward through
* the tree will not trigger a listener designated to use capture.
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
* for a detailed explanation.
*/
function once(element, type, listener, capture, shimmed = false) {
on(element, type, function selfRemovableListener(event) {
removeListener(element, type, selfRemovableListener, capture, shimmed);
listener.apply(this, arguments);
}, capture, shimmed);
}
exports.once = once;
/**
* Unregisters an event `listener` on a given `element` for the events of the
* specified `type`.
*
* @param {Element} element
* Dom element to unregister listener from.
* @param {String} type
* A string representing the
* [event type](https://developer.mozilla.org/en/DOM/event.type) to
* listen for.
* @param {Function} listener
* Function that is called whenever an event of the specified `type`
* occurs.
* @param {Boolean} capture
* If true, indicates that the user wishes to initiate capture. After
* initiating capture, all events of the specified type will be dispatched
* to the registered listener before being dispatched to any `EventTarget`s
* beneath it in the DOM tree. Events which are bubbling upward through
* the tree will not trigger a listener designated to use capture.
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
* for a detailed explanation.
*/
function removeListener(element, type, listener, capture, shimmed = false) {
if (shimmed) {
element.removeEventListener(type, listener, capture);
} else {
ShimWaiver.getProperty(element, "removeEventListener")(type, listener, capture);
}
}
exports.removeListener = removeListener;
/**
* Emits event of the specified `type` and `category` on the given `element`.
* Specified `settings` are used to initialize event before dispatching it.
* @param {Element} element
* Dom element to dispatch event on.
* @param {String} type
* A string representing the
* [event type](https://developer.mozilla.org/en/DOM/event.type).
* @param {Object} options
* Options object containing following properties:
* - `category`: String passed to the `document.createEvent`. Option is
* optional and defaults to "UIEvents".
* - `initializer`: If passed it will be used as name of the method used
* to initialize event. If omitted name will be generated from the
* `category` field by prefixing it with `"init"` and removing last
* character if it matches `"s"`.
* - `settings`: Array of settings that are forwarded to the event
* initializer after firs `type` argument.
* @see https://developer.mozilla.org/En/DOM/Document.createEvent
*/
function emit(element, type, { category, initializer, settings }, shimmed = false) {
category = category || "UIEvents";
initializer = initializer || getInitializerName(category);
let document = element.ownerDocument;
let event = document.createEvent(category);
event[initializer].apply(event, [type].concat(settings));
if (shimmed) {
element.dispatchEvent(event);
} else {
ShimWaiver.getProperty(element, "dispatchEvent")(event);
}
};
exports.emit = emit;
// Takes DOM `element` and returns promise which is resolved
// when given element is removed from it's parent node.
const removed = element => {
return new Promise(resolve => {
const { MutationObserver } = element.ownerDocument.defaultView;
const observer = new MutationObserver(mutations => {
for (let mutation of mutations) {
for (let node of mutation.removedNodes || []) {
if (node === element) {
observer.disconnect();
resolve(element);
}
}
}
});
observer.observe(element.parentNode, {childList: true});
});
};
exports.removed = removed;
const when = (element, eventName, capture=false, shimmed=false) => new Promise(resolve => {
const listener = event => {
if (shimmed) {
element.removeEventListener(eventName, listener, capture);
} else {
ShimWaiver.getProperty(element, "removeEventListener")(eventName, listener, capture);
}
resolve(event);
};
if (shimmed) {
element.addEventListener(eventName, listener, capture);
} else {
ShimWaiver.getProperty(element, "addEventListener")(eventName, listener, capture);
}
});
exports.when = when;

View file

@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "unstable"
};
const { emit } = require("../events");
const { getCodeForKey, toJSON } = require("../../keyboard/utils");
const { has } = require("../../util/array");
const { isString } = require("../../lang/type");
const INITIALIZER = "initKeyEvent";
const CATEGORY = "KeyboardEvent";
function Options(options) {
if (!isString(options))
return options;
var { key, modifiers } = toJSON(options);
return {
key: key,
control: has(modifiers, "control"),
alt: has(modifiers, "alt"),
shift: has(modifiers, "shift"),
meta: has(modifiers, "meta")
};
}
var keyEvent = exports.keyEvent = function keyEvent(element, type, options) {
emit(element, type, {
initializer: INITIALIZER,
category: CATEGORY,
settings: [
!("bubbles" in options) || options.bubbles !== false,
!("cancelable" in options) || options.cancelable !== false,
"window" in options && options.window ? options.window : null,
"control" in options && !!options.control,
"alt" in options && !!options.alt,
"shift" in options && !!options.shift,
"meta" in options && !!options.meta,
getCodeForKey(options.key) || 0,
options.key.length === 1 ? options.key.charCodeAt(0) : 0
]
});
}
exports.keyDown = function keyDown(element, options) {
keyEvent(element, "keydown", Options(options));
};
exports.keyUp = function keyUp(element, options) {
keyEvent(element, "keyup", Options(options));
};
exports.keyPress = function keyPress(element, options) {
keyEvent(element, "keypress", Options(options));
};