~dpm/ubufox/ca-update

« back to all changes in this revision

Viewing changes to res/modules/utils.jsm

  • Committer: Chris Coulson
  • Date: 2012-10-14 23:38:21 UTC
  • Revision ID: chris.coulson@canonical.com-20121014233821-uvbz5g0ux9hp3jgd
Refactor how we handle callbacks

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
var gBase;
17
17
var gLogPrefRoot;
18
18
var gBindNow = false;
 
19
var gCallbacks = {};
 
20
var gCallbacksByWrapper = {};
19
21
 
20
22
function formatLogMessage(aType, aDomain, aStr, aException) {
21
23
  let message = aType.toUpperCase() + " " + aDomain + ": " + aStr;
151
153
  }
152
154
 
153
155
  let domain;
154
 
  if (aDomain != null) {
 
156
  if (aDomain) {
155
157
    if (typeof(aDomain) != "string") {
156
158
      throw Error("Invalid type for domain");
157
159
    }
274
276
 
275
277
        let func = library.declare.apply(library, args);
276
278
        LOG("Loaded symbol " + aSymbol + " in lib" + aName + ".so."
277
 
            + self.ABI.toString());
 
279
            + abi.toString());
278
280
        return func;
279
281
      } catch (ex) {
280
282
        LOG("Failed to bind symbol " + aSymbol + " in lib" + aName + ".so."
281
 
            + self.ABI.toString());
 
283
            + abi.toString() + ": " + ex);
282
284
        return null;
283
285
      }
284
286
    }
605
607
    Object.defineProperty(aTarget, aName, { value: aValue, enumerable: true });
606
608
  }},
607
609
 
608
 
  /**
609
 
   * Set up a ctype function template and create a helper function for
610
 
   * wrapping JS functions as ctype functions, for use as an async callback
611
 
   * in asynchronous API's
612
 
   *
613
 
   * @param  aObj
614
 
   *         The object to add the helper and function template to
615
 
   * @param  aName
616
 
   *         The type name of the callback. Note that the helper function
617
 
   *         will be "wrap<type>" (eg, "wrapGAsyncReadyCallback")
618
 
   * @param  aRetType
619
 
   *         The native return type of the async callback
620
 
   * @param  aArgTypes
621
 
   *         An array of native argument types to be passed to the callback
622
 
   */
623
 
  createAsyncCallbackWrapper: {
624
 
    value: function CTypesUtils_createAsyncCallbackWrapper(aObj, aName,
625
 
                                                           aRetType,
626
 
                                                           aArgTypes) {
627
 
    var serial = 0;
628
 
    var callbacks = {};
629
 
 
630
 
    Object.defineProperty(aObj, aName, {
631
 
      value: ctypes.FunctionType(ctypes.default_abi, aRetType, aArgTypes).ptr,
632
 
      enumerable: true
633
 
    });
634
 
 
635
 
    Object.defineProperty(aObj, "wrap" + aName, {
636
 
      value: function(aCallback) {
637
 
        let cb = function() {
638
 
          try {
639
 
            return aCallback.apply(null, arguments);
640
 
          } catch(e) { ERROR("Async callback threw", e); }
641
 
          delete callbacks[id];
642
 
        };
643
 
        let ccb = aObj[aName](cb);
644
 
 
645
 
        while (callbacks[++serial]) {}
646
 
        var id = serial;
647
 
        callbacks[id] = ccb;
648
 
 
649
 
        return ccb;
650
 
      }
651
 
    });
 
610
  wrapCallback: { value: function CTypesUtils_wrapCallback(aCallback, aOptions) {
 
611
 
 
612
    function CallbackRootData(aWrapper) {
 
613
      this.wrapper = aWrapper;
 
614
      this.refcnt = 1;
 
615
    }
 
616
 
 
617
    if (typeof(aCallback) != "function") {
 
618
      throw Error("Callback must be a function");
 
619
    }
 
620
 
 
621
    if (typeof(aOptions) != "object" ||
 
622
        (!aOptions.type && !aOptions.rettype) ||
 
623
        (aOptions.type && aOptions.rettype)) {
 
624
      throw Error("Must specify a valid function type or return type");
 
625
    }
 
626
 
 
627
    if (aOptions.root && aCallback in gCallbacks) {
 
628
      gCallbacks[aCallback].refcnt++;
 
629
      return gCallbacks[aCallback].wrapper;
 
630
    }
 
631
 
 
632
    let wrapper = function() {
 
633
      try {
 
634
        return aCallback.apply(null, arguments);
 
635
      } catch(e) { ERROR("Callback threw", e); }
 
636
    };
 
637
 
 
638
    let type;
 
639
    if (aOptions.type) {
 
640
      type = aOptions.type;
 
641
    } else {
 
642
      type = ctypes.FunctionType(ctypes.default_abi, aOptions.rettype,
 
643
                                 aOptions.argtypes ? aOptions.argtypes : []).ptr;
 
644
    }
 
645
    wrapper = type(wrapper);
 
646
 
 
647
    if (aOptions.root) {
 
648
      gCallbacks[aCallback] = new CallbackRootData(wrapper);
 
649
      gCallbacksByWrapper[wrapper] = aCallback;
 
650
    }
 
651
 
 
652
    return wrapper;
 
653
  }},
 
654
 
 
655
  unrootCallback: { value: function CTypesUtils_unrootCallback(aCallback) {
 
656
    if (!(aCallback in gCallbacks)) {
 
657
      throw Error("The callback cannot be found in our roots");
 
658
    }
 
659
 
 
660
    if (gCallbacks[aCallback].refcnt <= 0) {
 
661
      ERROR("Ugh, why is this callback still rooted");
 
662
    }
 
663
 
 
664
    if (--gCallbacks[aCallback].refcnt <= 0) {
 
665
      let wrapper = gCallbacks[aCallback].wrapper;
 
666
      delete gCallbacks[aCallback];
 
667
      delete gCallbacksByWrapper[wrapper];
 
668
    }
 
669
  }},
 
670
 
 
671
  unrootCallbackByWrapper: { value: function CTypesUtils_unrootCallbackByWrapper(aCallback) {
 
672
    if (!(aCallback in gCallbacksByWrapper)) {
 
673
      throw Error("The callback cannot be found in our roots");
 
674
    }
 
675
 
 
676
    this.unrootCallback(gCallbacksByWrapper[aCallback]);
 
677
  }},
 
678
 
 
679
  callbackIsRooted: { value: function CTypesUtils_callbackIsRooted(aCallback) {
 
680
    if (aCallback in gCallbacks) {
 
681
      return true;
 
682
    }
 
683
 
 
684
    if (aCallback in gCallbacksByWrapper &&
 
685
        gCallbacksByWrapper[aCallback] in gCallbacks) {
 
686
      return true;
 
687
    }
 
688
 
 
689
    return false;
652
690
  }}
653
691
});
654
692
 
664
702
function SimpleObjectWrapper(aObject) {
665
703
 
666
704
  if (!("__exposedProps__" in aObject)) {
667
 
    throw Error("__exposedProps missing from object");
 
705
    throw Error("__exposedProps__ missing from object");
668
706
  }
669
707
 
670
708
  function Wrapper() {