toolkit/components/contentprefs/tests/unit_cps2/AsyncRunner.jsm

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/components/contentprefs/tests/unit_cps2/AsyncRunner.jsm	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,72 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +let EXPORTED_SYMBOLS = [
     1.9 +  "AsyncRunner",
    1.10 +];
    1.11 +
    1.12 +const { interfaces: Ci, classes: Cc } = Components;
    1.13 +
    1.14 +function AsyncRunner(callbacks) {
    1.15 +  this._callbacks = callbacks;
    1.16 +  this._iteratorQueue = [];
    1.17 +
    1.18 +  // This catches errors reported to the console, e.g., via Cu.reportError.
    1.19 +  Cc["@mozilla.org/consoleservice;1"].
    1.20 +    getService(Ci.nsIConsoleService).
    1.21 +    registerListener(this);
    1.22 +}
    1.23 +
    1.24 +AsyncRunner.prototype = {
    1.25 +
    1.26 +  appendIterator: function AR_appendIterator(iter) {
    1.27 +    this._iteratorQueue.push(iter);
    1.28 +  },
    1.29 +
    1.30 +  next: function AR_next(/* ... */) {
    1.31 +    if (!this._iteratorQueue.length) {
    1.32 +      this.destroy();
    1.33 +      this._callbacks.done();
    1.34 +      return;
    1.35 +    }
    1.36 +
    1.37 +    // send() discards all arguments after the first, so there's no choice here
    1.38 +    // but to send only one argument to the yielder.
    1.39 +    let args = [arguments.length <= 1 ? arguments[0] : Array.slice(arguments)];
    1.40 +    try {
    1.41 +      var val = this._iteratorQueue[0].send.apply(this._iteratorQueue[0], args);
    1.42 +    }
    1.43 +    catch (err if err instanceof StopIteration) {
    1.44 +      this._iteratorQueue.shift();
    1.45 +      this.next();
    1.46 +      return;
    1.47 +    }
    1.48 +    catch (err) {
    1.49 +      this._callbacks.error(err);
    1.50 +    }
    1.51 +
    1.52 +    // val is truthy => call next
    1.53 +    // val is an iterator => prepend it to the queue and start on it
    1.54 +    if (val) {
    1.55 +      if (typeof(val) != "boolean")
    1.56 +        this._iteratorQueue.unshift(val);
    1.57 +      this.next();
    1.58 +    }
    1.59 +  },
    1.60 +
    1.61 +  destroy: function AR_destroy() {
    1.62 +    Cc["@mozilla.org/consoleservice;1"].
    1.63 +      getService(Ci.nsIConsoleService).
    1.64 +      unregisterListener(this);
    1.65 +    this.destroy = function AR_alreadyDestroyed() {};
    1.66 +  },
    1.67 +
    1.68 +  observe: function AR_consoleServiceListener(msg) {
    1.69 +    if (msg instanceof Ci.nsIScriptError &&
    1.70 +        !(msg.flags & Ci.nsIScriptError.warningFlag))
    1.71 +    {
    1.72 +      this._callbacks.consoleError(msg);
    1.73 +    }
    1.74 +  },
    1.75 +};

mercurial