diff options
Diffstat (limited to 'mobile/android/modules/DelayedInit.jsm')
-rw-r--r-- | mobile/android/modules/DelayedInit.jsm | 177 |
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, - }); - } -}; |