зеркало из https://github.com/mozilla/gecko-dev.git
184 строки
4.7 KiB
JavaScript
184 строки
4.7 KiB
JavaScript
/* 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";
|
|
|
|
const { Loader } = require("sdk/test/loader");
|
|
const { isWeak, WeakReference } = require("sdk/core/reference");
|
|
const { subscribe, unsubscribe,
|
|
observe, Observer } = require("sdk/core/observer");
|
|
const { Class } = require("sdk/core/heritage");
|
|
|
|
const { Cc, Ci, Cu } = require("chrome");
|
|
const { notifyObservers } = Cc["@mozilla.org/observer-service;1"].
|
|
getService(Ci.nsIObserverService);
|
|
const { defer } = require("sdk/core/promise");
|
|
|
|
const message = x => ({wrappedJSObject: x});
|
|
|
|
exports["test subscribe unsubscribe"] = assert => {
|
|
const topic = Date.now().toString(32);
|
|
const Subscriber = Class({
|
|
extends: Observer,
|
|
initialize: function(observe) {
|
|
this.observe = observe;
|
|
}
|
|
});
|
|
observe.define(Subscriber, (x, subject, _, data) =>
|
|
x.observe(subject.wrappedJSObject.x));
|
|
|
|
let xs = [];
|
|
const x = Subscriber((...rest) => xs.push(...rest));
|
|
|
|
let ys = [];
|
|
const y = Subscriber((...rest) => ys.push(...rest));
|
|
|
|
const publish = (topic, data) =>
|
|
notifyObservers(message(data), topic, null);
|
|
|
|
publish({x:0});
|
|
|
|
subscribe(x, topic);
|
|
|
|
publish(topic, {x:1});
|
|
|
|
subscribe(y, topic);
|
|
|
|
publish(topic, {x:2});
|
|
publish(topic + "!", {x: 2.5});
|
|
|
|
unsubscribe(x, topic);
|
|
|
|
publish(topic, {x:3});
|
|
|
|
subscribe(y, topic);
|
|
|
|
publish(topic, {x:4});
|
|
|
|
subscribe(x, topic);
|
|
|
|
publish(topic, {x:5});
|
|
|
|
unsubscribe(x, topic);
|
|
unsubscribe(y, topic);
|
|
|
|
publish(topic, {x:6});
|
|
|
|
assert.deepEqual(xs, [1, 2, 5]);
|
|
assert.deepEqual(ys, [2, 3, 4, 5]);
|
|
}
|
|
|
|
exports["test weak observers are GC-ed on unload"] = (assert, end) => {
|
|
const topic = Date.now().toString(32);
|
|
const loader = Loader(module);
|
|
const { Observer, observe,
|
|
subscribe, unsubscribe } = loader.require("sdk/core/observer");
|
|
const { isWeak, WeakReference } = loader.require("sdk/core/reference");
|
|
|
|
const MyObserver = Class({
|
|
extends: Observer,
|
|
initialize: function(observe) {
|
|
this.observe = observe;
|
|
}
|
|
});
|
|
observe.define(MyObserver, (x, ...rest) => x.observe(...rest));
|
|
|
|
const MyWeakObserver = Class({
|
|
extends: MyObserver,
|
|
implements: [WeakReference]
|
|
});
|
|
|
|
let xs = [];
|
|
let ys = [];
|
|
let x = new MyObserver((subject, topic, data) => {
|
|
xs.push(subject.wrappedJSObject, topic, data);
|
|
});
|
|
let y = new MyWeakObserver((subject, topic, data) => {
|
|
ys.push(subject.wrappedJSObject, topic, data);
|
|
});
|
|
|
|
subscribe(x, topic);
|
|
subscribe(y, topic);
|
|
|
|
|
|
notifyObservers(message({ foo: 1 }), topic, null);
|
|
x = null;
|
|
y = null;
|
|
loader.unload();
|
|
|
|
Cu.schedulePreciseGC(() => {
|
|
|
|
notifyObservers(message({ bar: 2 }), topic, ":)");
|
|
|
|
assert.deepEqual(xs, [{ foo: 1 }, topic, null,
|
|
{ bar: 2 }, topic, ":)"],
|
|
"non week observer is kept");
|
|
|
|
assert.deepEqual(ys, [{ foo: 1 }, topic, null],
|
|
"week observer was GC-ed");
|
|
|
|
end();
|
|
});
|
|
};
|
|
|
|
exports["test weak observer unsubscribe"] = function*(assert) {
|
|
const loader = Loader(module);
|
|
const { Observer, observe, subscribe, unsubscribe } = loader.require("sdk/core/observer");
|
|
const { WeakReference } = loader.require("sdk/core/reference");
|
|
|
|
let sawNotification = false;
|
|
let firstWait = defer();
|
|
let secondWait = defer();
|
|
|
|
const WeakObserver = Class({
|
|
extends: Observer,
|
|
implements: [WeakReference],
|
|
observe: function() {
|
|
sawNotification = true;
|
|
firstWait.resolve();
|
|
}
|
|
});
|
|
|
|
const StrongObserver = Class({
|
|
extends: Observer,
|
|
observe: function() {
|
|
secondWait.resolve();
|
|
}
|
|
});
|
|
|
|
observe.define(Observer, (x, ...rest) => x.observe(...rest));
|
|
|
|
let weakObserver = new WeakObserver;
|
|
let strongObserver = new StrongObserver();
|
|
subscribe(weakObserver, "test-topic");
|
|
subscribe(strongObserver, "test-wait");
|
|
|
|
notifyObservers(null, "test-topic", null);
|
|
yield firstWait.promise;
|
|
|
|
assert.ok(sawNotification, "Should have seen notification before GC");
|
|
sawNotification = false;
|
|
|
|
yield loader.require("sdk/test/memory").gc();
|
|
|
|
notifyObservers(null, "test-topic", null);
|
|
notifyObservers(null, "test-wait", null);
|
|
yield secondWait.promise;
|
|
|
|
assert.ok(sawNotification, "Should have seen notification after GC");
|
|
sawNotification = false;
|
|
|
|
try {
|
|
unsubscribe(weakObserver, "test-topic");
|
|
unsubscribe(strongObserver, "test-wait");
|
|
assert.pass("Should not have seen an exception");
|
|
}
|
|
catch (e) {
|
|
assert.fail("Should not have seen an exception");
|
|
}
|
|
|
|
loader.unload();
|
|
};
|
|
|
|
require("sdk/test").run(exports);
|