Bug 882407 - Uplift addon-sdk to firefox. r=me

This commit is contained in:
Wes Kocher 2013-06-12 13:29:26 -07:00
parent 684cc56c32
commit a7ede0548b
39 changed files with 294 additions and 106 deletions

View File

@ -104,6 +104,14 @@ Exceptions in the listeners can be handled via `'error'` event listeners:
If there is no listener registered for `error` event or if it also throws
exception then such exceptions are logged into a console.
## Chaining
Emitters can also have their methods chained:
target.on('message', handleMessage)
.on('data', parseData)
.on('error', handleError);
<api name="EventTarget">
@class
`EventTarget` is an exemplar for creating an objects that can be used to
@ -131,6 +139,8 @@ specified `type` are emitted.
The type of event.
@param listener {Function}
The listener function that processes the event.
@returns {EventTarget}
Returns the EventTarget instance
</api>
<api name="once">
@ -141,6 +151,8 @@ the next time an event of the specified `type` is emitted.
The type of event.
@param listener {Function}
The listener function that processes the event.
@returns {EventTarget}
Returns the EventTarget instance
</api>
<api name="removeListener">
@ -150,6 +162,13 @@ Removes an event `listener` for the given event `type`.
The type of event.
@param listener {Function}
The listener function that processes the event.
@returns {EventTarget}
Returns the EventTarget instance
</api>
<api name="off">
@method
An alias for [removeListener](modules/sdk/event/target.html#removeListener(type, listener)).
</api>
</api>

View File

@ -286,6 +286,31 @@ of having to set a boolean flag and checking it later.
The wrapped `fn` that can only be executed once.
</api>
<api name="chain">
@function
Creates a version of the input function that will return `this`.
let { chain } = require("sdk/lang/functional");
function Person (age) { this.age = age; }
Person.prototype.happyBirthday = chain(function () this.age++);
let person = new Person(30);
person
.happyBirthday()
.happyBirthday()
.happyBirthday()
console.log(person.age); // 33
@param fn {function}
The function that will be wrapped by the chain function.
@returns {function}
The wrapped function that executes `fn` and returns `this`.
</api>
<api name="cache">
@function
An alias for [once](modules/sdk/lang/functional.html#once(fn)).

View File

@ -70,6 +70,13 @@ method exported by the
panel.show();
## Panel Positioning ##
By default the panel appears in the center of the currently active browser window.
You can position the panel by passing a `position` to the panel's
[constructor](modules/sdk/panel.html#Panel(options)) or to
its [`show()`](modules/sdk/panel.html#show(options)) method.
## Updating Panel Content ##
You can update the panel's content simply by setting the panel's `contentURL`
@ -425,23 +432,23 @@ Creates a panel.
The position of the panel.
Ignored if the panel is opened by a widget.
You can set as value an object that has one or more of the following
properites: `top`, `right`, `bottom` and `left`. Their values are expressed
This is an object that has one or more of the following
properties: `top`, `right`, `bottom` and `left`. Their values are expressed
in pixels. Any other properties will be ignored.
The default alignment is centered, so for example panel can be displayed in
the center of the bottom corner by leaving off vertical axis:
The default alignment along each axis is centered: so to display a panel centred
along the vertical or horizontal axis, just omit that axis:
// Show the panel to the centered horizontally and aligned to the bottom
// of the content area
// Show the panel centered horizontally and
// aligned to the bottom of the content area
require("sdk/panel").Panel({
position: {
bottom: 0
}
}).show();
// Show the panel to the centered vertically and aligned to the left o
// the content area
// Show the panel centered vertically and
// aligned to the left of the content area
require("sdk/panel").Panel({
position: {
left: 0
@ -451,11 +458,13 @@ Creates a panel.
// Centered panel, default behavior
require("sdk/panel").Panel({}).show();
In the same way of their CSS counterpart, setting both `top` and `bottom`,
or `left` and `right`, will results in calculated the `height` and `width`:
As with the CSS `top`, `bottom`, `left`, and `right` properties, setting
both `top` and `bottom` or both `left` and `right` will implicitly set the
panel's `height` or `width` relative to the content window:
// Show the panel centered horizontally, that is distant 40px
// from the top and 100px from the bottom.
// Show the panel centered horizontally, with:
// - the top edge 40px from the top of the content window
// - the bottom edge 100px from the bottom of the content window
require("sdk/panel").Panel({
position: {
top: 40,
@ -463,11 +472,13 @@ Creates a panel.
}
}).show();
Set implicitly `height` in this example, will makes the panel ignore the
`bottom` property, as the CSS homonym properties does:
If you set both `top` and `bottom`, but also set the panel's height
explicitly using the `height` property, then the panel will ignore
`bottom`, just as CSS does for its properties with the same name:
// Show the panel centered horizontally, that is distant 40px from the top
// and has 400px as height
// Show the panel centered horizontally, with:
// - the top edge 40px from the top of the content window
// - a height of 400px
require("sdk/panel").Panel({
position: {
top: 40,
@ -485,7 +496,8 @@ Creates a panel.
height: 400
}).show();
The same principle is applied for `width`, `left` and `right`.
The same principle is applied in the horizontal axis with
`width`, `left` and `right`.
@prop [focus=true] {boolean}
Set to `false` to prevent taking the focus away when the panel is shown.
@ -644,8 +656,10 @@ Displays the panel.
If the `options` argument is given, it will be shallow merged with the options
provided in the constructor: the `options` passed in the `show` method takes
the precedence.
It's useful for temporary changes, without touching the default values.
precedence.
Passing options here is useful for making temporary changes without touching
the default values.
@param options {object}
Showing options for the panel, with the following keys:

View File

@ -2,12 +2,12 @@
* 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/. */
var widgets = require('widget');
var pageMod = require('page-mod');
var data = require('self').data;
var panels = require('panel');
var simpleStorage = require('simple-storage');
var notifications = require("notifications");
var widgets = require('sdk/widget');
var pageMod = require('sdk/page-mod');
var data = require('sdk/self').data;
var panels = require('sdk/panel');
var simpleStorage = require('sdk/simple-storage');
var notifications = require("sdk/notifications");
/*
Global variables
@ -188,7 +188,7 @@ in the browser.
this.postMessage(simpleStorage.storage.annotations);
},
onMessage: function(message) {
require('tabs').open(message);
require('sdk/tabs').open(message);
}
});

View File

@ -2,11 +2,11 @@
* 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/. */
const tabs = require('tabs');
const widgets = require('widget');
const data = require('self').data;
const pageMod = require('page-mod');
const panel = require('panel');
const tabs = require('sdk/tabs');
const widgets = require('sdk/widget');
const data = require('sdk/self').data;
const pageMod = require('sdk/page-mod');
const panel = require('sdk/panel');
const ICON_WIDTH = 16;

View File

@ -2,9 +2,9 @@
* 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/. */
var self = require("self");
var panels = require("addon-kit/panel");
var widgets = require("addon-kit/widget");
var self = require("sdk/self");
var panels = require("sdk/panel");
var widgets = require("sdk/widget");
function replaceMom(html) {
return html.replace("World", "Mom");

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var m = require("main");
var self = require("self");
var self = require("sdk/self");
exports.testReplace = function(test) {
var input = "Hello World";

View File

@ -2,9 +2,9 @@
* 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/. */
var data = require("self").data;
var data = require("sdk/self").data;
var reddit_panel = require("panel").Panel({
var reddit_panel = require("sdk/panel").Panel({
width: 240,
height: 320,
contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
@ -13,10 +13,10 @@ var reddit_panel = require("panel").Panel({
});
reddit_panel.port.on("click", function(url) {
require("tabs").open(url);
require("sdk/tabs").open(url);
});
require("widget").Widget({
require("sdk/widget").Widget({
id: "open-reddit-btn",
label: "Reddit",
contentURL: "http://www.reddit.com/static/favicon.ico",

View File

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var m = require("main");
var self = require("self");
var self = require("sdk/self");
exports.testMain = function(test) {
var callbacks = { quit: function() {

View File

@ -205,17 +205,17 @@ Object.defineProperties(exports, {
*/
exports.getInnerId = deprecateFunction(getInnerId,
'require("window-utils").getInnerId is deprecated, ' +
'please use require("window/utils").getInnerId instead'
'please use require("sdk/window/utils").getInnerId instead'
);
exports.getOuterId = deprecateFunction(getOuterId,
'require("window-utils").getOuterId is deprecated, ' +
'please use require("window/utils").getOuterId instead'
'please use require("sdk/window/utils").getOuterId instead'
);
exports.isBrowser = deprecateFunction(isBrowser,
'require("window-utils").isBrowser is deprecated, ' +
'please use require("window/utils").isBrowser instead'
'please use require("sdk/window/utils").isBrowser instead'
);
exports.hiddenWindow = appShellService.hiddenDOMWindow;

View File

@ -11,7 +11,7 @@ module.metadata = {
};
const { on, once, off, setListeners } = require('./core');
const { method } = require('../lang/functional');
const { method, chain } = require('../lang/functional');
const { Class } = require('../core/heritage');
/**
@ -45,7 +45,7 @@ const EventTarget = Class({
* console.log('data received: ' + data)
* })
*/
on: method(on),
on: chain(method(on)),
/**
* Registers an event `listener` that is called once the next time an event
* of the specified `type` is emitted.
@ -54,7 +54,7 @@ const EventTarget = Class({
* @param {Function} listener
* The listener function that processes the event.
*/
once: method(once),
once: chain(method(once)),
/**
* Removes an event `listener` for the given event `type`.
* @param {String} type
@ -68,9 +68,11 @@ const EventTarget = Class({
// than intended. This way we make sure all arguments are passed and only
// one listener is removed at most.
off(this, type, listener);
return this;
},
off: function(type, listener) {
off(this, type, listener)
off(this, type, listener);
return this;
}
});
exports.EventTarget = EventTarget;

View File

@ -42,6 +42,17 @@ exports.defer = defer;
// Exporting `remit` alias as `defer` may conflict with promises.
exports.remit = defer;
/*
* Takes a funtion and returns a wrapped function that returns `this`
*/
function chain(f) {
return function chainable(...args) {
f.apply(this, args);
return this;
};
}
exports.chain = chain;
/**
* Invokes `callee` by passing `params` as an arguments and `self` as `this`
* pseudo-variable. Returns value that is returned by a callee.

View File

@ -73,7 +73,8 @@ exports.isPrivate = function(thing) {
function deprecateEvents(func) deprecateEvent(
func,
'The require("private-browsing") module\'s "start" and "stop" events are deprecated.',
'The require("sdk/private-browsing") module\'s "start" and "stop" events ' +
'are deprecated.',
['start', 'stop']
);

View File

@ -80,8 +80,9 @@ let setMode = defer(function setMode(value) {
});
exports.setMode = deprecateFunction(
setMode,
'require("private-browsing").activate and require("private-browsing").deactivate ' +
'is deprecated.'
'require("sdk/private-browsing").activate and ' +
'require("sdk/private-browsing").deactivate ' +
'are deprecated.'
);
let getMode = function getMode(chromeWin) {

View File

@ -12,22 +12,27 @@ const { isPrivateBrowsingSupported } = require('sdk/self');
const supportPrivateTabs = isPrivateBrowsingSupported && isWindowPBSupported;
function newTabWindow(options) {
// `tabs` option is under review and may be removed.
return windows.open({
tabs: [ options ],
isPrivate: options.isPrivate
});
}
Object.defineProperties(tabs, {
open: { value: function open(options) {
if (options.inNewWindow) {
// `tabs` option is under review and may be removed.
windows.open({
tabs: [ options ],
isPrivate: options.isPrivate
});
newTabWindow(options);
return undefined;
}
// Open in active window if new window was not required.
let activeWindow = windows.activeWindow;
let privateState = !!options.isPrivate;
// if the active window is in the state that we need then use it
if (!supportPrivateTabs || privateState === isPrivate(activeWindow)) {
if (activeWindow && (!supportPrivateTabs || privateState === isPrivate(activeWindow))) {
activeWindow.tabs.open(options);
}
else {
@ -38,10 +43,7 @@ Object.defineProperties(tabs, {
}
// open a window in the state that we need
else {
windows.open({
tabs: [ options ],
isPrivate: options.isPrivate
});
newTabWindow(options);
}
}

View File

@ -257,9 +257,9 @@ function cleanup() {
// dump the coverobject
if (Object.keys(coverObject).length){
const self = require('self');
const self = require('sdk/self');
const {pathFor} = require("sdk/system");
let file = require('file');
let file = require('sdk/io/file');
const {env} = require('sdk/system/environment');
console.log("CWD:", env.PWD);
let out = file.join(env.PWD,'coverstats-'+self.id+'.json');

View File

@ -14,7 +14,7 @@ const { EventTarget } = require('../event/target');
const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
const { deprecateUsage } = require('../util/deprecate');
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("tabs") instead';
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
const BrowserWindow = Class({
initialize: function initialize(options) {
@ -41,7 +41,7 @@ const BrowserWindow = Class({
get isPrivateBrowsing() {
deprecateUsage('`browserWindow.isPrivateBrowsing` is deprecated, please ' +
'consider using ' +
'`require("private-browsing").isPrivate(browserWindow)` ' +
'`require("sdk/private-browsing").isPrivate(browserWindow)` ' +
'instead.');
return isWindowPrivate(windowNS(this).window);
}

View File

@ -29,7 +29,7 @@ const WindowDom = Trait.compose({
get isPrivateBrowsing() {
deprecateUsage('`browserWindow.isPrivateBrowsing` is deprecated, please ' +
'consider using ' +
'`require("private-browsing").isPrivate(browserWindow)` ' +
'`require("sdk/private-browsing").isPrivate(browserWindow)` ' +
'instead.');
return isWindowPrivate(this._window);
}

View File

@ -13,7 +13,7 @@ const { method } = require('../lang/functional');
const { EventTarget } = require('../event/target');
const { List, addListItem } = require('../util/list');
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("tabs") instead';
const ERR_FENNEC_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
// NOTE: On Fennec there is only one window.

View File

@ -407,7 +407,7 @@ class ManifestBuilder:
# populate the self.modules[] cache. Note that we must
# tolerate cycles in the reference graph.
looked_in = [] # populated by subroutines
them_me = self.find_req_for(mi, reqname, looked_in)
them_me = self.find_req_for(mi, reqname, looked_in, locations)
if them_me is None:
if mi.section == "tests":
# tolerate missing modules in tests, because
@ -428,7 +428,7 @@ class ManifestBuilder:
return me
#print "LEAVING", pkg.name, mi.name
def find_req_for(self, from_module, reqname, looked_in):
def find_req_for(self, from_module, reqname, looked_in, locations):
# handle a single require(reqname) statement from from_module .
# Return a uri that exists in self.manifest
# Populate looked_in with places we looked.
@ -513,8 +513,21 @@ class ManifestBuilder:
normalized = normalized[len("api-utils/"):]
if normalized in NEW_LAYOUT_MAPPING:
# get the new absolute path for this module
original_reqname = reqname
reqname = NEW_LAYOUT_MAPPING[normalized]
from_pkg = from_module.package.name
# If the addon didn't explicitely told us to ignore deprecated
# require path, warn the developer:
# (target_cfg is the package.json file)
if not "ignore-deprecated-path" in self.target_cfg:
lineno = locations.get(original_reqname)
print >>self.stderr, "Warning: Use of deprecated require path:"
print >>self.stderr, " In %s:%d:" % (from_module.js, lineno)
print >>self.stderr, " require('%s')." % original_reqname
print >>self.stderr, " New path should be:"
print >>self.stderr, " require('%s')" % reqname
return self._search_packages_for_module(from_pkg,
lookfor_sections, reqname,
looked_in)

View File

@ -6,10 +6,10 @@ const { Cc, Ci } = require("chrome");
exports.main = function(options, callbacks) {
// Close Firefox window. Firefox should quit.
require("api-utils/window-utils").activeBrowserWindow.close();
require("sdk/deprecated/window-utils").activeBrowserWindow.close();
// But not on Mac where it stay alive! We have to request application quit.
if (require("api-utils/runtime").OS == "Darwin") {
if (require("sdk/system/runtime").OS == "Darwin") {
let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].
getService(Ci.nsIAppStartup);
appStartup.quit(appStartup.eAttemptQuit);

View File

@ -2,7 +2,7 @@
* 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/. */
var panel = require("panel");
var panel = require("sdk/panel");
var two = require("two.js");
var a = require("./two");
var b = require("sdk/tabs.js");

View File

@ -2,5 +2,5 @@
* 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/. */
var self = require("self"); // trigger inclusion of data
var self = require("sdk/self"); // trigger inclusion of data
exports.main = function () { console.log("main"); };

View File

@ -4,5 +4,5 @@
exports.main = 42;
require("./subdir/subfile");
require("self"); // trigger inclusion of our data/ directory
require("sdk/self"); // trigger inclusion of our data/ directory

View File

@ -48,7 +48,7 @@ class Basic(unittest.TestCase):
def assertReqIs(modname, reqname, path):
reqs = m["one/%s" % modname]["requirements"]
self.failUnlessEqual(reqs[reqname], path)
assertReqIs("main", "panel", "sdk/panel")
assertReqIs("main", "sdk/panel", "sdk/panel")
assertReqIs("main", "two.js", "one/two")
assertReqIs("main", "./two", "one/two")
assertReqIs("main", "sdk/tabs.js", "sdk/tabs")

View File

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const xulApp = require("xul-app");
const { PageMod } = require("page-mod");
const tabs = require("tabs");
const xulApp = require("sdk/system/xul-app");
const { PageMod } = require("sdk/page-mod");
const tabs = require("sdk/tabs");
exports.testCrossDomainIframe = function(assert, done) {
let serverPort = 8099;

View File

@ -1,3 +1,4 @@
{
"id": "test-layout-change"
"id": "test-layout-change",
"ignore-deprecated-path": true
}

View File

@ -7,7 +7,7 @@ const { defer } = require('sdk/core/promise');
const BROWSER = 'chrome://browser/content/browser.xul';
exports.testRequirePanel = function(assert) {
require('panel');
require('sdk/panel');
assert.ok('the panel module should not throw an error');
};

View File

@ -1,4 +1,5 @@
{
"id": "test-require",
"packages": "packages"
"packages": "packages",
"ignore-deprecated-path": true
}

View File

@ -9,6 +9,7 @@ const { open: openPromise, close, focus, promise } = require('sdk/window/helpers
const { isPrivate } = require('sdk/private-browsing');
const { browserWindows: windows } = require('sdk/windows');
const { defer } = require('sdk/core/promise');
const tabs = require('sdk/tabs');
// test openDialog() from window/utils with private option
// test isActive state in pwpb case
@ -90,7 +91,42 @@ exports.testIsPrivateOnWindowOpenFromPrivate = function(assert, done) {
return promise;
}).then(close).
then(done, assert.fail);
}
};
exports.testOpenTabWithPrivateWindow = function(assert, done) {
function start() {
openPromise(null, {
features: {
private: true,
toolbar: true
}
}).then(focus).then(function(window) {
let { promise, resolve } = defer();
assert.equal(isPrivate(window), true, 'the focused window is private');
tabs.open({
url: 'about:blank',
onOpen: function(tab) {
assert.equal(isPrivate(tab), false, 'the opened tab is not private');
// not closing this tab on purpose.. for now...
// we keep this tab open because we closed all windows
// and must keep a non-private window open at end of this test for next ones.
resolve(window);
}
});
return promise;
}).then(close).then(done, assert.fail);
}
(function closeWindows() {
if (windows.length > 0) {
return windows.activeWindow.close(closeWindows);
}
assert.pass('all pre test windows have been closed');
return start();
})()
};
exports.testIsPrivateOnWindowOff = function(assert, done) {
windows.open({

View File

@ -12,7 +12,7 @@ const { curry, identity, partial } = require("sdk/lang/functional");
let when = curry(function(options, tab) {
let type = options.type || options;
let capture = options.captuer || false;
let capture = options.capture || false;
let target = getBrowserForTab(tab);
let { promise, resolve } = defer();
@ -42,8 +42,12 @@ exports["test multiple tabs"] = function(assert, done) {
let { on, off } = loader.require("sdk/event/core");
let actual = [];
on(events, "data", function({type, target, timeStamp}) {
// ignore about:blank pages.
if (target.URL !== "about:blank") actual.push(type + " -> " + target.URL)
// ignore about:blank pages and *-document-global-created
// events that are not very consistent.
if (target.URL !== "about:blank" &&
type !== "chrome-document-global-created" &&
type !== "content-document-global-created")
actual.push(type + " -> " + target.URL)
});
let window = getMostRecentBrowserWindow();
@ -80,8 +84,12 @@ exports["test nested frames"] = function(assert, done) {
let { on, off } = loader.require("sdk/event/core");
let actual = [];
on(events, "data", function({type, target, timeStamp}) {
// ignore about:blank pages.
if (target.URL !== "about:blank") actual.push(type + " -> " + target.URL)
// ignore about:blank pages and *-global-created
// events that are not very consistent.
if (target.URL !== "about:blank" &&
type !== "chrome-document-global-created" &&
type !== "content-document-global-created")
actual.push(type + " -> " + target.URL)
});
let window = getMostRecentBrowserWindow();
@ -93,7 +101,6 @@ exports["test nested frames"] = function(assert, done) {
then(function() {
assert.deepEqual(actual, [
"document-element-inserted -> " + uri,
"content-document-global-created -> data:text/html,iframe",
"DOMContentLoaded -> " + uri,
"document-element-inserted -> data:text/html,iframe",
"DOMContentLoaded -> data:text/html,iframe",

View File

@ -115,13 +115,11 @@ exports["test disposables are GC-able"] = function(assert, done) {
let foo1 = null
let foo2 = null
Cu.forceGC();
setTimeout(function() {
Cu.forceGC();
Cu.schedulePreciseGC(function() {
loader.unload();
assert.equal(disposals, 0, "GC removed dispose listeners");
done();
}, 300);
});
}

View File

@ -163,5 +163,43 @@ exports['test unhandled errors'] = function(assert) {
'error in error handler is logged');
};
exports['test target is chainable'] = function (assert, done) {
let loader = Loader(module);
let exceptions = [];
let { EventTarget } = loader.require('sdk/event/target');
let { emit } = loader.require('sdk/event/core');
Object.defineProperties(loader.sandbox('sdk/event/core'), {
console: { value: {
exception: function(e) {
exceptions.push(e);
}
}}
});
let emitter = EventTarget();
let boom = Error('Boom');
let onceCalled = 0;
emitter.once('oneTime', function () {
assert.equal(++onceCalled, 1, 'once event called only once');
}).on('data', function (message) {
assert.equal(message, 'message', 'handles event');
emit(emitter, 'oneTime');
emit(emitter, 'data2', 'message2');
}).on('phony', function () {
assert.fail('removeListener does not remove chained event');
}).removeListener('phony')
.on('data2', function (message) {
assert.equal(message, 'message2', 'handle chained event');
emit(emitter, 'oneTime');
throw boom;
}).on('error', function (error) {
assert.equal(error, boom, 'error handled in chained event');
done();
});
emit(emitter, 'data', 'message');
};
require('test').run(exports);

View File

@ -5,7 +5,7 @@
const { setTimeout } = require('sdk/timers');
const utils = require('sdk/lang/functional');
const { invoke, defer, partial, compose, memoize, once, delay, wrap, curry } = utils;
const { invoke, defer, partial, compose, memoize, once, delay, wrap, curry, chain } = utils;
const { LoaderWithHookedConsole } = require('sdk/test/loader');
exports['test forwardApply'] = function(assert) {
@ -180,4 +180,19 @@ exports['test once'] = function(assert) {
assert.equal(target.state, 1, 'this was passed in and called only once');
};
exports['test chain'] = function (assert) {
let Player = function () { this.volume = 5; };
Player.prototype = {
setBand: chain(function (band) this.band = band),
incVolume: chain(function () this.volume++)
};
let player = new Player();
player
.setBand('Animals As Leaders')
.incVolume().incVolume().incVolume().incVolume().incVolume().incVolume();
assert.equal(player.band, 'Animals As Leaders', 'passes arguments into chained');
assert.equal(player.volume, 11, 'accepts no arguments in chain');
};
require('test').run(exports);

View File

@ -14,11 +14,10 @@ exports["test post GC references"] = function (assert, done) {
assert.equal(local(target).there, true, "namespaced preserved");
setTimeout(function() {
Cu.forceGC();
Cu.schedulePreciseGC(function() {
assert.equal(local(target).there, true, "namespace is preserved post GC");
done();
}, 300);
});
};
exports["test namsepace basics"] = function(assert) {

View File

@ -159,9 +159,7 @@ function hideAndShowFrame(window) {
iframe.style.display = "none";
Cu.forceGC();
setTimeout(function() {
Cu.schedulePreciseGC(function() {
events.on("document-shown", function shown(event) {
if (iframe.contentWindow !== event.subject.defaultView)
return;
@ -171,7 +169,7 @@ function hideAndShowFrame(window) {
}, true);
iframe.style.display = "";
}, 0)
});
return promise;
}

View File

@ -6,7 +6,7 @@ const events = require("sdk/system/events");
const self = require("sdk/self");
const { Cc, Ci, Cu } = require("chrome");
const { setTimeout } = require("sdk/timers");
const { LoaderWithHookedConsole2 } = require("sdk/test/loader");
const { Loader, LoaderWithHookedConsole2 } = require("sdk/test/loader");
const nsIObserverService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
@ -64,7 +64,10 @@ exports["test error reporting"] = function(assert) {
exports["test listeners are GC-ed"] = function(assert, done) {
let receivedFromWeak = [];
let receivedFromStrong = [];
let type = Date.now().toString(32);
let loader = Loader(module);
let events = loader.require('sdk/system/events');
let type = 'test-listeners-are-garbage-collected';
function handler(event) { receivedFromStrong.push(event); }
function weakHandler(event) { receivedFromWeak.push(event); }
@ -77,14 +80,15 @@ exports["test listeners are GC-ed"] = function(assert, done) {
handler = weakHandler = null;
Cu.forceGC();
setTimeout(function() {
Cu.forceGC();
Cu.schedulePreciseGC(function() {
events.emit(type, { data: 2 });
assert.equal(receivedFromWeak.length, 1, "weak listener was GC-ed");
assert.equal(receivedFromStrong.length, 2, "strong listener was invoked");
loader.unload();
done();
}, 300);
});
};
exports["test handle nsIObserverService notifications"] = function(assert) {

View File

@ -10,7 +10,7 @@ const WM = Cc['@mozilla.org/appshell/window-mediator;1'].
getService(Ci.nsIWindowMediator);
const { browserWindows } = require('sdk/windows');
const ERR_MSG = 'This method is not yet supported by Fennec, consider using require("tabs") instead';
const ERR_MSG = 'This method is not yet supported by Fennec, consider using require("sdk/tabs") instead';
// TEST: browserWindows.length for Fennec
exports.testBrowserWindowsLength = function(test) {

View File

@ -181,6 +181,8 @@ exports.testOnOpenOnCloseListeners = function(test) {
});
};
/*
Disabled due to all of the Win8 PGO bustage in bug 873007.
exports.testActiveWindow = function(test) {
const xulApp = require("sdk/system/xul-app");
if (xulApp.versionInRange(xulApp.platformVersion, "1.9.2", "1.9.2.*")) {
@ -283,6 +285,7 @@ exports.testActiveWindow = function(test) {
});
}
};
*/
exports.testTrackWindows = function(test) {
test.waitUntilDone();