summaryrefslogtreecommitdiffstats
path: root/mobile/android/modules/DelayedInit.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/modules/DelayedInit.jsm')
-rw-r--r--mobile/android/modules/DelayedInit.jsm177
1 files changed, 0 insertions, 177 deletions
diff --git a/mobile/android/modules/DelayedInit.jsm b/mobile/android/modules/DelayedInit.jsm
deleted file mode 100644
index 7c33a3ede..000000000
--- a/mobile/android/modules/DelayedInit.jsm
+++ /dev/null
@@ -1,177 +0,0 @@
-/* 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"
-
-/*globals MessageLoop */
-
-const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
-
-this.EXPORTED_SYMBOLS = ["DelayedInit"];
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "MessageLoop",
- "@mozilla.org/message-loop;1",
- "nsIMessageLoop");
-
-/**
- * Use DelayedInit to schedule initializers to run some time after startup.
- * Initializers are added to a list of pending inits. Whenever the main thread
- * message loop is idle, DelayedInit will start running initializers from the
- * pending list. To prevent monopolizing the message loop, every idling period
- * has a maximum duration. When that's reached, we give up the message loop and
- * wait for the next idle.
- *
- * DelayedInit is compatible with lazy getters like those from XPCOMUtils. When
- * the lazy getter is first accessed, its corresponding initializer is run
- * automatically if it hasn't been run already. Each initializer also has a
- * maximum wait parameter that specifies a mandatory timeout; when the timeout
- * is reached, the initializer is forced to run.
- *
- * DelayedInit.schedule(() => Foo.init(), null, null, 5000);
- *
- * In the example above, Foo.init will run automatically when the message loop
- * becomes idle, or when 5000ms has elapsed, whichever comes first.
- *
- * DelayedInit.schedule(() => Foo.init(), this, "Foo", 5000);
- *
- * In the example above, Foo.init will run automatically when the message loop
- * becomes idle, when |this.Foo| is accessed, or when 5000ms has elapsed,
- * whichever comes first.
- *
- * It may be simpler to have a wrapper for DelayedInit.schedule. For example,
- *
- * function InitLater(fn, obj, name) {
- * return DelayedInit.schedule(fn, obj, name, 5000); // constant max wait
- * }
- * InitLater(() => Foo.init());
- * InitLater(() => Bar.init(), this, "Bar");
- */
-var DelayedInit = {
- schedule: function (fn, object, name, maxWait) {
- return Impl.scheduleInit(fn, object, name, maxWait);
- },
-};
-
-// Maximum duration for each idling period. Pending inits are run until this
-// duration is exceeded; then we wait for next idling period.
-const MAX_IDLE_RUN_MS = 50;
-
-var Impl = {
- pendingInits: [],
-
- onIdle: function () {
- let startTime = Cu.now();
- let time = startTime;
- let nextDue;
-
- // Go through all the pending inits. Even if we don't run them,
- // we still need to find out when the next timeout should be.
- for (let init of this.pendingInits) {
- if (init.complete) {
- continue;
- }
-
- if (time - startTime < MAX_IDLE_RUN_MS) {
- init.maybeInit();
- time = Cu.now();
- } else {
- // We ran out of time; find when the next closest due time is.
- nextDue = nextDue ? Math.min(nextDue, init.due) : init.due;
- }
- }
-
- // Get rid of completed ones.
- this.pendingInits = this.pendingInits.filter((init) => !init.complete);
-
- if (nextDue !== undefined) {
- // Schedule the next idle, if we still have pending inits.
- MessageLoop.postIdleTask(() => this.onIdle(),
- Math.max(0, nextDue - time));
- }
- },
-
- addPendingInit: function (fn, wait) {
- let init = {
- fn: fn,
- due: Cu.now() + wait,
- complete: false,
- maybeInit: function () {
- if (this.complete) {
- return false;
- }
- this.complete = true;
- this.fn.call();
- this.fn = null;
- return true;
- },
- };
-
- if (!this.pendingInits.length) {
- // Schedule for the first idle.
- MessageLoop.postIdleTask(() => this.onIdle(), wait);
- }
- this.pendingInits.push(init);
- return init;
- },
-
- scheduleInit: function (fn, object, name, wait) {
- let init = this.addPendingInit(fn, wait);
-
- if (!object || !name) {
- // No lazy getter needed.
- return;
- }
-
- // Get any existing information about the property.
- let prop = Object.getOwnPropertyDescriptor(object, name) ||
- { configurable: true, enumerable: true, writable: true };
-
- if (!prop.configurable) {
- // Object.defineProperty won't work, so just perform init here.
- init.maybeInit();
- return;
- }
-
- // Define proxy getter/setter that will call first initializer first,
- // before delegating the get/set to the original target.
- Object.defineProperty(object, name, {
- get: function proxy_getter() {
- init.maybeInit();
-
- // If the initializer actually ran, it may have replaced our proxy
- // property with a real one, so we need to reload he property.
- let newProp = Object.getOwnPropertyDescriptor(object, name);
- if (newProp.get !== proxy_getter) {
- // Set prop if newProp doesn't refer to our proxy property.
- prop = newProp;
- } else {
- // Otherwise, reset to the original property.
- Object.defineProperty(object, name, prop);
- }
-
- if (prop.get) {
- return prop.get.call(object);
- }
- return prop.value;
- },
- set: function (newVal) {
- init.maybeInit();
-
- // Since our initializer already ran,
- // we can get rid of our proxy property.
- if (prop.get || prop.set) {
- Object.defineProperty(object, name, prop);
- return prop.set.call(object);
- }
-
- prop.value = newVal;
- Object.defineProperty(object, name, prop);
- return newVal;
- },
- configurable: true,
- enumerable: true,
- });
- }
-};