<!DOCTYPE html> <!-- Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ --> <html> <head> <meta charset="utf8"> <title></title> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> </head> <body> <script type="application/javascript;version=1.8"> "use strict"; const { utils: Cu } = Components; const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {}); const promise = require("promise"); const EventEmitter = require("devtools/shared/event-emitter"); const { Task } = require("devtools/shared/task"); SimpleTest.waitForExplicitFinish(); testEmitter(); testEmitter({}); Task.spawn(testPromise) .then(null, ok.bind(null, false)) .then(SimpleTest.finish); function testEmitter(aObject) { let emitter; if (aObject) { emitter = aObject; EventEmitter.decorate(emitter); } else { emitter = new EventEmitter(); } ok(emitter, "We have an event emitter"); let beenHere1 = false; let beenHere2 = false; emitter.on("next", next); emitter.emit("next", "abc", "def"); function next(eventName, str1, str2) { is(eventName, "next", "Got event"); is(str1, "abc", "Argument 1 is correct"); is(str2, "def", "Argument 2 is correct"); ok(!beenHere1, "first time in next callback"); beenHere1 = true; emitter.off("next", next); emitter.emit("next"); emitter.once("onlyonce", onlyOnce); emitter.emit("onlyonce"); emitter.emit("onlyonce"); } function onlyOnce() { ok(!beenHere2, "\"once\" listener has been called once"); beenHere2 = true; emitter.emit("onlyonce"); testThrowingExceptionInListener(); } function testThrowingExceptionInListener() { function throwListener() { emitter.off("throw-exception"); throw { toString: () => "foo", stack: "bar", }; } emitter.on("throw-exception", throwListener); emitter.emit("throw-exception"); killItWhileEmitting(); } function killItWhileEmitting() { function c1() { ok(true, "c1 called"); } function c2() { ok(true, "c2 called"); emitter.off("tick", c3); } function c3() { ok(false, "c3 should not be called"); } function c4() { ok(true, "c4 called"); } emitter.on("tick", c1); emitter.on("tick", c2); emitter.on("tick", c3); emitter.on("tick", c4); emitter.emit("tick"); offAfterOnce(); } function offAfterOnce() { let enteredC1 = false; function c1() { enteredC1 = true; } emitter.once("oao", c1); emitter.off("oao", c1); emitter.emit("oao"); ok(!enteredC1, "c1 should not be called"); } } function testPromise() { let emitter = new EventEmitter(); let p = emitter.once("thing"); // Check that the promise is only resolved once event though we // emit("thing") more than once let firstCallbackCalled = false; let check1 = p.then(arg => { is(firstCallbackCalled, false, "first callback called only once"); firstCallbackCalled = true; is(arg, "happened", "correct arg in promise"); return "rval from c1"; }); emitter.emit("thing", "happened", "ignored"); // Check that the promise is resolved asynchronously let secondCallbackCalled = false; let check2 = p.then(arg => { ok(true, "second callback called"); is(arg, "happened", "correct arg in promise"); secondCallbackCalled = true; is(arg, "happened", "correct arg in promise (a second time)"); return "rval from c2"; }); // Shouldn't call any of the above listeners emitter.emit("thing", "trashinate"); // Check that we can still separate events with different names // and that it works with no parameters let pfoo = emitter.once("foo"); let pbar = emitter.once("bar"); let check3 = pfoo.then(arg => { ok(arg === undefined, "no arg for foo event"); return "rval from c3"; }); pbar.then(() => { ok(false, "pbar should not be called"); }); emitter.emit("foo"); is(secondCallbackCalled, false, "second callback not called yet"); return promise.all([ check1, check2, check3 ]).then(args => { is(args[0], "rval from c1", "callback 1 done good"); is(args[1], "rval from c2", "callback 2 done good"); is(args[2], "rval from c3", "callback 3 done good"); }); } </script> </body> </html>