aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.12/lib/sdk/deprecated
diff options
context:
space:
mode:
Diffstat (limited to 'tools/addon-sdk-1.12/lib/sdk/deprecated')
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/api-utils.js158
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/app-strings.js67
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/cortex.js113
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/errors.js64
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/events.js182
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/events/assembler.js53
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/light-traits.js600
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/list.js118
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/memory.js118
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js134
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/tab-browser.js731
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/traits.js187
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/traits/core.js322
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test-finder.js71
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test.js451
-rw-r--r--tools/addon-sdk-1.12/lib/sdk/deprecated/window-utils.js201
16 files changed, 3570 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/api-utils.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/api-utils.js
new file mode 100644
index 0000000..521ad6e
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/api-utils.js
@@ -0,0 +1,158 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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": "deprecated"
+};
+
+const memory = require("./memory");
+// The possible return values of getTypeOf.
+const VALID_TYPES = [
+ "array",
+ "boolean",
+ "function",
+ "null",
+ "number",
+ "object",
+ "string",
+ "undefined",
+];
+
+/**
+ * Returns a function C that creates instances of privateCtor. C may be called
+ * with or without the new keyword. The prototype of each instance returned
+ * from C is C.prototype, and C.prototype is an object whose prototype is
+ * privateCtor.prototype. Instances returned from C will therefore be instances
+ * of both C and privateCtor. Additionally, the constructor of each instance
+ * returned from C is C.
+ *
+ * @param privateCtor
+ * A constructor.
+ * @return A function that makes new instances of privateCtor.
+ */
+exports.publicConstructor = function publicConstructor(privateCtor) {
+ function PublicCtor() {
+ let obj = { constructor: PublicCtor, __proto__: PublicCtor.prototype };
+ memory.track(obj, privateCtor.name);
+ privateCtor.apply(obj, arguments);
+ return obj;
+ }
+ PublicCtor.prototype = { __proto__: privateCtor.prototype };
+ return PublicCtor;
+};
+
+/**
+ * Returns a validated options dictionary given some requirements. If any of
+ * the requirements are not met, an exception is thrown.
+ *
+ * @param options
+ * An object, the options dictionary to validate. It's not modified.
+ * If it's null or otherwise falsey, an empty object is assumed.
+ * @param requirements
+ * An object whose keys are the expected keys in options. Any key in
+ * options that is not present in requirements is ignored. Each value
+ * in requirements is itself an object describing the requirements of
+ * its key. There are four optional keys in this object:
+ * map: A function that's passed the value of the key in options.
+ * map's return value is taken as the key's value in the final
+ * validated options, is, and ok. If map throws an exception
+ * it's caught and discarded, and the key's value is its value in
+ * options.
+ * is: An array containing any number of the typeof type names. If
+ * the key's value is none of these types, it fails validation.
+ * Arrays and null are identified by the special type names
+ * "array" and "null"; "object" will not match either. No type
+ * coercion is done.
+ * ok: A function that's passed the key's value. If it returns
+ * false, the value fails validation.
+ * msg: If the key's value fails validation, an exception is thrown.
+ * This string will be used as its message. If undefined, a
+ * generic message is used, unless is is defined, in which case
+ * the message will state that the value needs to be one of the
+ * given types.
+ * @return An object whose keys are those keys in requirements that are also in
+ * options and whose values are the corresponding return values of map
+ * or the corresponding values in options. Note that any keys not
+ * shared by both requirements and options are not in the returned
+ * object.
+ */
+exports.validateOptions = function validateOptions(options, requirements) {
+ options = options || {};
+ let validatedOptions = {};
+ let mapThrew = false;
+
+ for (let key in requirements) {
+ let req = requirements[key];
+ let [optsVal, keyInOpts] = (key in options) ?
+ [options[key], true] :
+ [undefined, false];
+ if (req.map) {
+ try {
+ optsVal = req.map(optsVal);
+ }
+ catch (err) {
+ mapThrew = true;
+ }
+ }
+ if (req.is) {
+ // Sanity check the caller's type names.
+ req.is.forEach(function (typ) {
+ if (VALID_TYPES.indexOf(typ) < 0) {
+ let msg = 'Internal error: invalid requirement type "' + typ + '".';
+ throw new Error(msg);
+ }
+ });
+ if (req.is.indexOf(getTypeOf(optsVal)) < 0)
+ throw requirementError(key, req);
+ }
+ if (req.ok && !req.ok(optsVal))
+ throw requirementError(key, req);
+
+ if (keyInOpts || (req.map && !mapThrew))
+ validatedOptions[key] = optsVal;
+ }
+
+ return validatedOptions;
+};
+
+exports.addIterator = function addIterator(obj, keysValsGenerator) {
+ obj.__iterator__ = function(keysOnly, keysVals) {
+ let keysValsIterator = keysValsGenerator.call(this);
+
+ // "for (.. in ..)" gets only keys, "for each (.. in ..)" gets values,
+ // and "for (.. in Iterator(..))" gets [key, value] pairs.
+ let index = keysOnly ? 0 : 1;
+ while (true)
+ yield keysVals ? keysValsIterator.next() : keysValsIterator.next()[index];
+ };
+};
+
+// Similar to typeof, except arrays and null are identified by "array" and
+// "null", not "object".
+let getTypeOf = exports.getTypeOf = function getTypeOf(val) {
+ let typ = typeof(val);
+ if (typ === "object") {
+ if (!val)
+ return "null";
+ if (Array.isArray(val))
+ return "array";
+ }
+ return typ;
+}
+
+// Returns a new Error with a nice message.
+function requirementError(key, requirement) {
+ let msg = requirement.msg;
+ if (!msg) {
+ msg = 'The option "' + key + '" ';
+ msg += requirement.is ?
+ "must be one of the following types: " + requirement.is.join(", ") :
+ "is invalid.";
+ }
+ return new Error(msg);
+}
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/app-strings.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/app-strings.js
new file mode 100644
index 0000000..e09f79e
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/app-strings.js
@@ -0,0 +1,67 @@
+/* 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": "deprecated"
+};
+
+const {Cc,Ci} = require("chrome");
+const apiUtils = require("./api-utils");
+
+/**
+ * A bundle of strings.
+ *
+ * @param url {String}
+ * the URL of the string bundle
+ */
+exports.StringBundle = apiUtils.publicConstructor(function StringBundle(url) {
+
+ let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
+ getService(Ci.nsIStringBundleService).
+ createBundle(url);
+
+ this.__defineGetter__("url", function () url);
+
+ /**
+ * Get a string from the bundle.
+ *
+ * @param name {String}
+ * the name of the string to get
+ * @param args {array} [optional]
+ * an array of arguments that replace occurrences of %S in the string
+ *
+ * @returns {String} the value of the string
+ */
+ this.get = function strings_get(name, args) {
+ try {
+ if (args)
+ return stringBundle.formatStringFromName(name, args, args.length);
+ else
+ return stringBundle.GetStringFromName(name);
+ }
+ catch(ex) {
+ // f.e. "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)
+ // [nsIStringBundle.GetStringFromName]"
+ throw new Error("String '" + name + "' could not be retrieved from the " +
+ "bundle due to an unknown error (it doesn't exist?).");
+ }
+ },
+
+ /**
+ * Iterate the strings in the bundle.
+ *
+ */
+ apiUtils.addIterator(
+ this,
+ function keysValsGen() {
+ let enumerator = stringBundle.getSimpleEnumeration();
+ while (enumerator.hasMoreElements()) {
+ let elem = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
+ yield [elem.key, elem.value];
+ }
+ }
+ );
+});
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/cortex.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/cortex.js
new file mode 100644
index 0000000..8eef91c
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/cortex.js
@@ -0,0 +1,113 @@
+/* vim:set ts=2 sw=2 sts=2
+ * 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": "deprecated"
+};
+
+// `var` is being used in the module in order to make it reusable in
+// environments in which `let` and `const` is not yet supported.
+
+// Returns `object`'s property value, where `name` is a name of the property.
+function get(object, name) {
+ return object[name];
+}
+
+// Assigns `value` to the `object`'s property, where `name` is the name of the
+// property.
+function set(object, name, value) {
+ return object[name] = value;
+}
+
+/**
+ * Given an `object` containing a property with the given `name`, create
+ * a property descriptor that can be used to define alias/proxy properties
+ * on other objects. A change in the value of an alias will propagate
+ * to the aliased property and vice versa.
+ */
+function createAliasProperty(object, name) {
+ // Getting own property descriptor of an `object` for the given `name` as
+ // we are going to create proxy analog.
+ var property = Object.getOwnPropertyDescriptor(object, name);
+ var descriptor = {
+ configurable: property.configurable,
+ enumerable: property.enumerable,
+ alias: true
+ };
+
+ // If the original property has a getter and/or setter, bind a
+ // corresponding getter/setter in the alias descriptor to the original
+ // object, so the `this` object in the getter/setter is the original object
+ // rather than the alias.
+ if ("get" in property && property.get)
+ descriptor.get = property.get.bind(object);
+ if ("set" in property && property.set)
+ descriptor.set = property.set.bind(object);
+
+ // If original property was a value property.
+ if ("value" in property) {
+ // If original property is a method using it's `object` bounded copy.
+ if (typeof property.value === "function") {
+ descriptor.value = property.value.bind(object);
+ // Also preserving writability of the original property.
+ descriptor.writable = property.writable;
+ }
+
+ // If the original property was just a data property, we create proxy
+ // accessors using our custom get/set functions to propagate changes to the
+ // original `object` and vice versa.
+ else {
+ descriptor.get = get.bind(null, object, name);
+ descriptor.set = set.bind(null, object, name);
+ }
+ }
+ return descriptor;
+}
+
+// Defines property on `object` object with a name `alias` if given if not
+// defaults to `name` that represents an alias of `source[name]`. If aliased
+// property was an assessor or a method `this` pseudo-variable will be `source`
+// when invoked. If aliased property was a data property changes on any of the
+// aliases will propagate to the `source[name]` and also other way round.
+function defineAlias(source, target, name, alias) {
+ return Object.defineProperty(target, alias || name,
+ createAliasProperty(source, name));
+}
+
+/**
+ * Function takes any `object` and returns a proxy for its own public
+ * properties. By default properties are considered to be public if they don't
+ * start with `"_"`, but default behavior can be overridden if needed, by
+ * passing array of public property `names` as a second argument. By default
+ * returned object will be direct decedent of the given `object`'s prototype,
+ * but this can be overridden by passing third optional argument, that will be
+ * used as `prototype` instead.
+ * @param {Object} object
+ * Object to create cortex for.
+ * @param {String[]} [names]
+ * Optional array of public property names.
+ * @param {Object} [prototype]
+ * Optional argument that will be used as `prototype` of the returned object,
+ * if not provided `Object.getPrototypeOf(object)` is used instead.
+ */
+exports.Cortex = function Cortex(object, names, prototype) {
+ // Creating a cortex object from the given `prototype`, if one was not
+ // provided then `prototype` of a given `object` is used. This allows
+ // consumer to define expected behavior `instanceof`. In common case
+ // `prototype` argument can be omitted to preserve same behavior of
+ // `instanceof` as on original `object`.
+ var cortex = Object.create(prototype || Object.getPrototypeOf(object));
+ // Creating alias properties on the `cortex` object for all the own
+ // properties of the original `object` that are contained in `names` array.
+ // If `names` array is not provided then all the properties that don't
+ // start with `"_"` are aliased.
+ Object.getOwnPropertyNames(object).forEach(function (name) {
+ if ((!names && "_" !== name.charAt(0)) || (names && ~names.indexOf(name)))
+ defineAlias(object, cortex, name);
+ });
+ return cortex;
+}
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/errors.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/errors.js
new file mode 100644
index 0000000..b640d05
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/errors.js
@@ -0,0 +1,64 @@
+/* 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": "deprecated"
+};
+
+function logToConsole(e) {
+ console.exception(e);
+}
+
+var catchAndLog = exports.catchAndLog = function(callback,
+ defaultResponse,
+ logException) {
+ if (!logException)
+ logException = logToConsole;
+
+ return function() {
+ try {
+ return callback.apply(this, arguments);
+ } catch (e) {
+ logException(e);
+ return defaultResponse;
+ }
+ };
+};
+
+exports.catchAndLogProps = function catchAndLogProps(object,
+ props,
+ defaultResponse,
+ logException) {
+ if (typeof(props) == "string")
+ props = [props];
+ props.forEach(
+ function(property) {
+ object[property] = catchAndLog(object[property],
+ defaultResponse,
+ logException);
+ });
+};
+
+/**
+ * Catch and return an exception while calling the callback. If the callback
+ * doesn't throw, return the return value of the callback in a way that makes it
+ * possible to distinguish between a return value and an exception.
+ *
+ * This function is useful when you need to pass the result of a call across
+ * a process boundary (across which exceptions don't propagate). It probably
+ * doesn't need to be factored out into this module, since it is only used by
+ * a single caller, but putting it here works around bug 625560.
+ */
+exports.catchAndReturn = function(callback) {
+ return function() {
+ try {
+ return { returnValue: callback.apply(this, arguments) };
+ }
+ catch (exception) {
+ return { exception: exception };
+ }
+ };
+};
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/events.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/events.js
new file mode 100644
index 0000000..0c28a1a
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/events.js
@@ -0,0 +1,182 @@
+/* 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": "deprecated"
+};
+
+const ERROR_TYPE = 'error',
+ UNCAUGHT_ERROR = 'An error event was dispatched for which there was'
+ + ' no listener.',
+ BAD_LISTENER = 'The event listener must be a function.';
+/**
+ * This object is used to create an `EventEmitter` that, useful for composing
+ * objects that emit events. It implements an interface like `EventTarget` from
+ * DOM Level 2, which is implemented by Node objects in implementations that
+ * support the DOM Event Model.
+ * @see http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
+ * @see http://nodejs.org/api.html#EventEmitter
+ * @see http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/events/EventDispatcher.html
+ */
+const eventEmitter = {
+ /**
+ * Registers an event `listener` that is called every time events of
+ * specified `type` are emitted.
+ * @param {String} type
+ * The type of event.
+ * @param {Function} listener
+ * The listener function that processes the event.
+ * @example
+ * worker.on('message', function (data) {
+ * console.log('data received: ' + data)
+ * })
+ */
+ on: function on(type, listener) {
+ if ('function' !== typeof listener)
+ throw new Error(BAD_LISTENER);
+ let listeners = this._listeners(type);
+ if (0 > listeners.indexOf(listener))
+ listeners.push(listener);
+ // Use of `_public` is required by the legacy traits code that will go away
+ // once bug-637633 is fixed.
+ return this._public || this;
+ },
+
+ /**
+ * Registers an event `listener` that is called once the next time an event
+ * of the specified `type` is emitted.
+ * @param {String} type
+ * The type of the event.
+ * @param {Function} listener
+ * The listener function that processes the event.
+ */
+ once: function once(type, listener) {
+ this.on(type, function selfRemovableListener() {
+ this.removeListener(type, selfRemovableListener);
+ listener.apply(this, arguments);
+ });
+ },
+
+ /**
+ * Unregister `listener` for the specified event type.
+ * @param {String} type
+ * The type of event.
+ * @param {Function} listener
+ * The listener function that processes the event.
+ */
+ removeListener: function removeListener(type, listener) {
+ if ('function' !== typeof listener)
+ throw new Error(BAD_LISTENER);
+ let listeners = this._listeners(type),
+ index = listeners.indexOf(listener);
+ if (0 <= index)
+ listeners.splice(index, 1);
+ // Use of `_public` is required by the legacy traits code, that will go away
+ // once bug-637633 is fixed.
+ return this._public || this;
+ },
+
+ /**
+ * Hash of listeners on this EventEmitter.
+ */
+ _events: null,
+
+ /**
+ * Returns an array of listeners for the specified event `type`. This array
+ * can be manipulated, e.g. to remove listeners.
+ * @param {String} type
+ * The type of event.
+ */
+ _listeners: function listeners(type) {
+ let events = this._events || (this._events = {});
+ return events[type] || (events[type] = []);
+ },
+
+ /**
+ * Execute each of the listeners in order with the supplied arguments.
+ * Returns `true` if listener for this event was called, `false` if there are
+ * no listeners for this event `type`.
+ *
+ * All the exceptions that are thrown by listeners during the emit
+ * are caught and can be handled by listeners of 'error' event. Thrown
+ * exceptions are passed as an argument to an 'error' event listener.
+ * If no 'error' listener is registered exception will propagate to a
+ * caller of this method.
+ *
+ * **It's recommended to have a default 'error' listener in all the complete
+ * composition that in worst case may dump errors to the console.**
+ *
+ * @param {String} type
+ * The type of event.
+ * @params {Object|Number|String|Boolean}
+ * Arguments that will be passed to listeners.
+ * @returns {Boolean}
+ */
+ _emit: function _emit(type, event) {
+ let args = Array.slice(arguments);
+ // Use of `_public` is required by the legacy traits code that will go away
+ // once bug-637633 is fixed.
+ args.unshift(this._public || this);
+ return this._emitOnObject.apply(this, args);
+ },
+
+ /**
+ * A version of _emit that lets you specify the object on which listeners are
+ * called. This is a hack that is sometimes necessary when such an object
+ * (exports, for example) cannot be an EventEmitter for some reason, but other
+ * object(s) managing events for the object are EventEmitters. Once bug
+ * 577782 is fixed, this method shouldn't be necessary.
+ *
+ * @param {object} targetObj
+ * The object on which listeners will be called.
+ * @param {string} type
+ * The event name.
+ * @param {value} event
+ * The first argument to pass to listeners.
+ * @param {value} ...
+ * More arguments to pass to listeners.
+ * @returns {boolean}
+ */
+ _emitOnObject: function _emitOnObject(targetObj, type, event /* , ... */) {
+ let listeners = this._listeners(type).slice(0);
+ // If there is no 'error' event listener then throw.
+ if (type === ERROR_TYPE && !listeners.length)
+ console.exception(event);
+ if (!listeners.length)
+ return false;
+ let params = Array.slice(arguments, 2);
+ for each (let listener in listeners) {
+ try {
+ listener.apply(targetObj, params);
+ } catch(e) {
+ // Bug 726967: Ignore exceptions being throws while notifying the error
+ // in order to avoid infinite loops.
+ if (type !== ERROR_TYPE)
+ this._emit(ERROR_TYPE, e);
+ else
+ console.exception("Exception in error event listener " + e);
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Removes all the event listeners for the specified event `type`.
+ * @param {String} type
+ * The type of event.
+ */
+ _removeAllListeners: function _removeAllListeners(type) {
+ if (typeof type == "undefined") {
+ this._events = null;
+ return this;
+ }
+
+ this._listeners(type).splice(0);
+ return this;
+ }
+};
+exports.EventEmitter = require("./traits").Trait.compose(eventEmitter);
+exports.EventEmitterTrait = require('./light-traits').Trait(eventEmitter);
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/events/assembler.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/events/assembler.js
new file mode 100644
index 0000000..fcde1e3
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/events/assembler.js
@@ -0,0 +1,53 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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";
+
+const { Trait } = require("../light-traits");
+const { removeListener, on } = require("../../dom/events");
+
+/**
+ * Trait may be used for building objects / composing traits that wish to handle
+ * multiple dom events from multiple event targets in one place. Event targets
+ * can be added / removed by calling `observe / ignore` methods. Composer should
+ * provide array of event types it wishes to handle as property
+ * `supportedEventsTypes` and function for handling all those events as
+ * `handleEvent` property.
+ */
+exports.DOMEventAssembler = Trait({
+ /**
+ * Function that is supposed to handle all the supported events (that are
+ * present in the `supportedEventsTypes`) from all the observed
+ * `eventTargets`.
+ * @param {Event} event
+ * Event being dispatched.
+ */
+ handleEvent: Trait.required,
+ /**
+ * Array of supported event names.
+ * @type {String[]}
+ */
+ supportedEventsTypes: Trait.required,
+ /**
+ * Adds `eventTarget` to the list of observed `eventTarget`s. Listeners for
+ * supported events will be registered on the given `eventTarget`.
+ * @param {EventTarget} eventTarget
+ */
+ observe: function observe(eventTarget) {
+ this.supportedEventsTypes.forEach(function(eventType) {
+ on(eventTarget, eventType, this);
+ }, this);
+ },
+ /**
+ * Removes `eventTarget` from the list of observed `eventTarget`s. Listeners
+ * for all supported events will be unregistered from the given `eventTarget`.
+ * @param {EventTarget} eventTarget
+ */
+ ignore: function ignore(eventTarget) {
+ this.supportedEventsTypes.forEach(function(eventType) {
+ removeListener(eventTarget, eventType, this);
+ }, this);
+ }
+});
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/light-traits.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/light-traits.js
new file mode 100644
index 0000000..b18dccb
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/light-traits.js
@@ -0,0 +1,600 @@
+/* vim:ts=2:sts=2:sw=2:
+ * 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": "deprecated"
+};
+
+// `var` is being used in the module in order to make it reusable in
+// environments in which `let` is not yet supported.
+
+// Shortcut to `Object.prototype.hasOwnProperty.call`.
+// owns(object, name) would be the same as
+// Object.prototype.hasOwnProperty.call(object, name);
+var owns = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
+
+/**
+ * Whether or not given property descriptors are equivalent. They are
+ * equivalent either if both are marked as 'conflict' or 'required' property
+ * or if all the properties of descriptors are equal.
+ * @param {Object} actual
+ * @param {Object} expected
+ */
+function equivalentDescriptors(actual, expected) {
+ return (actual.conflict && expected.conflict) ||
+ (actual.required && expected.required) ||
+ equalDescriptors(actual, expected);
+}
+/**
+ * Whether or not given property descriptors define equal properties.
+ */
+function equalDescriptors(actual, expected) {
+ return actual.get === expected.get &&
+ actual.set === expected.set &&
+ actual.value === expected.value &&
+ !!actual.enumerable === !!expected.enumerable &&
+ !!actual.configurable === !!expected.configurable &&
+ !!actual.writable === !!expected.writable;
+}
+
+// Utilities that throwing exceptions for a properties that are marked
+// as "required" or "conflict" properties.
+function throwConflictPropertyError(name) {
+ throw new Error("Remaining conflicting property: `" + name + "`");
+}
+function throwRequiredPropertyError(name) {
+ throw new Error("Missing required property: `" + name + "`");
+}
+
+/**
+ * Generates custom **required** property descriptor. Descriptor contains
+ * non-standard property `required` that is equal to `true`.
+ * @param {String} name
+ * property name to generate descriptor for.
+ * @returns {Object}
+ * custom property descriptor
+ */
+function RequiredPropertyDescriptor(name) {
+ // Creating function by binding first argument to a property `name` on the
+ // `throwConflictPropertyError` function. Created function is used as a
+ // getter & setter of the created property descriptor. This way we ensure
+ // that we throw exception late (on property access) if object with
+ // `required` property was instantiated using built-in `Object.create`.
+ var accessor = throwRequiredPropertyError.bind(null, name);
+ return { get: accessor, set: accessor, required: true };
+}
+
+/**
+ * Generates custom **conflicting** property descriptor. Descriptor contains
+ * non-standard property `conflict` that is equal to `true`.
+ * @param {String} name
+ * property name to generate descriptor for.
+ * @returns {Object}
+ * custom property descriptor
+ */
+function ConflictPropertyDescriptor(name) {
+ // For details see `RequiredPropertyDescriptor` since idea is same.
+ var accessor = throwConflictPropertyError.bind(null, name);
+ return { get: accessor, set: accessor, conflict: true };
+}
+
+/**
+ * Tests if property is marked as `required` property.
+ */
+function isRequiredProperty(object, name) {
+ return !!object[name].required;
+}
+
+/**
+ * Tests if property is marked as `conflict` property.
+ */
+function isConflictProperty(object, name) {
+ return !!object[name].conflict;
+}
+
+/**
+ * Function tests whether or not method of the `source` object with a given
+ * `name` is inherited from `Object.prototype`.
+ */
+function isBuiltInMethod(name, source) {
+ var target = Object.prototype[name];
+
+ // If methods are equal then we know it's `true`.
+ return target == source ||
+ // If `source` object comes form a different sandbox `==` will evaluate
+ // to `false`, in that case we check if functions names and sources match.
+ (String(target) === String(source) && target.name === source.name);
+}
+
+/**
+ * Function overrides `toString` and `constructor` methods of a given `target`
+ * object with a same-named methods of a given `source` if methods of `target`
+ * object are inherited / copied from `Object.prototype`.
+ * @see create
+ */
+function overrideBuiltInMethods(target, source) {
+ if (isBuiltInMethod("toString", target.toString)) {
+ Object.defineProperty(target, "toString", {
+ value: source.toString,
+ configurable: true,
+ enumerable: false
+ });
+ }
+
+ if (isBuiltInMethod("constructor", target.constructor)) {
+ Object.defineProperty(target, "constructor", {
+ value: source.constructor,
+ configurable: true,
+ enumerable: false
+ });
+ }
+}
+
+/**
+ * Composes new trait with the same own properties as the original trait,
+ * except that all property names appearing in the first argument are replaced
+ * by "required" property descriptors.
+ * @param {String[]} keys
+ * Array of strings property names.
+ * @param {Object} trait
+ * A trait some properties of which should be excluded.
+ * @returns {Object}
+ * @example
+ * var newTrait = exclude(["name", ...], trait)
+ */
+function exclude(names, trait) {
+ var map = {};
+
+ Object.keys(trait).forEach(function(name) {
+
+ // If property is not excluded (the array of names does not contain it),
+ // or it is a "required" property, copy it to the property descriptor `map`
+ // that will be used for creation of resulting trait.
+ if (!~names.indexOf(name) || isRequiredProperty(trait, name))
+ map[name] = { value: trait[name], enumerable: true };
+
+ // For all the `names` in the exclude name array we create required
+ // property descriptors and copy them to the `map`.
+ else
+ map[name] = { value: RequiredPropertyDescriptor(name), enumerable: true };
+ });
+
+ return Object.create(Trait.prototype, map);
+}
+
+/**
+ * Composes new instance of `Trait` with a properties of a given `trait`,
+ * except that all properties whose name is an own property of `renames` will
+ * be renamed to `renames[name]` and a `"required"` property for name will be
+ * added instead.
+ *
+ * For each renamed property, a required property is generated. If
+ * the `renames` map two properties to the same name, a conflict is generated.
+ * If the `renames` map a property to an existing unrenamed property, a
+ * conflict is generated.
+ *
+ * @param {Object} renames
+ * An object whose own properties serve as a mapping from old names to new
+ * names.
+ * @param {Object} trait
+ * A new trait with renamed properties.
+ * @returns {Object}
+ * @example
+ *
+ * // Return trait with `bar` property equal to `trait.foo` and with
+ * // `foo` and `baz` "required" properties.
+ * var renamedTrait = rename({ foo: "bar", baz: null }), trait);
+ *
+ * // t1 and t2 are equivalent traits
+ * var t1 = rename({a: "b"}, t);
+ * var t2 = compose(exclude(["a"], t), { a: { required: true }, b: t[a] });
+ */
+function rename(renames, trait) {
+ var map = {};
+
+ // Loop over all the properties of the given `trait` and copy them to a
+ // property descriptor `map` that will be used for the creation of the
+ // resulting trait. Also, rename properties in the `map` as specified by
+ // `renames`.
+ Object.keys(trait).forEach(function(name) {
+ var alias;
+
+ // If the property is in the `renames` map, and it isn't a "required"
+ // property (which should never need to be aliased because "required"
+ // properties never conflict), then we must try to rename it.
+ if (owns(renames, name) && !isRequiredProperty(trait, name)) {
+ alias = renames[name];
+
+ // If the `map` already has the `alias`, and it isn't a "required"
+ // property, that means the `alias` conflicts with an existing name for a
+ // provided trait (that can happen if >=2 properties are aliased to the
+ // same name). In this case we mark it as a conflicting property.
+ // Otherwise, everything is fine, and we copy property with an `alias`
+ // name.
+ if (owns(map, alias) && !map[alias].value.required) {
+ map[alias] = {
+ value: ConflictPropertyDescriptor(alias),
+ enumerable: true
+ };
+ }
+ else {
+ map[alias] = {
+ value: trait[name],
+ enumerable: true
+ };
+ }
+
+ // Regardless of whether or not the rename was successful, we check to
+ // see if the original `name` exists in the map (such a property
+ // could exist if previous another property was aliased to this `name`).
+ // If it isn't, we mark it as "required", to make sure the caller
+ // provides another value for the old name, which methods of the trait
+ // might continue to reference.
+ if (!owns(map, name)) {
+ map[name] = {
+ value: RequiredPropertyDescriptor(name),
+ enumerable: true
+ };
+ }
+ }
+
+ // Otherwise, either the property isn't in the `renames` map (thus the
+ // caller is not trying to rename it) or it is a "required" property.
+ // Either way, we don't have to alias the property, we just have to copy it
+ // to the map.
+ else {
+ // The property isn't in the map yet, so we copy it over.
+ if (!owns(map, name)) {
+ map[name] = { value: trait[name], enumerable: true };
+ }
+
+ // The property is already in the map (that means another property was
+ // aliased with this `name`, which creates a conflict if the property is
+ // not marked as "required"), so we have to mark it as a "conflict"
+ // property.
+ else if (!isRequiredProperty(trait, name)) {
+ map[name] = {
+ value: ConflictPropertyDescriptor(name),
+ enumerable: true
+ };
+ }
+ }
+ });
+ return Object.create(Trait.prototype, map);
+}
+
+/**
+ * Composes new resolved trait, with all the same properties as the original
+ * `trait`, except that all properties whose name is an own property of
+ * `resolutions` will be renamed to `resolutions[name]`.
+ *
+ * If `resolutions[name]` is `null`, the value is mapped to a property
+ * descriptor that is marked as a "required" property.
+ */
+function resolve(resolutions, trait) {
+ var renames = {};
+ var exclusions = [];
+
+ // Go through each mapping in `resolutions` object and distribute it either
+ // to `renames` or `exclusions`.
+ Object.keys(resolutions).forEach(function(name) {
+
+ // If `resolutions[name]` is a truthy value then it's a mapping old -> new
+ // so we copy it to `renames` map.
+ if (resolutions[name])
+ renames[name] = resolutions[name];
+
+ // Otherwise it's not a mapping but an exclusion instead in which case we
+ // add it to the `exclusions` array.
+ else
+ exclusions.push(name);
+ });
+
+ // First `exclude` **then** `rename` and order is important since
+ // `exclude` and `rename` are not associative.
+ return rename(renames, exclude(exclusions, trait));
+}
+
+/**
+ * Create a Trait (a custom property descriptor map) that represents the given
+ * `object`'s own properties. Property descriptor map is a "custom", because it
+ * inherits from `Trait.prototype` and it's property descriptors may contain
+ * two attributes that is not part of the ES5 specification:
+ *
+ * - "required" (this property must be provided by another trait
+ * before an instance of this trait can be created)
+ * - "conflict" (when the trait is composed with another trait,
+ * a unique value for this property is provided by two or more traits)
+ *
+ * Data properties bound to the `Trait.required` singleton exported by
+ * this module will be marked as "required" properties.
+ *
+ * @param {Object} object
+ * Map of properties to compose trait from.
+ * @returns {Trait}
+ * Trait / Property descriptor map containing all the own properties of the
+ * given argument.
+ */
+function trait(object) {
+ var map;
+ var trait = object;
+
+ if (!(object instanceof Trait)) {
+ // If the passed `object` is not already an instance of `Trait`, we create
+ // a property descriptor `map` containing descriptors for the own properties
+ // of the given `object`. `map` is then used to create a `Trait` instance
+ // after all properties are mapped. Note that we can't create a trait and
+ // then just copy properties into it since that will fail for inherited
+ // read-only properties.
+ map = {};
+
+ // Each own property of the given `object` is mapped to a data property
+ // whose value is a property descriptor.
+ Object.keys(object).forEach(function (name) {
+
+ // If property of an `object` is equal to a `Trait.required`, it means
+ // that it was marked as "required" property, in which case we map it
+ // to "required" property.
+ if (Trait.required ==
+ Object.getOwnPropertyDescriptor(object, name).value) {
+ map[name] = {
+ value: RequiredPropertyDescriptor(name),
+ enumerable: true
+ };
+ }
+ // Otherwise property is mapped to it's property descriptor.
+ else {
+ map[name] = {
+ value: Object.getOwnPropertyDescriptor(object, name),
+ enumerable: true
+ };
+ }
+ });
+
+ trait = Object.create(Trait.prototype, map);
+ }
+ return trait;
+}
+
+/**
+ * Compose a property descriptor map that inherits from `Trait.prototype` and
+ * contains property descriptors for all the own properties of the passed
+ * traits.
+ *
+ * If two or more traits have own properties with the same name, the returned
+ * trait will contain a "conflict" property for that name. Composition is a
+ * commutative and associative operation, and the order of its arguments is
+ * irrelevant.
+ */
+function compose(trait1, trait2/*, ...*/) {
+ // Create a new property descriptor `map` to which all the own properties
+ // of the passed traits are copied. This map will be used to create a `Trait`
+ // instance that will be the result of this composition.
+ var map = {};
+
+ // Properties of each passed trait are copied to the composition.
+ Array.prototype.forEach.call(arguments, function(trait) {
+ // Copying each property of the given trait.
+ Object.keys(trait).forEach(function(name) {
+
+ // If `map` already owns a property with the `name` and it is not
+ // marked "required".
+ if (owns(map, name) && !map[name].value.required) {
+
+ // If the source trait's property with the `name` is marked as
+ // "required", we do nothing, as the requirement was already resolved
+ // by a property in the `map` (because it already contains a
+ // non-required property with that `name`). But if properties are just
+ // different, we have a name clash and we substitute it with a property
+ // that is marked "conflict".
+ if (!isRequiredProperty(trait, name) &&
+ !equivalentDescriptors(map[name].value, trait[name])
+ ) {
+ map[name] = {
+ value: ConflictPropertyDescriptor(name),
+ enumerable: true
+ };
+ }
+ }
+
+ // Otherwise, the `map` does not have an own property with the `name`, or
+ // it is marked "required". Either way, the trait's property is copied to
+ // the map (if the property of the `map` is marked "required", it is going
+ // to be resolved by the property that is being copied).
+ else {
+ map[name] = { value: trait[name], enumerable: true };
+ }
+ });
+ });
+
+ return Object.create(Trait.prototype, map);
+}
+
+/**
+ * `defineProperties` is like `Object.defineProperties`, except that it
+ * ensures that:
+ * - An exception is thrown if any property in a given `properties` map
+ * is marked as "required" property and same named property is not
+ * found in a given `prototype`.
+ * - An exception is thrown if any property in a given `properties` map
+ * is marked as "conflict" property.
+ * @param {Object} object
+ * Object to define properties on.
+ * @param {Object} properties
+ * Properties descriptor map.
+ * @returns {Object}
+ * `object` that was passed as a first argument.
+ */
+function defineProperties(object, properties) {
+
+ // Create a map into which we will copy each verified property from the given
+ // `properties` description map. We use it to verify that none of the
+ // provided properties is marked as a "conflict" property and that all
+ // "required" properties are resolved by a property of an `object`, so we
+ // can throw an exception before mutating object if that isn't the case.
+ var verifiedProperties = {};
+
+ // Coping each property from a given `properties` descriptor map to a
+ // verified map of property descriptors.
+ Object.keys(properties).forEach(function(name) {
+
+ // If property is marked as "required" property and we don't have a same
+ // named property in a given `object` we throw an exception. If `object`
+ // has same named property just skip this property since required property
+ // is was inherited and there for requirement was satisfied.
+ if (isRequiredProperty(properties, name)) {
+ if (!(name in object))
+ throwRequiredPropertyError(name);
+ }
+
+ // If property is marked as "conflict" property we throw an exception.
+ else if (isConflictProperty(properties, name)) {
+ throwConflictPropertyError(name);
+ }
+
+ // If property is not marked neither as "required" nor "conflict" property
+ // we copy it to verified properties map.
+ else {
+ verifiedProperties[name] = properties[name];
+ }
+ });
+
+ // If no exceptions were thrown yet, we know that our verified property
+ // descriptor map has no properties marked as "conflict" or "required",
+ // so we just delegate to the built-in `Object.defineProperties`.
+ return Object.defineProperties(object, verifiedProperties);
+}
+
+/**
+ * `create` is like `Object.create`, except that it ensures that:
+ * - An exception is thrown if any property in a given `properties` map
+ * is marked as "required" property and same named property is not
+ * found in a given `prototype`.
+ * - An exception is thrown if any property in a given `properties` map
+ * is marked as "conflict" property.
+ * @param {Object} prototype
+ * prototype of the composed object
+ * @param {Object} properties
+ * Properties descriptor map.
+ * @returns {Object}
+ * An object that inherits form a given `prototype` and implements all the
+ * properties defined by a given `properties` descriptor map.
+ */
+function create(prototype, properties) {
+
+ // Creating an instance of the given `prototype`.
+ var object = Object.create(prototype);
+
+ // Overriding `toString`, `constructor` methods if they are just inherited
+ // from `Object.prototype` with a same named methods of the `Trait.prototype`
+ // that will have more relevant behavior.
+ overrideBuiltInMethods(object, Trait.prototype);
+
+ // Trying to define given `properties` on the `object`. We use our custom
+ // `defineProperties` function instead of build-in `Object.defineProperties`
+ // that behaves exactly the same, except that it will throw if any
+ // property in the given `properties` descriptor is marked as "required" or
+ // "conflict" property.
+ return defineProperties(object, properties);
+}
+
+/**
+ * Composes new trait. If two or more traits have own properties with the
+ * same name, the new trait will contain a "conflict" property for that name.
+ * "compose" is a commutative and associative operation, and the order of its
+ * arguments is not significant.
+ *
+ * **Note:** Use `Trait.compose` instead of calling this function with more
+ * than one argument. The multiple-argument functionality is strictly for
+ * backward compatibility.
+ *
+ * @params {Object} trait
+ * Takes traits as an arguments
+ * @returns {Object}
+ * New trait containing the combined own properties of all the traits.
+ * @example
+ * var newTrait = compose(trait_1, trait_2, ..., trait_N)
+ */
+function Trait(trait1, trait2) {
+
+ // If the function was called with one argument, the argument should be
+ // an object whose properties are mapped to property descriptors on a new
+ // instance of Trait, so we delegate to the trait function.
+ // If the function was called with more than one argument, those arguments
+ // should be instances of Trait or plain property descriptor maps
+ // whose properties should be mixed into a new instance of Trait,
+ // so we delegate to the compose function.
+
+ return trait2 === undefined ? trait(trait1) : compose.apply(null, arguments);
+}
+
+Object.freeze(Object.defineProperties(Trait.prototype, {
+ toString: {
+ value: function toString() {
+ return "[object " + this.constructor.name + "]";
+ }
+ },
+
+ /**
+ * `create` is like `Object.create`, except that it ensures that:
+ * - An exception is thrown if this trait defines a property that is
+ * marked as required property and same named property is not
+ * found in a given `prototype`.
+ * - An exception is thrown if this trait contains property that is
+ * marked as "conflict" property.
+ * @param {Object}
+ * prototype of the compared object
+ * @returns {Object}
+ * An object with all of the properties described by the trait.
+ */
+ create: {
+ value: function createTrait(prototype) {
+ return create(undefined === prototype ? Object.prototype : prototype,
+ this);
+ },
+ enumerable: true
+ },
+
+ /**
+ * Composes a new resolved trait, with all the same properties as the original
+ * trait, except that all properties whose name is an own property of
+ * `resolutions` will be renamed to the value of `resolutions[name]`. If
+ * `resolutions[name]` is `null`, the property is marked as "required".
+ * @param {Object} resolutions
+ * An object whose own properties serve as a mapping from old names to new
+ * names, or to `null` if the property should be excluded.
+ * @returns {Object}
+ * New trait with the same own properties as the original trait but renamed.
+ */
+ resolve: {
+ value: function resolveTrait(resolutions) {
+ return resolve(resolutions, this);
+ },
+ enumerable: true
+ }
+}));
+
+/**
+ * @see compose
+ */
+Trait.compose = Object.freeze(compose);
+Object.freeze(compose.prototype);
+
+/**
+ * Constant singleton, representing placeholder for required properties.
+ * @type {Object}
+ */
+Trait.required = Object.freeze(Object.create(Object.prototype, {
+ toString: {
+ value: Object.freeze(function toString() {
+ return "<Trait.required>";
+ })
+ }
+}));
+Object.freeze(Trait.required.toString.prototype);
+
+exports.Trait = Object.freeze(Trait);
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/list.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/list.js
new file mode 100644
index 0000000..5de69e7
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/list.js
@@ -0,0 +1,118 @@
+/* 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": "experimental"
+};
+
+const { Trait } = require('../deprecated/traits');
+
+/**
+ * @see https://jetpack.mozillalabs.com/sdk/latest/docs/#module/api-utils/list
+ */
+const Iterable = Trait.compose({
+ /**
+ * Hash map of key-values to iterate over.
+ * Note: That this property can be a getter if you need dynamic behavior.
+ * @type {Object}
+ */
+ _keyValueMap: Trait.required,
+ /**
+ * Custom iterator providing `Iterable`s enumeration behavior.
+ * @param {Boolean} onKeys
+ */
+ __iterator__: function __iterator__(onKeys, onKeyValue) {
+ let map = this._keyValueMap;
+ for (let key in map)
+ yield onKeyValue ? [key, map[key]] : onKeys ? key : map[key];
+ }
+});
+exports.Iterable = Iterable;
+
+/**
+ * An ordered collection (also known as a sequence) disallowing duplicate
+ * elements. List is composed out of `Iterable` there for it provides custom
+ * enumeration behavior that is similar to array (enumerates only on the
+ * elements of the list). List is a base trait and is meant to be a part of
+ * composition, since all of it's API is private except length property.
+ */
+const List = Trait.resolve({ toString: null }).compose({
+ _keyValueMap: null,
+ /**
+ * List constructor can take any number of element to populate itself.
+ * @params {Object|String|Number} element
+ * @example
+ * List(1,2,3).length == 3 // true
+ */
+ constructor: function List() {
+ this._keyValueMap = [];
+ for (let i = 0, ii = arguments.length; i < ii; i++)
+ this._add(arguments[i]);
+ },
+ /**
+ * Number of elements in this list.
+ * @type {Number}
+ */
+ get length() this._keyValueMap.length,
+ /**
+ * Returns a string representing this list.
+ * @returns {String}
+ */
+ toString: function toString() 'List(' + this._keyValueMap + ')',
+ /**
+ * Returns `true` if this list contains the specified `element`.
+ * @param {Object|Number|String} element
+ * @returns {Boolean}
+ */
+ _has: function _has(element) 0 <= this._keyValueMap.indexOf(element),
+ /**
+ * Appends the specified `element` to the end of this list, if it doesn't
+ * contains it. Ignores the call if `element` is already contained.
+ * @param {Object|Number|String} element
+ */
+ _add: function _add(element) {
+ let list = this._keyValueMap,
+ index = list.indexOf(element);
+ if (0 > index)
+ list.push(this._public[list.length] = element);
+ },
+ /**
+ * Removes specified `element` from this list, if it contains it.
+ * Ignores the call if `element` is not contained.
+ * @param {Object|Number|String} element
+ */
+ _remove: function _remove(element) {
+ let list = this._keyValueMap,
+ index = list.indexOf(element);
+ if (0 <= index) {
+ delete this._public[list.length - 1];
+ list.splice(index, 1);
+ for (let length = list.length; index < length; index++)
+ this._public[index] = list[index];
+ }
+ },
+ /**
+ * Removes all of the elements from this list.
+ */
+ _clear: function _clear() {
+ for (let i = 0, ii = this._keyValueMap.length; i < ii; i ++)
+ delete this._public[i];
+ this._keyValueMap.splice(0);
+ },
+ /**
+ * Custom iterator providing `List`s enumeration behavior.
+ * We cant reuse `_iterator` that is defined by `Iterable` since it provides
+ * iteration in an arbitrary order.
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
+ * @param {Boolean} onKeys
+ */
+ __iterator__: function __iterator__(onKeys, onKeyValue) {
+ let array = this._keyValueMap.slice(0),
+ i = -1;
+ for each(let element in array)
+ yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
+ }
+});
+exports.List = List;
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/memory.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/memory.js
new file mode 100644
index 0000000..70bcffc
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/memory.js
@@ -0,0 +1,118 @@
+/* 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": "deprecated"
+};
+
+const {Cc,Ci,Cu,components} = require("chrome");
+var trackedObjects = {};
+
+var Compacter = {
+ INTERVAL: 5000,
+ notify: function(timer) {
+ var newTrackedObjects = {};
+ for (let name in trackedObjects) {
+ var oldBin = trackedObjects[name];
+ var newBin = [];
+ var strongRefs = [];
+ for (var i = 0; i < oldBin.length; i++) {
+ var strongRef = oldBin[i].weakref.get();
+ if (strongRef && strongRefs.indexOf(strongRef) == -1) {
+ strongRefs.push(strongRef);
+ newBin.push(oldBin[i]);
+ }
+ }
+ if (newBin.length)
+ newTrackedObjects[name] = newBin;
+ }
+ trackedObjects = newTrackedObjects;
+ }
+};
+
+var timer = Cc["@mozilla.org/timer;1"]
+ .createInstance(Ci.nsITimer);
+
+timer.initWithCallback(Compacter,
+ Compacter.INTERVAL,
+ Ci.nsITimer.TYPE_REPEATING_SLACK);
+
+var track = exports.track = function track(object, bin, stackFrameNumber) {
+ var frame = components.stack.caller;
+ var weakref = Cu.getWeakReference(object);
+ if (!bin && 'constructor' in object)
+ bin = object.constructor.name;
+ if (bin == "Object")
+ bin = frame.name;
+ if (!bin)
+ bin = "generic";
+ if (!(bin in trackedObjects))
+ trackedObjects[bin] = [];
+
+ if (stackFrameNumber > 0)
+ for (var i = 0; i < stackFrameNumber; i++)
+ frame = frame.caller;
+
+ trackedObjects[bin].push({weakref: weakref,
+ created: new Date(),
+ filename: frame.filename,
+ lineNo: frame.lineNumber,
+ bin: bin});
+};
+
+var getBins = exports.getBins = function getBins() {
+ var names = [];
+ for (let name in trackedObjects)
+ names.push(name);
+ return names;
+};
+
+var getObjects = exports.getObjects = function getObjects(bin) {
+ function getLiveObjectsInBin(bin, array) {
+ for (var i = 0; i < bin.length; i++) {
+ var object = bin[i].weakref.get();
+ if (object)
+ array.push(bin[i]);
+ }
+ }
+
+ var results = [];
+ if (bin) {
+ if (bin in trackedObjects)
+ getLiveObjectsInBin(trackedObjects[bin], results);
+ } else
+ for (let name in trackedObjects)
+ getLiveObjectsInBin(trackedObjects[name], results);
+ return results;
+};
+
+var gc = exports.gc = function gc() {
+ // Components.utils.forceGC() doesn't currently perform
+ // cycle collection, which means that e.g. DOM elements
+ // won't be collected by it. Fortunately, there are
+ // other ways...
+
+ var window = Cc["@mozilla.org/appshell/appShellService;1"]
+ .getService(Ci.nsIAppShellService)
+ .hiddenDOMWindow;
+ var test_utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ test_utils.garbageCollect();
+ Compacter.notify();
+
+ // Not sure why, but sometimes it appears that we don't get
+ // them all with just one CC, so let's do it again.
+ test_utils.garbageCollect();
+};
+
+require("../system/unload").when(
+ function() {
+ trackedObjects = {};
+ if (timer) {
+ timer.cancel();
+ timer = null;
+ }
+ });
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js
new file mode 100644
index 0000000..6a25109
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/observer-service.js
@@ -0,0 +1,134 @@
+/* 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": "deprecated"
+};
+
+const { Cc, Ci } = require("chrome");
+const { when: unload } = require("../system/unload");
+const { ns } = require("../core/namespace");
+const { on, off, emit, once } = require("../system/events");
+const { id } = require("../self");
+
+const subscribers = ns();
+const cache = [];
+
+/**
+ * Topics specifically available to Jetpack-generated extensions.
+ *
+ * Using these predefined consts instead of the platform strings is good:
+ * - allows us to scope topics specifically for Jetpacks
+ * - addons aren't dependent on strings nor behavior of core platform topics
+ * - the core platform topics are not clearly named
+ *
+ */
+exports.topics = {
+ /**
+ * A topic indicating that the application is in a state usable
+ * by add-ons.
+ */
+ APPLICATION_READY: id + "_APPLICATION_READY"
+};
+
+function Listener(callback, target) {
+ return function listener({ subject, data }) {
+ callback.call(target || callback, subject, data);
+ }
+}
+
+/**
+ * Register the given callback as an observer of the given topic.
+ *
+ * @param topic {String}
+ * the topic to observe
+ *
+ * @param callback {Object}
+ * the callback; an Object that implements nsIObserver or a Function
+ * that gets called when the notification occurs
+ *
+ * @param target {Object} [optional]
+ * the object to use as |this| when calling a Function callback
+ *
+ * @returns the observer
+ */
+function add(topic, callback, target) {
+ let listeners = subscribers(callback);
+ if (!(topic in listeners)) {
+ let listener = Listener(callback, target);
+ listeners[topic] = listener;
+
+ // Cache callback unless it's already cached.
+ if (!~cache.indexOf(callback))
+ cache.push(callback);
+
+ on(topic, listener);
+ }
+};
+exports.add = add;
+
+/**
+ * Unregister the given callback as an observer of the given topic.
+ *
+ * @param topic {String}
+ * the topic being observed
+ *
+ * @param callback {Object}
+ * the callback doing the observing
+ *
+ * @param target {Object} [optional]
+ * the object being used as |this| when calling a Function callback
+ */
+function remove(topic, callback, target) {
+ let listeners = subscribers(callback);
+ if (topic in listeners) {
+ let listener = listeners[topic];
+ delete listeners[topic];
+
+ // If no more observers are registered and callback is still in cache
+ // then remove it.
+ let index = cache.indexOf(callback);
+ if (~index && !Object.keys(listeners).length)
+ cache.splice(index, 1)
+
+ off(topic, listener);
+ }
+};
+exports.remove = remove;
+
+/**
+ * Notify observers about something.
+ *
+ * @param topic {String}
+ * the topic to notify observers about
+ *
+ * @param subject {Object} [optional]
+ * some information about the topic; can be any JS object or primitive
+ *
+ * @param data {String} [optional] [deprecated]
+ * some more information about the topic; deprecated as the subject
+ * is sufficient to pass all needed information to the JS observers
+ * that this module targets; if you have multiple values to pass to
+ * the observer, wrap them in an object and pass them via the subject
+ * parameter (i.e.: { foo: 1, bar: "some string", baz: myObject })
+ */
+function notify(topic, subject, data) {
+ emit(topic, {
+ subject: subject === undefined ? null : subject,
+ data: data === undefined ? null : data
+ });
+}
+exports.notify = notify;
+
+unload(function() {
+ // Make a copy of cache first, since cache will be changing as we
+ // iterate through it.
+ cache.slice().forEach(function(callback) {
+ Object.keys(subscribers(callback)).forEach(function(topic) {
+ remove(topic, callback);
+ });
+ });
+})
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/tab-browser.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/tab-browser.js
new file mode 100644
index 0000000..068471c
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/tab-browser.js
@@ -0,0 +1,731 @@
+/* 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': 'deprecated'
+};
+
+const {Cc,Ci,Cu} = require('chrome');
+var NetUtil = {};
+Cu.import('resource://gre/modules/NetUtil.jsm', NetUtil);
+NetUtil = NetUtil.NetUtil;
+const errors = require('./errors');
+const windowUtils = require('./window-utils');
+const apiUtils = require('./api-utils');
+const collection = require('../util/collection');
+const { getMostRecentBrowserWindow } = require('../window/utils');
+const { getSelectedTab } = require('../tabs/utils');
+
+// TODO: The hard-coding of app-specific info here isn't very nice;
+// ideally such app-specific info should be more decoupled, and the
+// module should be extensible, allowing for support of new apps at
+// runtime, perhaps by inspecting supported packages (e.g. via
+// dynamically-named modules or package-defined extension points).
+
+if (!require("../system/xul-app").is("Firefox")) {
+ throw new Error([
+ "The tab-browser module currently supports only Firefox. In the future ",
+ "it will support other applications. Please see ",
+ "https://bugzilla.mozilla.org/show_bug.cgi?id=560716 for more information."
+ ].join(""));
+}
+
+function onBrowserLoad(callback, event) {
+ if (event.target && event.target.defaultView == this) {
+ this.removeEventListener("load", onBrowserLoad, true);
+ try {
+ require("../timers").setTimeout(function () {
+ callback(event);
+ }, 10);
+ } catch (e) { console.exception(e); }
+ }
+}
+
+// Utility function to open a new browser window.
+function openBrowserWindow(callback, url) {
+ let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Ci.nsIWindowWatcher);
+ let urlString = Cc["@mozilla.org/supports-string;1"].
+ createInstance(Ci.nsISupportsString);
+ urlString.data = url;
+ let window = ww.openWindow(null, "chrome://browser/content/browser.xul",
+ "_blank", "chrome,all,dialog=no", urlString);
+ if (callback)
+ window.addEventListener("load", onBrowserLoad.bind(window, callback), true);
+
+ return window;
+}
+
+// Open a URL in a new tab
+exports.addTab = function addTab(url, options) {
+ if (!options)
+ options = {};
+ options.url = url;
+
+ options = apiUtils.validateOptions(options, {
+ // TODO: take URL object instead of string (bug 564524)
+ url: {
+ is: ["string"],
+ ok: function (v) !!v,
+ msg: "The url parameter must have be a non-empty string."
+ },
+ inNewWindow: {
+ is: ["undefined", "null", "boolean"]
+ },
+ inBackground: {
+ is: ["undefined", "null", "boolean"]
+ },
+ onLoad: {
+ is: ["undefined", "null", "function"]
+ },
+ isPinned: {
+ is: ["undefined", "boolean"]
+ }
+ });
+
+ var win = getMostRecentBrowserWindow();
+ if (!win || options.inNewWindow) {
+ openBrowserWindow(function(e) {
+ if(options.isPinned) {
+ //get the active tab in the recently created window
+ let mainWindow = e.target.defaultView;
+ mainWindow.gBrowser.pinTab(getSelectedTab(mainWindow));
+ }
+ require("./errors").catchAndLog(function(e) options.onLoad(e))(e);
+ }, options.url);
+ }
+ else {
+ let tab = win.gBrowser.addTab(options.url);
+ if (!options.inBackground)
+ win.gBrowser.selectedTab = tab;
+ if (options.onLoad) {
+ let tabBrowser = win.gBrowser.getBrowserForTab(tab);
+ tabBrowser.addEventListener("load", function onLoad(e) {
+ if (e.target.defaultView.content.location == "about:blank")
+ return;
+ // remove event handler from addTab - don't want notified
+ // for subsequent loads in same tab.
+ tabBrowser.removeEventListener("load", onLoad, true);
+ require("./errors").catchAndLog(function(e) options.onLoad(e))(e);
+ }, true);
+ }
+ }
+}
+
+// Iterate over a window's tabbrowsers
+function tabBrowserIterator(window) {
+ var browsers = window.document.querySelectorAll("tabbrowser");
+ for (var i = 0; i < browsers.length; i++)
+ yield browsers[i];
+}
+
+// Iterate over a tabbrowser's tabs
+function tabIterator(tabbrowser) {
+ var tabs = tabbrowser.tabContainer;
+ for (var i = 0; i < tabs.children.length; i++) {
+ yield tabs.children[i];
+ }
+}
+
+// Tracker for all tabbrowsers across all windows,
+// or a single tabbrowser if the window is given.
+function Tracker(delegate, window) {
+ this._delegate = delegate;
+ this._browsers = [];
+ this._window = window;
+ this._windowTracker = windowUtils.WindowTracker(this);
+
+ require("../system/unload").ensure(this);
+}
+Tracker.prototype = {
+ __iterator__: function __iterator__() {
+ for (var i = 0; i < this._browsers.length; i++)
+ yield this._browsers[i];
+ },
+ get: function get(index) {
+ return this._browsers[index];
+ },
+ onTrack: function onTrack(window) {
+ if (this._window && window != this._window)
+ return;
+
+ for (let browser in tabBrowserIterator(window))
+ this._browsers.push(browser);
+ if (this._delegate)
+ for (let browser in tabBrowserIterator(window))
+ this._delegate.onTrack(browser);
+ },
+ onUntrack: function onUntrack(window) {
+ if (this._window && window != this._window)
+ return;
+
+ for (let browser in tabBrowserIterator(window)) {
+ let index = this._browsers.indexOf(browser);
+ if (index != -1)
+ this._browsers.splice(index, 1);
+ else
+ console.error("internal error: browser tab not found");
+ }
+ if (this._delegate)
+ for (let browser in tabBrowserIterator(window))
+ this._delegate.onUntrack(browser);
+ },
+ get length() {
+ return this._browsers.length;
+ },
+ unload: function unload() {
+ this._windowTracker.unload();
+ }
+};
+exports.Tracker = apiUtils.publicConstructor(Tracker);
+
+// Tracker for all tabs across all windows,
+// or a single window if it's given.
+function TabTracker(delegate, window) {
+ this._delegate = delegate;
+ this._tabs = [];
+ this._tracker = new Tracker(this, window);
+ require("../system/unload").ensure(this);
+}
+TabTracker.prototype = {
+ _TAB_EVENTS: ["TabOpen", "TabClose"],
+ _safeTrackTab: function safeTrackTab(tab) {
+ this._tabs.push(tab);
+ try {
+ this._delegate.onTrack(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeUntrackTab: function safeUntrackTab(tab) {
+ var index = this._tabs.indexOf(tab);
+ if (index == -1)
+ console.error("internal error: tab not found");
+ this._tabs.splice(index, 1);
+ try {
+ this._delegate.onUntrack(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ handleEvent: function handleEvent(event) {
+ switch (event.type) {
+ case "TabOpen":
+ this._safeTrackTab(event.target);
+ break;
+ case "TabClose":
+ this._safeUntrackTab(event.target);
+ break;
+ default:
+ throw new Error("internal error: unknown event type: " +
+ event.type);
+ }
+ },
+ onTrack: function onTrack(tabbrowser) {
+ for (let tab in tabIterator(tabbrowser))
+ this._safeTrackTab(tab);
+ var self = this;
+ this._TAB_EVENTS.forEach(
+ function(eventName) {
+ tabbrowser.tabContainer.addEventListener(eventName, self, true);
+ });
+ },
+ onUntrack: function onUntrack(tabbrowser) {
+ for (let tab in tabIterator(tabbrowser))
+ this._safeUntrackTab(tab);
+ var self = this;
+ this._TAB_EVENTS.forEach(
+ function(eventName) {
+ tabbrowser.tabContainer.removeEventListener(eventName, self, true);
+ });
+ },
+ unload: function unload() {
+ this._tracker.unload();
+ }
+};
+exports.TabTracker = apiUtils.publicConstructor(TabTracker);
+
+exports.whenContentLoaded = function whenContentLoaded(callback) {
+ var cb = require("./errors").catchAndLog(function eventHandler(event) {
+ if (event.target && event.target.defaultView)
+ callback(event.target.defaultView);
+ });
+
+ var tracker = new Tracker({
+ onTrack: function(tabBrowser) {
+ tabBrowser.addEventListener("DOMContentLoaded", cb, false);
+ },
+ onUntrack: function(tabBrowser) {
+ tabBrowser.removeEventListener("DOMContentLoaded", cb, false);
+ }
+ });
+
+ return tracker;
+};
+
+Object.defineProperty(exports, 'activeTab', {
+ get: function() {
+ return getSelectedTab(getMostRecentBrowserWindow());
+ }
+});
+
+/******************* TabModule *********************/
+
+// Supported tab events
+const events = [
+ "onActivate",
+ "onDeactivate",
+ "onOpen",
+ "onClose",
+ "onReady",
+ "onLoad",
+ "onPaint"
+];
+exports.tabEvents = events;
+
+/**
+ * TabModule
+ *
+ * Constructor for a module that implements the tabs API
+ */
+let TabModule = exports.TabModule = function TabModule(window) {
+ let self = this;
+ /**
+ * Tab
+ *
+ * Safe object representing a tab.
+ */
+ let tabConstructor = apiUtils.publicConstructor(function(element) {
+ if (!element)
+ throw new Error("no tab element.");
+ let win = element.ownerDocument.defaultView;
+ if (!win)
+ throw new Error("element has no window.");
+ if (window && win != window)
+ throw new Error("module's window and element's window don't match.");
+ let browser = win.gBrowser.getBrowserForTab(element);
+
+ this.__defineGetter__("title", function() browser.contentDocument.title);
+ this.__defineGetter__("location", function() browser.contentDocument.location);
+ this.__defineSetter__("location", function(val) browser.contentDocument.location = val);
+ this.__defineGetter__("contentWindow", function() browser.contentWindow);
+ this.__defineGetter__("contentDocument", function() browser.contentDocument);
+ this.__defineGetter__("favicon", function() {
+ let pageURI = NetUtil.newURI(browser.contentDocument.location);
+ let fs = Cc["@mozilla.org/browser/favicon-service;1"].
+ getService(Ci.nsIFaviconService);
+ let faviconURL;
+ try {
+ let faviconURI = fs.getFaviconForPage(pageURI);
+ faviconURL = fs.getFaviconDataAsDataURL(faviconURI);
+ } catch(ex) {
+ let data = getChromeURLContents("chrome://mozapps/skin/places/defaultFavicon.png");
+ let encoded = browser.contentWindow.btoa(data);
+ faviconURL = "data:image/png;base64," + encoded;
+ }
+ return faviconURL;
+ });
+ this.__defineGetter__("style", function() null); // TODO
+ this.__defineGetter__("index", function() win.gBrowser.getBrowserIndexForDocument(browser.contentDocument));
+ this.__defineGetter__("thumbnail", function() getThumbnailCanvasForTab(element, browser.contentWindow));
+
+ this.close = function() win.gBrowser.removeTab(element);
+ this.move = function(index) {
+ win.gBrowser.moveTabTo(element, index);
+ };
+
+ this.__defineGetter__("isPinned", function() element.pinned);
+ this.pin = function() win.gBrowser.pinTab(element);
+ this.unpin = function() win.gBrowser.unpinTab(element);
+
+ // Set up the event handlers
+ let tab = this;
+ events.filter(function(e) e != "onOpen").forEach(function(e) {
+ // create a collection for each event
+ collection.addCollectionProperty(tab, e);
+ // make tabs setter for each event, for adding via property assignment
+ tab.__defineSetter__(e, function(val) tab[e].add(val));
+ });
+
+ // listen for events, filtered on this tab
+ eventsTabDelegate.addTabDelegate(this);
+ });
+
+ /**
+ * tabs.activeTab
+ */
+ this.__defineGetter__("activeTab", function() {
+ try {
+ return window ? tabConstructor(getSelectedTab(window))
+ : tabConstructor(exports.activeTab);
+ }
+ catch (e) { }
+ return null;
+ });
+ this.__defineSetter__("activeTab", function(tab) {
+ let [tabElement, win] = getElementAndWindowForTab(tab, window);
+ if (tabElement) {
+ // set as active tab
+ win.gBrowser.selectedTab = tabElement;
+ // focus the window
+ win.focus();
+ }
+ });
+
+ this.open = function TM_open(options) {
+ open(options, tabConstructor, window);
+ }
+
+ // Set up the event handlers
+ events.forEach(function(eventHandler) {
+ // create a collection for each event
+ collection.addCollectionProperty(self, eventHandler);
+ // make tabs setter for each event, for adding via property assignment
+ self.__defineSetter__(eventHandler, function(val) self[eventHandler].add(val));
+ });
+
+ // Tracker that listens for tab events, and proxies
+ // them to registered event listeners.
+ let eventsTabDelegate = {
+ selectedTab: null,
+ tabs: [],
+ addTabDelegate: function TETT_addTabDelegate(tabObj) {
+ this.tabs.push(tabObj);
+ },
+ pushTabEvent: function TETT_pushTabEvent(event, tab) {
+ for (let callback in self[event]) {
+ require("./errors").catchAndLog(function(tab) {
+ callback(new tabConstructor(tab));
+ })(tab);
+ }
+
+ if (event != "onOpen") {
+ this.tabs.forEach(function(tabObj) {
+ if (tabObj[event].length) {
+ let [tabEl,] = getElementAndWindowForTab(tabObj, window);
+ if (tabEl == tab) {
+ for (let callback in tabObj[event])
+ require("./errors").catchAndLog(function() callback())();
+ }
+ }
+ // if being closed, remove the tab object from the cache
+ // of tabs to notify about events.
+ if (event == "onClose")
+ this.tabs.splice(this.tabs.indexOf(tabObj), 1);
+ }, this);
+ }
+ },
+ unload: function() {
+ this.selectedTab = null;
+ this.tabs.splice(0);
+ }
+ };
+ require("../system/unload").ensure(eventsTabDelegate);
+
+ let eventsTabTracker = new ModuleTabTracker({
+ onTrack: function TETT_onTrack(tab) {
+ eventsTabDelegate.pushTabEvent("onOpen", tab);
+ },
+ onUntrack: function TETT_onUntrack(tab) {
+ eventsTabDelegate.pushTabEvent("onClose", tab);
+ },
+ onSelect: function TETT_onSelect(tab) {
+ if (eventsTabDelegate.selectedTab)
+ eventsTabDelegate.pushTabEvent("onDeactivate", tab);
+
+ eventsTabDelegate.selectedTab = new tabConstructor(tab);
+
+ eventsTabDelegate.pushTabEvent("onActivate", tab);
+ },
+ onReady: function TETT_onReady(tab) {
+ eventsTabDelegate.pushTabEvent("onReady", tab);
+ },
+ onLoad: function TETT_onLoad(tab) {
+ eventsTabDelegate.pushTabEvent("onLoad", tab);
+ },
+ onPaint: function TETT_onPaint(tab) {
+ eventsTabDelegate.pushTabEvent("onPaint", tab);
+ }
+ }, window);
+ require("../system/unload").ensure(eventsTabTracker);
+
+ // Iterator for all tabs
+ this.__iterator__ = function tabsIterator() {
+ for (let i = 0; i < eventsTabTracker._tabs.length; i++)
+ yield tabConstructor(eventsTabTracker._tabs[i]);
+ }
+
+ this.__defineGetter__("length", function() eventsTabTracker._tabs.length);
+
+ // Cleanup when unloaded
+ this.unload = function TM_unload() {
+ // Unregister tabs event listeners
+ events.forEach(function(e) self[e] = []);
+ }
+ require("../system/unload").ensure(this);
+
+} // End of TabModule constructor
+
+/**
+ * tabs.open - open a URL in a new tab
+ */
+function open(options, tabConstructor, window) {
+ if (typeof options === "string")
+ options = { url: options };
+
+ options = apiUtils.validateOptions(options, {
+ url: {
+ is: ["string"]
+ },
+ inNewWindow: {
+ is: ["undefined", "boolean"]
+ },
+ inBackground: {
+ is: ["undefined", "boolean"]
+ },
+ isPinned: {
+ is: ["undefined", "boolean"]
+ },
+ onOpen: {
+ is: ["undefined", "function"]
+ }
+ });
+
+ if (window)
+ options.inNewWindow = false;
+
+ let win = window || require("./window-utils").activeBrowserWindow;
+
+ if (!win || options.inNewWindow)
+ openURLInNewWindow(options, tabConstructor);
+ else
+ openURLInNewTab(options, win, tabConstructor);
+}
+
+function openURLInNewWindow(options, tabConstructor) {
+ let addTabOptions = {
+ inNewWindow: true
+ };
+ if (options.onOpen) {
+ addTabOptions.onLoad = function(e) {
+ let win = e.target.defaultView;
+ let tabEl = win.gBrowser.tabContainer.childNodes[0];
+ let tabBrowser = win.gBrowser.getBrowserForTab(tabEl);
+ tabBrowser.addEventListener("load", function onLoad(e) {
+ tabBrowser.removeEventListener("load", onLoad, true);
+ let tab = tabConstructor(tabEl);
+ require("./errors").catchAndLog(function(e) options.onOpen(e))(tab);
+ }, true);
+ };
+ }
+ if (options.isPinned) {
+ addTabOptions.isPinned = true;
+ }
+ exports.addTab(options.url.toString(), addTabOptions);
+}
+
+function openURLInNewTab(options, window, tabConstructor) {
+ window.focus();
+ let tabEl = window.gBrowser.addTab(options.url.toString());
+ if (!options.inBackground)
+ window.gBrowser.selectedTab = tabEl;
+ if (options.isPinned)
+ window.gBrowser.pinTab(tabEl);
+ if (options.onOpen) {
+ let tabBrowser = window.gBrowser.getBrowserForTab(tabEl);
+ tabBrowser.addEventListener("load", function onLoad(e) {
+ // remove event handler from addTab - don't want to be notified
+ // for subsequent loads in same tab.
+ tabBrowser.removeEventListener("load", onLoad, true);
+ let tab = tabConstructor(tabEl);
+ require("../timers").setTimeout(function() {
+ require("./errors").catchAndLog(function(tab) options.onOpen(tab))(tab);
+ }, 10);
+ }, true);
+ }
+}
+
+function getElementAndWindowForTab(tabObj, window) {
+ // iterate over open windows, or use single window if provided
+ let windowIterator = window ? function() { yield window; }
+ : require("./window-utils").windowIterator;
+ for (let win in windowIterator()) {
+ if (win.gBrowser) {
+ // find the tab element at tab.index
+ let index = win.gBrowser.getBrowserIndexForDocument(tabObj.contentDocument);
+ if (index > -1)
+ return [win.gBrowser.tabContainer.getItemAtIndex(index), win];
+ }
+ }
+ return [null, null];
+}
+
+// Tracker for all tabs across all windows
+// This is tab-browser.TabTracker, but with
+// support for additional events added.
+function ModuleTabTracker(delegate, window) {
+ this._delegate = delegate;
+ this._tabs = [];
+ this._tracker = new Tracker(this, window);
+ require("../system/unload").ensure(this);
+}
+ModuleTabTracker.prototype = {
+ _TAB_EVENTS: ["TabOpen", "TabClose", "TabSelect", "DOMContentLoaded",
+ "load", "MozAfterPaint"],
+ _safeTrackTab: function safeTrackTab(tab) {
+ tab.addEventListener("load", this, false);
+ tab.linkedBrowser.addEventListener("MozAfterPaint", this, false);
+ this._tabs.push(tab);
+ try {
+ this._delegate.onTrack(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeUntrackTab: function safeUntrackTab(tab) {
+ tab.removeEventListener("load", this, false);
+ tab.linkedBrowser.removeEventListener("MozAfterPaint", this, false);
+ var index = this._tabs.indexOf(tab);
+ if (index == -1)
+ throw new Error("internal error: tab not found");
+ this._tabs.splice(index, 1);
+ try {
+ this._delegate.onUntrack(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeSelectTab: function safeSelectTab(tab) {
+ var index = this._tabs.indexOf(tab);
+ if (index == -1)
+ console.error("internal error: tab not found");
+ try {
+ if (this._delegate.onSelect)
+ this._delegate.onSelect(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeDOMContentLoaded: function safeDOMContentLoaded(event) {
+ let tabBrowser = event.currentTarget;
+ let tabBrowserIndex = tabBrowser.getBrowserIndexForDocument(event.target);
+ // TODO: I'm seeing this when loading data url images
+ if (tabBrowserIndex == -1)
+ return;
+ let tab = tabBrowser.tabContainer.getItemAtIndex(tabBrowserIndex);
+ let index = this._tabs.indexOf(tab);
+ if (index == -1)
+ console.error("internal error: tab not found");
+ try {
+ if (this._delegate.onReady)
+ this._delegate.onReady(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeLoad: function safeLoad(event) {
+ let tab = event.target;
+ let index = this._tabs.indexOf(tab);
+ if (index == -1)
+ console.error("internal error: tab not found");
+ try {
+ if (this._delegate.onLoad)
+ this._delegate.onLoad(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ _safeMozAfterPaint: function safeMozAfterPaint(event) {
+ let win = event.currentTarget.ownerDocument.defaultView;
+ let tabIndex = win.gBrowser.getBrowserIndexForDocument(event.target.document);
+ if (tabIndex == -1)
+ return;
+ let tab = win.gBrowser.tabContainer.getItemAtIndex(tabIndex);
+ let index = this._tabs.indexOf(tab);
+ if (index == -1)
+ console.error("internal error: tab not found");
+ try {
+ if (this._delegate.onPaint)
+ this._delegate.onPaint(tab);
+ } catch (e) {
+ console.exception(e);
+ }
+ },
+ handleEvent: function handleEvent(event) {
+ switch (event.type) {
+ case "TabOpen":
+ this._safeTrackTab(event.target);
+ break;
+ case "TabClose":
+ this._safeUntrackTab(event.target);
+ break;
+ case "TabSelect":
+ this._safeSelectTab(event.target);
+ break;
+ case "DOMContentLoaded":
+ this._safeDOMContentLoaded(event);
+ break;
+ case "load":
+ this._safeLoad(event);
+ break;
+ case "MozAfterPaint":
+ this._safeMozAfterPaint(event);
+ break;
+ default:
+ throw new Error("internal error: unknown event type: " +
+ event.type);
+ }
+ },
+ onTrack: function onTrack(tabbrowser) {
+ for (let tab in tabIterator(tabbrowser))
+ this._safeTrackTab(tab);
+ tabbrowser.tabContainer.addEventListener("TabOpen", this, false);
+ tabbrowser.tabContainer.addEventListener("TabClose", this, false);
+ tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
+ tabbrowser.ownerDocument.defaultView.gBrowser.addEventListener("DOMContentLoaded", this, false);
+ },
+ onUntrack: function onUntrack(tabbrowser) {
+ for (let tab in tabIterator(tabbrowser))
+ this._safeUntrackTab(tab);
+ tabbrowser.tabContainer.removeEventListener("TabOpen", this, false);
+ tabbrowser.tabContainer.removeEventListener("TabClose", this, false);
+ tabbrowser.tabContainer.removeEventListener("TabSelect", this, false);
+ tabbrowser.ownerDocument.defaultView.gBrowser.removeEventListener("DOMContentLoaded", this, false);
+ },
+ unload: function unload() {
+ this._tracker.unload();
+ }
+};
+
+// Utility to get a thumbnail canvas from a tab object
+function getThumbnailCanvasForTab(tabEl, window) {
+ var thumbnail = window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+ thumbnail.mozOpaque = true;
+ window = tabEl.linkedBrowser.contentWindow;
+ thumbnail.width = Math.ceil(window.screen.availWidth / 5.75);
+ var aspectRatio = 0.5625; // 16:9
+ thumbnail.height = Math.round(thumbnail.width * aspectRatio);
+ var ctx = thumbnail.getContext("2d");
+ var snippetWidth = window.innerWidth * .6;
+ var scale = thumbnail.width / snippetWidth;
+ ctx.scale(scale, scale);
+ ctx.drawWindow(window, window.scrollX, window.scrollY, snippetWidth, snippetWidth * aspectRatio, "rgb(255,255,255)");
+ return thumbnail;
+}
+
+// Utility to return the contents of the target of a chrome URL
+function getChromeURLContents(chromeURL) {
+ let io = Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+ let channel = io.newChannel(chromeURL, null, null);
+ let input = channel.open();
+ let stream = Cc["@mozilla.org/binaryinputstream;1"].
+ createInstance(Ci.nsIBinaryInputStream);
+ stream.setInputStream(input);
+ let str = stream.readBytes(input.available());
+ stream.close();
+ input.close();
+ return str;
+}
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/traits.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/traits.js
new file mode 100644
index 0000000..30ae342
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/traits.js
@@ -0,0 +1,187 @@
+/* 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": "deprecated"
+};
+
+const {
+ compose: _compose,
+ override: _override,
+ resolve: _resolve,
+ trait: _trait,
+ //create: _create,
+ required,
+} = require('./traits/core');
+
+const defineProperties = Object.defineProperties,
+ freeze = Object.freeze,
+ create = Object.create;
+
+/**
+ * Work around bug 608959 by defining the _create function here instead of
+ * importing it from traits/core. For docs on this function, see the create
+ * function in that module.
+ *
+ * FIXME: remove this workaround in favor of importing the function once that
+ * bug has been fixed.
+ */
+function _create(proto, trait) {
+ let properties = {},
+ keys = Object.getOwnPropertyNames(trait);
+ for each(let key in keys) {
+ let descriptor = trait[key];
+ if (descriptor.required &&
+ !Object.prototype.hasOwnProperty.call(proto, key))
+ throw new Error('Missing required property: ' + key);
+ else if (descriptor.conflict)
+ throw new Error('Remaining conflicting property: ' + key);
+ else
+ properties[key] = descriptor;
+ }
+ return Object.create(proto, properties);
+}
+
+/**
+ * Placeholder for `Trait.prototype`
+ */
+let TraitProto = Object.prototype;
+
+function Get(key) this[key]
+function Set(key, value) this[key] = value
+
+/**
+ * Creates anonymous trait descriptor from the passed argument, unless argument
+ * is a trait constructor. In later case trait's already existing properties
+ * descriptor is returned.
+ * This is module's internal function and is used as a gateway to a trait's
+ * internal properties descriptor.
+ * @param {Function} $
+ * Composed trait's constructor.
+ * @returns {Object}
+ * Private trait property of the composition.
+ */
+function TraitDescriptor(object)
+ (
+ 'function' == typeof object &&
+ (object.prototype == TraitProto || object.prototype instanceof Trait)
+ ) ? object._trait(TraitDescriptor) : _trait(object)
+
+function Public(instance, trait) {
+ let result = {},
+ keys = Object.getOwnPropertyNames(trait);
+ for each (let key in keys) {
+ if ('_' === key.charAt(0) && '__iterator__' !== key )
+ continue;
+ let property = trait[key],
+ descriptor = {
+ configurable: property.configurable,
+ enumerable: property.enumerable
+ };
+ if (property.get)
+ descriptor.get = property.get.bind(instance);
+ if (property.set)
+ descriptor.set = property.set.bind(instance);
+ if ('value' in property) {
+ let value = property.value;
+ if ('function' === typeof value) {
+ descriptor.value = property.value.bind(instance);
+ descriptor.writable = property.writable;
+ } else {
+ descriptor.get = Get.bind(instance, key);
+ descriptor.set = Set.bind(instance, key);
+ }
+ }
+ result[key] = descriptor;
+ }
+ return result;
+}
+
+/**
+ * This is private function that composes new trait with privates.
+ */
+function Composition(trait) {
+ function Trait() {
+ let self = _create({}, trait);
+ self._public = create(Trait.prototype, Public(self, trait));
+ delete self._public.constructor;
+ if (Object === self.constructor)
+ self.constructor = Trait;
+ else
+ return self.constructor.apply(self, arguments) || self._public;
+ return self._public;
+ }
+ defineProperties(Trait, {
+ prototype: { value: freeze(create(TraitProto, {
+ constructor: { value: constructor, writable: true }
+ }))}, // writable is `true` to avoid getters in custom ES5
+ displayName: { value: (trait.constructor || constructor).name },
+ compose: { value: compose, enumerable: true },
+ override: { value: override, enumerable: true },
+ resolve: { value: resolve, enumerable: true },
+ required: { value: required, enumerable: true },
+ _trait: { value: function _trait(caller)
+ caller === TraitDescriptor ? trait : undefined
+ }
+ });
+ return freeze(Trait);
+}
+
+/**
+ * Composes new trait out of itself and traits / property maps passed as an
+ * arguments. If two or more traits / property maps have properties with the
+ * same name, the new trait will contain a "conflict" property for that name.
+ * This is a commutative and associative operation, and the order of its
+ * arguments is not significant.
+ * @params {Object|Function}
+ * List of Traits or property maps to create traits from.
+ * @returns {Function}
+ * New trait containing the combined properties of all the traits.
+ */
+function compose() {
+ let traits = Array.slice(arguments, 0);
+ traits.push(this);
+ return Composition(_compose.apply(null, traits.map(TraitDescriptor)));
+}
+
+/**
+ * Composes a new trait with all of the combined properties of `this` and the
+ * argument traits. In contrast to `compose`, `override` immediately resolves
+ * all conflicts resulting from this composition by overriding the properties of
+ * later traits. Trait priority is from left to right. I.e. the properties of
+ * the leftmost trait are never overridden.
+ * @params {Object} trait
+ * @returns {Object}
+ */
+function override() {
+ let traits = Array.slice(arguments, 0);
+ traits.push(this);
+ return Composition(_override.apply(null, traits.map(TraitDescriptor)));
+}
+
+/**
+ * Composes new resolved trait, with all the same properties as this
+ * trait, except that all properties whose name is an own property of
+ * `resolutions` will be renamed to `resolutions[name]`. If it is
+ * `resolutions[name]` is `null` value is changed into a required property
+ * descriptor.
+ */
+function resolve(resolutions)
+ Composition(_resolve(resolutions, TraitDescriptor(this)))
+
+/**
+ * Base Trait, that all the traits are composed of.
+ */
+const Trait = Composition({
+ /**
+ * Internal property holding public API of this instance.
+ */
+ _public: { value: null, configurable: true, writable: true },
+ toString: { value: function() '[object ' + this.constructor.name + ']' }
+});
+TraitProto = Trait.prototype;
+exports.Trait = Trait;
+
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/traits/core.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/traits/core.js
new file mode 100644
index 0000000..c08c38f
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/traits/core.js
@@ -0,0 +1,322 @@
+/* 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": "deprecated"
+};
+
+// Design inspired by: http://www.traitsjs.org/
+
+// shortcuts
+const getOwnPropertyNames = Object.getOwnPropertyNames,
+ getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
+ hasOwn = Object.prototype.hasOwnProperty,
+ _create = Object.create;
+
+function doPropertiesMatch(object1, object2, name) {
+ // If `object1` has property with the given `name`
+ return name in object1 ?
+ // then `object2` should have it with the same value.
+ name in object2 && object1[name] === object2[name] :
+ // otherwise `object2` should not have property with the given `name`.
+ !(name in object2);
+}
+
+/**
+ * Compares two trait custom property descriptors if they are the same. If
+ * both are `conflict` or all the properties of descriptor are equal returned
+ * value will be `true`, otherwise it will be `false`.
+ * @param {Object} desc1
+ * @param {Object} desc2
+ */
+function areSame(desc1, desc2) {
+ return ('conflict' in desc1 && desc1.conflict &&
+ 'conflict' in desc2 && desc2.conflict) ||
+ (doPropertiesMatch(desc1, desc2, 'get') &&
+ doPropertiesMatch(desc1, desc2, 'set') &&
+ doPropertiesMatch(desc1, desc2, 'value') &&
+ doPropertiesMatch(desc1, desc2, 'enumerable') &&
+ doPropertiesMatch(desc1, desc2, 'required') &&
+ doPropertiesMatch(desc1, desc2, 'conflict'));
+}
+
+/**
+ * Converts array to an object whose own property names represent
+ * values of array.
+ * @param {String[]} names
+ * @returns {Object}
+ * @example
+ * Map(['foo', ...]) => { foo: true, ...}
+ */
+function Map(names) {
+ let map = {};
+ for each (let name in names)
+ map[name] = true;
+ return map;
+}
+
+
+const ERR_CONFLICT = 'Remaining conflicting property: ',
+ ERR_REQUIRED = 'Missing required property: ';
+/**
+ * Constant singleton, representing placeholder for required properties.
+ * @type {Object}
+ */
+const required = { toString: function()'<Trait.required>' };
+exports.required = required;
+
+/**
+ * Generates custom **required** property descriptor. Descriptor contains
+ * non-standard property `required` that is equal to `true`.
+ * @param {String} name
+ * property name to generate descriptor for.
+ * @returns {Object}
+ * custom property descriptor
+ */
+function Required(name) {
+ function required() { throw new Error(ERR_REQUIRED + name) }
+ return {
+ get: required,
+ set: required,
+ required: true
+ };
+}
+
+/**
+ * Generates custom **conflicting** property descriptor. Descriptor contains
+ * non-standard property `conflict` that is equal to `true`.
+ * @param {String} name
+ * property name to generate descriptor for.
+ * @returns {Object}
+ * custom property descriptor
+ */
+function Conflict(name) {
+ function conflict() { throw new Error(ERR_CONFLICT + name) }
+ return {
+ get: conflict,
+ set: conflict,
+ conflict: true
+ };
+}
+
+/**
+ * Function generates custom properties descriptor of the `object`s own
+ * properties. All the inherited properties are going to be ignored.
+ * Properties with values matching `required` singleton will be marked as
+ * 'required' properties.
+ * @param {Object} object
+ * Set of properties to generate trait from.
+ * @returns {Object}
+ * Properties descriptor of all of the `object`'s own properties.
+ */
+function trait(properties) {
+ let result = {},
+ keys = getOwnPropertyNames(properties);
+ for each (let key in keys) {
+ let descriptor = getOwnPropertyDescriptor(properties, key);
+ result[key] = (required === descriptor.value) ? Required(key) : descriptor;
+ }
+ return result;
+}
+exports.Trait = exports.trait = trait;
+
+/**
+ * Composes new trait. If two or more traits have own properties with the
+ * same name, the new trait will contain a 'conflict' property for that name.
+ * 'compose' is a commutative and associative operation, and the order of its
+ * arguments is not significant.
+ *
+ * @params {Object} trait
+ * Takes traits as an arguments
+ * @returns {Object}
+ * New trait containing the combined own properties of all the traits.
+ * @example
+ * var newTrait = compose(trait_1, trait_2, ..., trait_N);
+ */
+function compose(trait1, trait2) {
+ let traits = Array.slice(arguments, 0),
+ result = {};
+ for each (let trait in traits) {
+ let keys = getOwnPropertyNames(trait);
+ for each (let key in keys) {
+ let descriptor = trait[key];
+ // if property already exists and it's not a requirement
+ if (hasOwn.call(result, key) && !result[key].required) {
+ if (descriptor.required)
+ continue;
+ if (!areSame(descriptor, result[key]))
+ result[key] = Conflict(key);
+ } else {
+ result[key] = descriptor;
+ }
+ }
+ }
+ return result;
+}
+exports.compose = compose;
+
+/**
+ * Composes new trait with the same own properties as the original trait,
+ * except that all property names appearing in the first argument are replaced
+ * by 'required' property descriptors.
+ * @param {String[]} keys
+ * Array of strings property names.
+ * @param {Object} trait
+ * A trait some properties of which should be excluded.
+ * @returns {Object}
+ * @example
+ * var newTrait = exclude(['name', ...], trait)
+ */
+function exclude(keys, trait) {
+ let exclusions = Map(keys),
+ result = {};
+
+ keys = getOwnPropertyNames(trait);
+
+ for each (let key in keys) {
+ if (!hasOwn.call(exclusions, key) || trait[key].required)
+ result[key] = trait[key];
+ else
+ result[key] = Required(key);
+ }
+ return result;
+}
+
+/**
+ * Composes a new trait with all of the combined properties of the argument
+ * traits. In contrast to `compose`, `override` immediately resolves all
+ * conflicts resulting from this composition by overriding the properties of
+ * later traits. Trait priority is from left to right. I.e. the properties of
+ * the leftmost trait are never overridden.
+ * @params {Object} trait
+ * @returns {Object}
+ * @examples
+ * // override is associative:
+ * override(t1,t2,t3)
+ * // is equivalent to
+ * override(t1, override(t2, t3))
+ * // or
+ * to override(override(t1, t2), t3)
+ *
+ * // override is not commutative:
+ * override(t1,t2)
+ * // is not equivalent to
+ * override(t2,t1)
+ */
+function override() {
+ let traits = Array.slice(arguments, 0),
+ result = {};
+ for each (let trait in traits) {
+ let keys = getOwnPropertyNames(trait);
+ for each(let key in keys) {
+ let descriptor = trait[key];
+ if (!hasOwn.call(result, key) || result[key].required)
+ result[key] = descriptor;
+ }
+ }
+ return result;
+}
+exports.override = override;
+
+/**
+ * Composes a new trait with the same properties as the original trait, except
+ * that all properties whose name is an own property of map will be renamed to
+ * map[name], and a 'required' property for name will be added instead.
+ * @param {Object} map
+ * An object whose own properties serve as a mapping from old names to new
+ * names.
+ * @param {Object} trait
+ * A trait object
+ * @returns {Object}
+ * @example
+ * var newTrait = rename(map, trait);
+ */
+function rename(map, trait) {
+ let result = {},
+ keys = getOwnPropertyNames(trait);
+ for each(let key in keys) {
+ // must be renamed & it's not requirement
+ if (hasOwn.call(map, key) && !trait[key].required) {
+ let alias = map[key];
+ if (hasOwn.call(result, alias) && !result[alias].required)
+ result[alias] = Conflict(alias);
+ else
+ result[alias] = trait[key];
+ if (!hasOwn.call(result, key))
+ result[key] = Required(key);
+ } else { // must not be renamed or its a requirement
+ // property is not in result trait yet
+ if (!hasOwn.call(result, key))
+ result[key] = trait[key];
+ // property is already in resulted trait & it's not requirement
+ else if (!trait[key].required)
+ result[key] = Conflict(key);
+ }
+ }
+ return result;
+}
+
+/**
+* Composes new resolved trait, with all the same properties as the original
+* trait, except that all properties whose name is an own property of
+* resolutions will be renamed to `resolutions[name]`. If it is
+* `resolutions[name]` is `null` value is changed into a required property
+* descriptor.
+* function can be implemented as `rename(map,exclude(exclusions, trait))`
+* where map is the subset of mappings from oldName to newName and exclusions
+* is an array of all the keys that map to `null`.
+* Note: it's important to **first** `exclude`, **then** `rename`, since
+* `exclude` and rename are not associative.
+* @param {Object} resolutions
+* An object whose own properties serve as a mapping from old names to new
+* names, or to `null` if the property should be excluded.
+* @param {Object} trait
+* A trait object
+* @returns {Object}
+* Resolved trait with the same own properties as the original trait.
+*/
+function resolve(resolutions, trait) {
+ let renames = {},
+ exclusions = [],
+ keys = getOwnPropertyNames(resolutions);
+ for each (let key in keys) { // pre-process renamed and excluded properties
+ if (resolutions[key]) // old name -> new name
+ renames[key] = resolutions[key];
+ else // name -> undefined
+ exclusions.push(key);
+ }
+ return rename(renames, exclude(exclusions, trait));
+}
+exports.resolve = resolve;
+
+/**
+ * `create` is like `Object.create`, except that it ensures that:
+ * - an exception is thrown if 'trait' still contains required properties
+ * - an exception is thrown if 'trait' still contains conflicting
+ * properties
+ * @param {Object}
+ * prototype of the completed object
+ * @param {Object} trait
+ * trait object to be turned into a complete object
+ * @returns {Object}
+ * An object with all of the properties described by the trait.
+ */
+function create(proto, trait) {
+ let properties = {},
+ keys = getOwnPropertyNames(trait);
+ for each(let key in keys) {
+ let descriptor = trait[key];
+ if (descriptor.required && !hasOwn.call(proto, key))
+ throw new Error(ERR_REQUIRED + key);
+ else if (descriptor.conflict)
+ throw new Error(ERR_CONFLICT + key);
+ else
+ properties[key] = descriptor;
+ }
+ return _create(proto, properties);
+}
+exports.create = create;
+
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test-finder.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test-finder.js
new file mode 100644
index 0000000..880f554
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test-finder.js
@@ -0,0 +1,71 @@
+/* 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": "deprecated"
+};
+
+const file = require("../io/file");
+const memory = require('./memory');
+const suites = require('@test/options').allTestModules;
+
+
+const NOT_TESTS = ['setup', 'teardown'];
+
+var TestFinder = exports.TestFinder = function TestFinder(options) {
+ memory.track(this);
+ this.filter = options.filter;
+ this.testInProcess = options.testInProcess === false ? false : true;
+ this.testOutOfProcess = options.testOutOfProcess === true ? true : false;
+};
+
+TestFinder.prototype = {
+ findTests: function findTests(cb) {
+ var self = this;
+ var tests = [];
+ var filter;
+ // A filter string is {fileNameRegex}[:{testNameRegex}] - ie, a colon
+ // optionally separates a regex for the test fileName from a regex for the
+ // testName.
+ if (this.filter) {
+ var colonPos = this.filter.indexOf(':');
+ var filterFileRegex, filterNameRegex;
+ if (colonPos === -1) {
+ filterFileRegex = new RegExp(self.filter);
+ } else {
+ filterFileRegex = new RegExp(self.filter.substr(0, colonPos));
+ filterNameRegex = new RegExp(self.filter.substr(colonPos + 1));
+ }
+ // This function will first be called with just the filename; if
+ // it returns true the module will be loaded then the function
+ // called again with both the filename and the testname.
+ filter = function(filename, testname) {
+ return filterFileRegex.test(filename) &&
+ ((testname && filterNameRegex) ? filterNameRegex.test(testname)
+ : true);
+ };
+ } else
+ filter = function() {return true};
+
+ suites.forEach(
+ function(suite) {
+ var module = require(suite);
+ if (self.testInProcess)
+ for each (let name in Object.keys(module).sort()) {
+ if(NOT_TESTS.indexOf(name) === -1 && filter(suite, name)) {
+ tests.push({
+ setup: module.setup,
+ teardown: module.teardown,
+ testFunction: module[name],
+ name: suite + "." + name
+ });
+ }
+ }
+ });
+
+ cb(tests);
+ }
+};
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test.js
new file mode 100644
index 0000000..6a8ac1b
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/unit-test.js
@@ -0,0 +1,451 @@
+/* vim:st=2:sts=2:sw=2:
+ * 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": "deprecated"
+};
+
+const memory = require('./memory');
+var timer = require("../timers");
+
+exports.findAndRunTests = function findAndRunTests(options) {
+ var TestFinder = require("./unit-test-finder").TestFinder;
+ var finder = new TestFinder({
+ filter: options.filter,
+ testInProcess: options.testInProcess,
+ testOutOfProcess: options.testOutOfProcess
+ });
+ var runner = new TestRunner({fs: options.fs});
+ finder.findTests(
+ function (tests) {
+ runner.startMany({tests: tests,
+ stopOnError: options.stopOnError,
+ onDone: options.onDone});
+ });
+};
+
+var TestRunner = exports.TestRunner = function TestRunner(options) {
+ if (options) {
+ this.fs = options.fs;
+ }
+ this.console = (options && "console" in options) ? options.console : console;
+ memory.track(this);
+ this.passed = 0;
+ this.failed = 0;
+ this.testRunSummary = [];
+ this.expectFailNesting = 0;
+};
+
+TestRunner.prototype = {
+ toString: function toString() "[object TestRunner]",
+
+ DEFAULT_PAUSE_TIMEOUT: 10000,
+ PAUSE_DELAY: 500,
+
+ _logTestFailed: function _logTestFailed(why) {
+ if (!(why in this.test.errors))
+ this.test.errors[why] = 0;
+ this.test.errors[why]++;
+ if (!this.testFailureLogged) {
+ this.console.error("TEST FAILED: " + this.test.name + " (" + why + ")");
+ this.testFailureLogged = true;
+ }
+ },
+
+ pass: function pass(message) {
+ if(!this.expectFailure) {
+ this.console.info("pass:", message);
+ this.passed++;
+ this.test.passed++;
+ }
+ else {
+ this.expectFailure = false;
+ this.fail('Failure Expected: ' + message);
+ }
+ },
+
+ fail: function fail(message) {
+ if(!this.expectFailure) {
+ this._logTestFailed("failure");
+ this.console.error("fail:", message);
+ this.console.trace();
+ this.failed++;
+ this.test.failed++;
+ }
+ else {
+ this.expectFailure = false;
+ this.pass(message);
+ }
+ },
+
+ expectFail: function(callback) {
+ this.expectFailure = true;
+ callback();
+ this.expectFailure = false;
+ },
+
+ exception: function exception(e) {
+ this._logTestFailed("exception");
+ this.console.exception(e);
+ this.failed++;
+ this.test.failed++;
+ },
+
+ assertMatches: function assertMatches(string, regexp, message) {
+ if (regexp.test(string)) {
+ if (!message)
+ message = uneval(string) + " matches " + uneval(regexp);
+ this.pass(message);
+ } else {
+ var no = uneval(string) + " doesn't match " + uneval(regexp);
+ if (!message)
+ message = no;
+ else
+ message = message + " (" + no + ")";
+ this.fail(message);
+ }
+ },
+
+ assertRaises: function assertRaises(func, predicate, message) {
+ try {
+ func();
+ if (message)
+ this.fail(message + " (no exception thrown)");
+ else
+ this.fail("function failed to throw exception");
+ } catch (e) {
+ var errorMessage;
+ if (typeof(e) == "string")
+ errorMessage = e;
+ else
+ errorMessage = e.message;
+ if (typeof(predicate) == "string")
+ this.assertEqual(errorMessage, predicate, message);
+ else
+ this.assertMatches(errorMessage, predicate, message);
+ }
+ },
+
+ assert: function assert(a, message) {
+ if (!a) {
+ if (!message)
+ message = "assertion failed, value is " + a;
+ this.fail(message);
+ } else
+ this.pass(message || "assertion successful");
+ },
+
+ assertNotEqual: function assertNotEqual(a, b, message) {
+ if (a != b) {
+ if (!message)
+ message = "a != b != " + uneval(a);
+ this.pass(message);
+ } else {
+ var equality = uneval(a) + " == " + uneval(b);
+ if (!message)
+ message = equality;
+ else
+ message += " (" + equality + ")";
+ this.fail(message);
+ }
+ },
+
+ assertEqual: function assertEqual(a, b, message) {
+ if (a == b) {
+ if (!message)
+ message = "a == b == " + uneval(a);
+ this.pass(message);
+ } else {
+ var inequality = uneval(a) + " != " + uneval(b);
+ if (!message)
+ message = inequality;
+ else
+ message += " (" + inequality + ")";
+ this.fail(message);
+ }
+ },
+
+ assertNotStrictEqual: function assertNotStrictEqual(a, b, message) {
+ if (a !== b) {
+ if (!message)
+ message = "a !== b !== " + uneval(a);
+ this.pass(message);
+ } else {
+ var equality = uneval(a) + " === " + uneval(b);
+ if (!message)
+ message = equality;
+ else
+ message += " (" + equality + ")";
+ this.fail(message);
+ }
+ },
+
+ assertStrictEqual: function assertStrictEqual(a, b, message) {
+ if (a === b) {
+ if (!message)
+ message = "a === b === " + uneval(a);
+ this.pass(message);
+ } else {
+ var inequality = uneval(a) + " !== " + uneval(b);
+ if (!message)
+ message = inequality;
+ else
+ message += " (" + inequality + ")";
+ this.fail(message);
+ }
+ },
+
+ assertFunction: function assertFunction(a, message) {
+ this.assertStrictEqual('function', typeof a, message);
+ },
+
+ assertUndefined: function(a, message) {
+ this.assertStrictEqual('undefined', typeof a, message);
+ },
+
+ assertNotUndefined: function(a, message) {
+ this.assertNotStrictEqual('undefined', typeof a, message);
+ },
+
+ assertNull: function(a, message) {
+ this.assertStrictEqual(null, a, message);
+ },
+
+ assertNotNull: function(a, message) {
+ this.assertNotStrictEqual(null, a, message);
+ },
+
+ assertObject: function(a, message) {
+ this.assertStrictEqual('[object Object]', Object.prototype.toString.apply(a), message);
+ },
+
+ assertString: function(a, message) {
+ this.assertStrictEqual('[object String]', Object.prototype.toString.apply(a), message);
+ },
+
+ assertArray: function(a, message) {
+ this.assertStrictEqual('[object Array]', Object.prototype.toString.apply(a), message);
+ },
+
+ assertNumber: function(a, message) {
+ this.assertStrictEqual('[object Number]', Object.prototype.toString.apply(a), message);
+ },
+
+ done: function done() {
+ if (!this.isDone) {
+ this.isDone = true;
+ if(this.test.teardown) {
+ this.test.teardown(this);
+ }
+ if (this.waitTimeout !== null) {
+ timer.clearTimeout(this.waitTimeout);
+ this.waitTimeout = null;
+ }
+ // Do not leave any callback set when calling to `waitUntil`
+ this.waitUntilCallback = null;
+ if (this.test.passed == 0 && this.test.failed == 0) {
+ this._logTestFailed("empty test");
+ this.failed++;
+ this.test.failed++;
+ }
+
+ this.testRunSummary.push({
+ name: this.test.name,
+ passed: this.test.passed,
+ failed: this.test.failed,
+ errors: [error for (error in this.test.errors)].join(", ")
+ });
+
+ if (this.onDone !== null) {
+ var onDone = this.onDone;
+ var self = this;
+ this.onDone = null;
+ timer.setTimeout(function() { onDone(self); }, 0);
+ }
+ }
+ },
+
+ // Set of assertion functions to wait for an assertion to become true
+ // These functions take the same arguments as the TestRunner.assert* methods.
+ waitUntil: function waitUntil() {
+ return this._waitUntil(this.assert, arguments);
+ },
+
+ waitUntilNotEqual: function waitUntilNotEqual() {
+ return this._waitUntil(this.assertNotEqual, arguments);
+ },
+
+ waitUntilEqual: function waitUntilEqual() {
+ return this._waitUntil(this.assertEqual, arguments);
+ },
+
+ waitUntilMatches: function waitUntilMatches() {
+ return this._waitUntil(this.assertMatches, arguments);
+ },
+
+ /**
+ * Internal function that waits for an assertion to become true.
+ * @param {Function} assertionMethod
+ * Reference to a TestRunner assertion method like test.assert,
+ * test.assertEqual, ...
+ * @param {Array} args
+ * List of arguments to give to the previous assertion method.
+ * All functions in this list are going to be called to retrieve current
+ * assertion values.
+ */
+ _waitUntil: function waitUntil(assertionMethod, args) {
+ let count = 0;
+ let maxCount = this.DEFAULT_PAUSE_TIMEOUT / this.PAUSE_DELAY;
+
+ // We need to ensure that test is asynchronous
+ if (!this.waitTimeout)
+ this.waitUntilDone(this.DEFAULT_PAUSE_TIMEOUT);
+
+ let callback = null;
+ let finished = false;
+
+ let test = this;
+
+ // capture a traceback before we go async.
+ let traceback = require("../console/traceback");
+ let stack = traceback.get();
+ stack.splice(-2, 2);
+ let currentWaitStack = traceback.format(stack);
+ let timeout = null;
+
+ function loop(stopIt) {
+ timeout = null;
+
+ // Build a mockup object to fake TestRunner API and intercept calls to
+ // pass and fail methods, in order to retrieve nice error messages
+ // and assertion result
+ let mock = {
+ pass: function (msg) {
+ test.pass(msg);
+ test.waitUntilCallback = null;
+ if (callback && !stopIt)
+ callback();
+ finished = true;
+ },
+ fail: function (msg) {
+ // If we are called on test timeout, we stop the loop
+ // and print which test keeps failing:
+ if (stopIt) {
+ test.console.error("test assertion never became true:\n",
+ msg + "\n",
+ currentWaitStack);
+ if (timeout)
+ timer.clearTimeout(timeout);
+ return;
+ }
+ timeout = timer.setTimeout(loop, test.PAUSE_DELAY);
+ }
+ };
+
+ // Automatically call args closures in order to build arguments for
+ // assertion function
+ let appliedArgs = [];
+ for (let i = 0, l = args.length; i < l; i++) {
+ let a = args[i];
+ if (typeof a == "function") {
+ try {
+ a = a();
+ }
+ catch(e) {
+ test.fail("Exception when calling asynchronous assertion: " + e +
+ "\n" + e.stack);
+ finished = true;
+ return;
+ }
+ }
+ appliedArgs.push(a);
+ }
+
+ // Finally call assertion function with current assertion values
+ assertionMethod.apply(mock, appliedArgs);
+ }
+ loop();
+ this.waitUntilCallback = loop;
+
+ // Return an object with `then` method, to offer a way to execute
+ // some code when the assertion passed or failed
+ return {
+ then: function (c) {
+ callback = c;
+
+ // In case of immediate positive result, we need to execute callback
+ // immediately here:
+ if (finished)
+ callback();
+ }
+ };
+ },
+
+ waitUntilDone: function waitUntilDone(ms) {
+ if (ms === undefined)
+ ms = this.DEFAULT_PAUSE_TIMEOUT;
+
+ var self = this;
+
+ function tiredOfWaiting() {
+ self._logTestFailed("timed out");
+ if (self.waitUntilCallback) {
+ self.waitUntilCallback(true);
+ self.waitUntilCallback = null;
+ }
+ self.failed++;
+ self.test.failed++;
+ self.done();
+ }
+
+ // We may already have registered a timeout callback
+ if (this.waitTimeout)
+ timer.clearTimeout(this.waitTimeout);
+
+ this.waitTimeout = timer.setTimeout(tiredOfWaiting, ms);
+ },
+
+ startMany: function startMany(options) {
+ function runNextTest(self) {
+ var test = options.tests.shift();
+ if (options.stopOnError && self.test && self.test.failed) {
+ self.console.error("aborted: test failed and --stop-on-error was specified");
+ options.onDone(self);
+ } else if (test) {
+ self.start({test: test, onDone: runNextTest});
+ } else {
+ options.onDone(self);
+ }
+ }
+ runNextTest(this);
+ },
+
+ start: function start(options) {
+ this.test = options.test;
+ this.test.passed = 0;
+ this.test.failed = 0;
+ this.test.errors = {};
+
+ this.isDone = false;
+ this.onDone = options.onDone;
+ this.waitTimeout = null;
+ this.testFailureLogged = false;
+
+ try {
+ this.console.info("executing '" + this.test.name + "'");
+
+ if(this.test.setup) {
+ this.test.setup(this);
+ }
+ this.test.testFunction(this);
+ } catch (e) {
+ this.exception(e);
+ }
+ if (this.waitTimeout === null)
+ this.done();
+ }
+};
diff --git a/tools/addon-sdk-1.12/lib/sdk/deprecated/window-utils.js b/tools/addon-sdk-1.12/lib/sdk/deprecated/window-utils.js
new file mode 100644
index 0000000..66fcfba
--- /dev/null
+++ b/tools/addon-sdk-1.12/lib/sdk/deprecated/window-utils.js
@@ -0,0 +1,201 @@
+/* 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': 'deprecated'
+};
+
+const { Cc, Ci } = require('chrome');
+const { EventEmitter } = require('../deprecated/events');
+const { Trait } = require('../deprecated/traits');
+const { when } = require('../system/unload');
+const { getInnerId, getOuterId, windows, isDocumentLoaded, isBrowser,
+ getMostRecentBrowserWindow } = require('../window/utils');
+const errors = require('../deprecated/errors');
+const { deprecateFunction } = require('../util/deprecate');
+
+const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1'].
+ getService(Ci.nsIWindowWatcher);
+const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
+ getService(Ci.nsIAppShellService);
+
+/**
+ * An iterator for XUL windows currently in the application.
+ *
+ * @return A generator that yields XUL windows exposing the
+ * nsIDOMWindow interface.
+ */
+function windowIterator() {
+ // Bug 752631: We only pass already loaded window in order to avoid
+ // breaking XUL windows DOM. DOM is broken when some JS code try
+ // to access DOM during "uninitialized" state of the related document.
+ let list = windows().filter(isDocumentLoaded);
+ for (let i = 0, l = list.length; i < l; i++) {
+ yield list[i];
+ }
+};
+exports.windowIterator = windowIterator;
+
+/**
+ * An iterator for browser windows currently open in the application.
+ * @returns {Function}
+ * A generator that yields browser windows exposing the `nsIDOMWindow`
+ * interface.
+ */
+function browserWindowIterator() {
+ for each (let window in windowIterator()) {
+ if (isBrowser(window))
+ yield window;
+ }
+}
+exports.browserWindowIterator = browserWindowIterator;
+
+function WindowTracker(delegate) {
+ if (!(this instanceof WindowTracker)) {
+ return new WindowTracker(delegate);
+ }
+
+ this._delegate = delegate;
+ this._loadingWindows = [];
+
+ for each (let window in windows())
+ this._regWindow(window);
+ windowWatcher.registerNotification(this);
+
+ require('../system/unload').ensure(this);
+
+ return this;
+};
+
+WindowTracker.prototype = {
+ _regLoadingWindow: function _regLoadingWindow(window) {
+ this._loadingWindows.push(window);
+ window.addEventListener('load', this, true);
+ },
+
+ _unregLoadingWindow: function _unregLoadingWindow(window) {
+ var index = this._loadingWindows.indexOf(window);
+
+ if (index != -1) {
+ this._loadingWindows.splice(index, 1);
+ window.removeEventListener('load', this, true);
+ }
+ },
+
+ _regWindow: function _regWindow(window) {
+ if (window.document.readyState == 'complete') {
+ this._unregLoadingWindow(window);
+ this._delegate.onTrack(window);
+ } else
+ this._regLoadingWindow(window);
+ },
+
+ _unregWindow: function _unregWindow(window) {
+ if (window.document.readyState == 'complete') {
+ if (this._delegate.onUntrack)
+ this._delegate.onUntrack(window);
+ } else {
+ this._unregLoadingWindow(window);
+ }
+ },
+
+ unload: function unload() {
+ windowWatcher.unregisterNotification(this);
+ for each (let window in windows())
+ this._unregWindow(window);
+ },
+
+ handleEvent: errors.catchAndLog(function handleEvent(event) {
+ if (event.type == 'load' && event.target) {
+ var window = event.target.defaultView;
+ if (window)
+ this._regWindow(window);
+ }
+ }),
+
+ observe: errors.catchAndLog(function observe(subject, topic, data) {
+ var window = subject.QueryInterface(Ci.nsIDOMWindow);
+ if (topic == 'domwindowopened')
+ this._regWindow(window);
+ else
+ this._unregWindow(window);
+ })
+};
+exports.WindowTracker = WindowTracker;
+
+const WindowTrackerTrait = Trait.compose({
+ _onTrack: Trait.required,
+ _onUntrack: Trait.required,
+ constructor: function WindowTrackerTrait() {
+ WindowTracker({
+ onTrack: this._onTrack.bind(this),
+ onUntrack: this._onUntrack.bind(this)
+ });
+ }
+});
+exports.WindowTrackerTrait = WindowTrackerTrait;
+
+var gDocsToClose = [];
+
+function onDocUnload(event) {
+ var index = gDocsToClose.indexOf(event.target);
+ if (index == -1)
+ throw new Error('internal error: unloading document not found');
+ var document = gDocsToClose.splice(index, 1)[0];
+ // Just in case, let's remove the event listener too.
+ document.defaultView.removeEventListener('unload', onDocUnload, false);
+}
+
+onDocUnload = require('./errors').catchAndLog(onDocUnload);
+
+exports.closeOnUnload = function closeOnUnload(window) {
+ window.addEventListener('unload', onDocUnload, false);
+ gDocsToClose.push(window.document);
+};
+
+Object.defineProperties(exports, {
+ activeWindow: {
+ enumerable: true,
+ get: function() {
+ return Cc['@mozilla.org/appshell/window-mediator;1']
+ .getService(Ci.nsIWindowMediator)
+ .getMostRecentWindow(null);
+ },
+ set: function(window) {
+ try { window.focus(); } catch (e) { }
+ }
+ },
+ activeBrowserWindow: {
+ enumerable: true,
+ get: getMostRecentBrowserWindow
+ }
+});
+
+
+/**
+ * Returns the ID of the window's current inner window.
+ */
+exports.getInnerId = deprecateFunction(getInnerId,
+ 'require("window-utils").getInnerId is deprecated, ' +
+ 'please use require("window/utils").getInnerId instead'
+);
+
+exports.getOuterId = deprecateFunction(getOuterId,
+ 'require("window-utils").getOuterId is deprecated, ' +
+ 'please use require("window/utils").getOuterId instead'
+);
+
+exports.isBrowser = deprecateFunction(isBrowser,
+ 'require("window-utils").isBrowser is deprecated, ' +
+ 'please use require("window/utils").isBrowser instead'
+);
+
+exports.hiddenWindow = appShellService.hiddenDOMWindow;
+
+when(
+ function() {
+ gDocsToClose.slice().forEach(
+ function(doc) { doc.defaultView.close(); });
+ });