2014年1月17日

Firefox 28 での DeferredTask.jsm の変更

DeferredTask.jsm が Firefox 28 でインターフェースというか内部の作りからまるまる変更され、Promise.jsmTask.jsm ベースになりました。
(という事をついさっき UnMHT の Mozmill のテストを Nightly 向けに走らせて知りました)
詳細は Bug 940408 を参照。
Firefox 27 までの DeferredTask.jsm は、以下のような使い方でした。

let helloTask = new DeferredTask(function() {
  Cu.reportError("Hello");
}, 2000);

// タスクを開始
helloTask.start();

setTimeout(function() {
  // 1 秒待ってからタスクを再度開始
  helloTask.start();
}, 1000);

// 3 秒後に Hello と表示される

Firefox 28 からは、同じ事をやるのに以下のように書くようです。

let helloTask = new DeferredTask(function() {
  Cu.reportError("Hello");
}, 2000);

// タスクを開始
helloTask.arm();

setTimeout(function() {
  // 1 秒待ってからタスクを取り止め
  helloTask.disarm();
  // タスクを開始
  helloTask.arm();
}, 1000);

// 3 秒後に Hello と表示される

おおよその対応は以下のとおり

Firefox 27 までFirefox 28 から
void start()void arm()
void cancel()void disarm()
void flush()Promise finalize()
boolean isPending()boolean isArmed
これは関数ではなく属性
なしboolean iRunning

arm()start() と違って遅延が追加されないとか、finalize()flush() と違って以降 arm() が呼べなくなるとか、細かい違いがあるので、コードを書き換える際には注意が必要です。

let helloTask = new DeferredTask(function() {
  Cu.reportError("Hello");
}, 2000);

// タスクを開始
helloTask.arm();

setTimeout(function() {
  // 1 秒待ってから disarm() を呼ばずにタスクを開始
  helloTask.arm();
}, 1000);

// 2 秒後に Hello と表示される

また、Task.jsm ベースになったので、タスクとしてジェネレータ関数を渡せるようになりました。

// 3 秒後に resolve するなんかイイカンジの関数
let waitThreeSecond = function() {
  let deferred = Promise.defer();
  setTimeout(function() {
    deferred.resolve();
  }, 3000);
  return deferred.promise;
}

let helloTask = new DeferredTask(function*() {
  yield waitThreeSecond();
  Cu.reportError("Hello");
}, 2000);
helloTask.arm();

// 5 秒後に Hello と表示される

この場合、タスク自体は 2 秒後から走り始めているので、3 秒後に arm() を呼んだ場合、これは最初の arm() とまとめられずに、arm() を呼んだ時点ではなくタスクの完了後から 2 秒後に再びタスクが走り始めます。
// 3 秒後に resolve するなんかイイカンジの関数
let waitThreeSecond = function() {
  let deferred = Promise.defer();
  setTimeout(function() {
    deferred.resolve();
  }, 3000);
  return deferred.promise;
}

let helloTask = new DeferredTask(function*() {
  yield waitThreeSecond();
  Cu.reportError("Hello");
}, 2000);
helloTask.arm();

setTimeout(function() {
  // 3 秒待ってからタスクを再度開始
  helloTask.arm();
}, 3000);

// 5 秒後と 10 秒後に Hello と表示され、

2014年1月2日

Nightly での nsIMemoryReporterManager の変更

UnMHT のメモリリークテストを動かしていたところ Nightly でテスト自体がエラーになる事態に、
という事で調べてみると nsIMemoryReporterManager.enumerateReporters が無くなったのでした。
詳細は Bug 947802 にあるようです。
どうやら全部非同期にするための変更らしいですヨ。

新しい方法は nsIMemoryReporterManager.getReports のようで、下のように書くと動きます。

let MemoryReporterManager
  = Cc["@mozilla.org/memory-reporter-manager;1"].
  getService(Ci.nsIMemoryReporterManager);

let handleReport = function(process, path, kind, units, amount,
                            description) {
  // 情報を集めるヤツ
};

let finishReporting = function() {
  // 完了したら呼ばれるヤツ
};

MemoryReporterManager.getReports(handleReport, null,
                                 finishReporting, null);

ちなみにこちらが Firefox 28 までのヤツ。
for (let r in XPCOMUtils.IterSimpleEnumerator(
  MemoryReporterManager.enumerateReporters(), Ci.nsIMemoryReporter)) {
  r.collectReports(handleReport, null);
}

そしてその前 (いつだっけ?) のヤツ。

for (let r in XPCOMUtils.IterSimpleEnumerator(
  MemoryReporterManager.enumerateReporters(), Ci.nsIMemoryReporter)) {
  handleReport(r.process, r.path, r.kind, r.units,
               r.amount, r.description);
}

for (let r in XPCOMUtils.IterSimpleEnumerator(
  MemoryReporterManager.enumerateMultiReporters(),
  Ci.nsIMemoryMultiReporter)) {
  r.collectReports(handleReport, null);
}