summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/bookmark_manager/js
diff options
context:
space:
mode:
authorarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 22:32:23 +0000
committerarv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-14 22:32:23 +0000
commit4cc5e954e5a7b0c60f88b5461fd953d377ffe5f9 (patch)
tree5a2e69c5caacc2251599c3691ed662e072a28995 /chrome/browser/resources/bookmark_manager/js
parentfdabdc748152405ebdd2f7910ee9d5aebe26588c (diff)
downloadchromium_src-4cc5e954e5a7b0c60f88b5461fd953d377ffe5f9.zip
chromium_src-4cc5e954e5a7b0c60f88b5461fd953d377ffe5f9.tar.gz
chromium_src-4cc5e954e5a7b0c60f88b5461fd953d377ffe5f9.tar.bz2
Bookmark manager: Middle click, Ctrl click, Shift+Control click should open bookmark link in a background tab etc..
BUG=40359 TEST=Middle click on a bookmark link. It should open in a background tab Review URL: http://codereview.chromium.org/1553026 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44560 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources/bookmark_manager/js')
-rw-r--r--chrome/browser/resources/bookmark_manager/js/bmm/bookmarklist.js32
-rw-r--r--chrome/browser/resources/bookmark_manager/js/cr/linkcontroller.js168
-rw-r--r--chrome/browser/resources/bookmark_manager/js/cr/linkcontroller_test.html353
-rw-r--r--chrome/browser/resources/bookmark_manager/js/cr/promise.js50
-rw-r--r--chrome/browser/resources/bookmark_manager/js/cr/promise_test.html30
5 files changed, 600 insertions, 33 deletions
diff --git a/chrome/browser/resources/bookmark_manager/js/bmm/bookmarklist.js b/chrome/browser/resources/bookmark_manager/js/bmm/bookmarklist.js
index a683208..a81ca23 100644
--- a/chrome/browser/resources/bookmark_manager/js/bmm/bookmarklist.js
+++ b/chrome/browser/resources/bookmark_manager/js/bmm/bookmarklist.js
@@ -152,11 +152,10 @@ cr.define('bmm', function() {
handleClick_: function(e) {
var self = this;
- function dispatch(url, kind) {
- var event = self.ownerDocument.createEvent('Event');
- event.initEvent('urlClicked', true, false);
+ function dispatch(url) {
+ var event = new cr.Event('urlClicked', true, false);
event.url = url;
- event.kind = kind;
+ event.originalEvent = e;
self.dispatchEvent(event);
}
@@ -164,8 +163,7 @@ cr.define('bmm', function() {
// Handle clicks on the links to URLs.
if (el.href) {
- dispatch(el.href,
- e.shiftKey ? 'window' : e.button == 1 ? 'tab' : 'self');
+ dispatch(el.href);
// Handle middle click to open bookmark in a new tab.
} else if (e.button == 1) {
@@ -174,7 +172,7 @@ cr.define('bmm', function() {
}
var node = el.bookmarkNode;
if (!bmm.isFolder(node))
- dispatch(node.url, 'tab');
+ dispatch(node.url);
}
},
@@ -460,6 +458,7 @@ cr.define('bmm', function() {
var urlEl = el.childNodes[1];
labelEl.href = urlEl.textContent = bookmarkNode.url;
} else {
+ labelEl.href = '#' + bookmarkNode.id;
el.className = 'folder';
}
}
@@ -470,25 +469,6 @@ cr.define('bmm', function() {
return div;
})();
-
- /**
- * Workaround for http://crbug.com/40902
- * @param {!HTMLElement} list The element to fix the width for.
- */
- function fixListWidth(list) {
- // The width of the list is wrong after its content has changed. Fortunately
- // the reported offsetWidth is correct so we can detect the incorrect width.
- if (list.offsetWidth != list.parentNode.clientWidth - list.offsetLeft) {
- // Set the width to the correct size. This causes the relayout.
- list.style.width = list.parentNode.clientWidth - list.offsetLeft + 'px';
- // Remove the temporary style.width in a timeout. Once the timer fires the
- // size should not change since we already fixed the width.
- window.setTimeout(function() {
- list.style.width = '';
- }, 0);
- }
- }
-
return {
createListItem: createListItem,
BookmarkList: BookmarkList,
diff --git a/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller.js b/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller.js
new file mode 100644
index 0000000..e6241de
--- /dev/null
+++ b/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller.js
@@ -0,0 +1,168 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview This file provides a class that can be used to open URLs based
+ * on user interactions. It ensures a consistent behavior when it comes to
+ * holding down Ctrl and Shift while clicking or activating the a link.
+ *
+ * This depends on the {@code chrome.windows} and {@code chrome.tabs}
+ * extensions API.
+ */
+
+cr.define('cr', function() {
+
+ /**
+ * The kind of link open we want to perform.
+ * @enum {number}
+ */
+ const LinkKind = {
+ FOREGROUND_TAB: 0,
+ BACKGROUND_TAB: 1,
+ WINDOW: 2,
+ SELF: 3,
+ INCOGNITO: 4
+ };
+
+ /**
+ * This class is used to handle opening of links based on user actions. The
+ * following actions are currently implemented:
+ *
+ * * Press Ctrl and click a link. Or click a link with your middle mouse
+ * button (or mousewheel). Or press Enter while holding Ctrl.
+ * Opens the link in a new tab in the background .
+ * * Press Ctrl+Shift and click a link. Or press Shift and click a link with
+ * your middle mouse button (or mousewheel). Or press Enter while holding
+ * Ctrl+Shift.
+ * Opens the link in a new tab and switches to the newly opened tab.
+ * * Press Shift and click a link. Or press Enter while holding Shift.
+ * Opens the link in a new window.
+ *
+ * On Mac, uses Command instead of Ctrl.
+ * For keyboard support you need to use keydown.
+ *
+ * @param {!LocalStrings} localStrings The local strings object which is used
+ * to localize the warning prompt in case the user tries to open a lot of
+ * links.
+ * @constructor
+ */
+ function LinkController(localStrings) {
+ this.localStrings_ = localStrings;
+ }
+
+ LinkController.prototype = {
+ /**
+ * The number of links that can be opened before showing a warning confirm
+ * message.
+ */
+ warningLimit: 15,
+
+ /**
+ * The DOM window that we want to open links into in case we are opening
+ * links in the same window.
+ * @type {!Window}
+ */
+ window: window,
+
+ /**
+ * This method is used for showing the warning confirm message when the
+ * user is trying to open a lot of links.
+ * @param {number} The number of URLs to open.
+ * @return {string} The message to show the user.
+ */
+ getWarningMessage: function(count) {
+ return this.localStrings_.getStringF('should_open_all', count);
+ },
+
+ /**
+ * Open an URL from a mouse or keyboard event.
+ * @param {string} url The URL to open.
+ * @param {!Event} e The event triggering the opening of the URL.
+ */
+ openUrlFromEvent: function(url, e) {
+ // We only support keydown Enter and non right click events.
+ if (e.type == 'keydown') {
+ if(e.keyIdentifier != 'Enter')
+ return;
+ } else if (e.type != 'click' || e.button == 2) {
+ return;
+ }
+
+ var kind;
+ var ctrl = cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey;
+
+ if (e.button == 1 || ctrl) // middle, ctrl or keyboard
+ kind = e.shiftKey ? LinkKind.FOREGROUND_TAB : LinkKind.BACKGROUND_TAB;
+ else // left or keyboard
+ kind = e.shiftKey ? LinkKind.WINDOW : LinkKind.SELF;
+
+ this.openUrls([url], kind);
+ },
+
+
+ /**
+ * Opens a URL in a new tab, window or incognito window.
+ * @param {string} url The URL to open.
+ * @param {LinkKind} kind The kind of open we want to do.
+ */
+ openUrl: function (url, kind) {
+ this.openUrls([url], kind);
+ },
+
+ /**
+ * Opens URLs in new tab, window or incognito mode.
+ * @param {!Array.<string>} urls The URLs to open.
+ * @param {LinkKind} kind The kind of open we want to do.
+ */
+ openUrls: function (urls, kind) {
+ if (urls.length < 1)
+ return;
+
+ if (urls.length > this.warningLimit) {
+ if (!this.window.confirm(this.getWarningMessage(urls.length)))
+ return;
+ }
+
+ // Fix '#124' URLs since opening those in a new window does not work. We
+ // prepend the base URL when we encounter those.
+ var base = this.window.location.href.split('#')[0];
+ urls = urls.map(function(url) {
+ return url[0] == '#' ? base + url : url;
+ });
+
+ var incognito = kind == LinkKind.INCOGNITO;
+ if (kind == LinkKind.WINDOW || incognito) {
+ chrome.windows.create({
+ url: urls[0],
+ incognito: incognito
+ }, function(window) {
+ urls.forEach(function(url, i) {
+ if (i > 0)
+ chrome.tabs.create({
+ url: url,
+ windowId: window.id,
+ selected: false
+ });
+ });
+ });
+ } else if (kind == LinkKind.FOREGROUND_TAB ||
+ kind == LinkKind.BACKGROUND_TAB) {
+ urls.forEach(function(url, i) {
+ chrome.tabs.create({
+ url: url,
+ selected: kind == LinkKind.FOREGROUND_TAB && !i
+ });
+ });
+ } else {
+ this.window.location.href = urls[0];
+ }
+ }
+ };
+
+ // Export
+ return {
+ LinkController: LinkController,
+ LinkKind: LinkKind
+ };
+});
diff --git a/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller_test.html b/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller_test.html
new file mode 100644
index 0000000..eb7ebd5
--- /dev/null
+++ b/chrome/browser/resources/bookmark_manager/js/cr/linkcontroller_test.html
@@ -0,0 +1,353 @@
+<!DOCTYPE html>
+<html>
+<head>
+<!-- TODO(arv): Check in Closue unit tests and make this run as part of the
+ tests -->
+<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
+<script src="../cr.js"></script>
+<script src="linkcontroller.js"></script>
+<script>
+
+goog.require('goog.testing.MockControl');
+goog.require('goog.testing.PropertyReplacer');
+goog.require('goog.testing.jsunit');
+goog.require('goog.testing.mockmatchers');
+
+</script>
+</head>
+<body>
+<script>
+
+var mockControl, propertyReplacer, mockWindow;
+var chrome = chrome || {};
+chrome.tabs = chrome.tabs || {};
+chrome.windows = chrome.windows || {};
+
+var ObjectEqualsMatcher = goog.testing.mockmatchers.ObjectEquals;
+var SaveArgumentMatcher = goog.testing.mockmatchers.SaveArgument;
+
+var MSG = 'MSG';
+var localStrings = {
+ getStringF: function(msg, number) {
+ assertEquals('should_open_all', msg);
+ return MSG + number;
+ }
+};
+
+var URL1 = 'http://chromium.org/';
+var URL2 = '#hash';
+var WINDOW_ID = 'WINDOW_ID';
+
+function setUp() {
+ mockControl = new goog.testing.MockControl;
+ chrome.tabs.create = mockControl.createFunctionMock();
+ chrome.windows.create = mockControl.createFunctionMock();
+
+ propertyReplacer = new goog.testing.PropertyReplacer;
+
+ mockWindow = {
+ confirm: mockControl.createFunctionMock(),
+ location: {
+ get href() {
+ return 'http://www.google.com/';
+ },
+ set href(url) {
+ assertEquals(URL1, url);
+ }
+ }
+ };
+}
+
+function tearDown() {
+ mockControl.$tearDown();
+ propertyReplacer.reset();
+}
+
+function testGetWarningMessage() {
+ var lc = new cr.LinkController(localStrings);
+ var msg = lc.getWarningMessage(10);
+ assertEquals(MSG + 10, msg);
+}
+
+function openUrlFromEventHelper(event, isMac, expectedKind) {
+ var lc = new cr.LinkController(localStrings);
+
+ lc.openUrls = mockControl.createFunctionMock();
+ lc.openUrls([URL1], expectedKind);
+
+ propertyReplacer.set(cr, 'isMac', isMac);
+
+ mockControl.$replayAll();
+
+ lc.openUrlFromEvent(URL1, event);
+
+ mockControl.$verifyAll();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+function testOpenUrlFromEventForegroundTab() {
+ var e = {
+ type: 'click',
+ button: 0,
+ shiftKey: true,
+ ctrlKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.FOREGROUND_TAB);
+}
+
+function testOpenUrlFromEventForegroundTabMac() {
+ var e = {
+ type: 'click',
+ button: 0,
+ shiftKey: true,
+ metaKey: true
+ };
+ openUrlFromEventHelper(e, true, cr.LinkKind.FOREGROUND_TAB);
+}
+
+function testOpenUrlFromEventForegroundTabEnter() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter',
+ shiftKey: true,
+ ctrlKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.FOREGROUND_TAB);
+}
+
+function testOpenUrlFromEventForegroundTabEnterMac() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter',
+ shiftKey: true,
+ metaKey: true
+ };
+ openUrlFromEventHelper(e, true, cr.LinkKind.FOREGROUND_TAB);
+}
+
+function testOpenUrlFromEventForegroundTabMiddleClick() {
+ var e = {
+ type: 'click',
+ button: 1,
+ shiftKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.FOREGROUND_TAB);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+function testOpenUrlFromEventBackgroundTab() {
+ var e = {
+ type: 'click',
+ button: 0,
+ ctrlKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.BACKGROUND_TAB);
+}
+
+function testOpenUrlFromEventBackgroundTabMac() {
+ var e = {
+ type: 'click',
+ button: 0,
+ metaKey: true
+ };
+ openUrlFromEventHelper(e, true, cr.LinkKind.BACKGROUND_TAB);
+}
+
+function testOpenUrlFromEventBackgroundTabEnter() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter',
+ ctrlKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.BACKGROUND_TAB);
+}
+
+function testOpenUrlFromEventBackgroundTabEnterMac() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter',
+ metaKey: true
+ };
+ openUrlFromEventHelper(e, true, cr.LinkKind.BACKGROUND_TAB);
+}
+
+function testOpenUrlFromEventBackgroundTabMiddleClick() {
+ var e = {
+ type: 'click',
+ button: 1
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.BACKGROUND_TAB);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+function testOpenUrlFromEventWindow() {
+ var e = {
+ type: 'click',
+ button: 0,
+ shiftKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.WINDOW);
+}
+
+function testOpenUrlFromEventWindowEnter() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter',
+ shiftKey: true
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.WINDOW);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+function testOpenUrlFromEventSelf() {
+ var e = {
+ type: 'click',
+ button: 0
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.SELF);
+}
+
+function testOpenUrlFromEventSelfEnter() {
+ var e = {
+ type: 'keydown',
+ keyIdentifier: 'Enter'
+ };
+ openUrlFromEventHelper(e, false, cr.LinkKind.SELF);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+function testOpenUrl() {
+ var lc = new cr.LinkController(localStrings);
+ lc.openUrls = mockControl.createFunctionMock();
+
+ lc.openUrls(new ObjectEqualsMatcher([URL1]), cr.LinkKind.SELF);
+ mockControl.$replayAll();
+
+ lc.openUrl(URL1, cr.LinkKind.SELF);
+
+ mockControl.$verifyAll();
+}
+
+/////////////////////////////// OpenUrls //////////////////////////////////////
+
+function testOpenUrlsTooFew() {
+ var lc = new cr.LinkController(localStrings);
+
+ mockControl.$replayAll();
+
+ lc.openUrls([], cr.LinkKind.SELF);
+
+ mockControl.$verifyAll();
+}
+
+
+function testOpenUrlsTooMany() {
+ var lc = new cr.LinkController(localStrings);
+ lc.warningLimit = 9;
+
+ var urls = new Array(lc.warningLimit + 1);
+ lc.window = mockWindow;
+
+ lc.window.confirm('MSG10').$returns(false);
+ mockControl.$replayAll();
+
+ lc.openUrls(urls, cr.LinkKind.SELF);
+
+ mockControl.$verifyAll();
+}
+
+function testOpenUrlsSelf() {
+ var lc = new cr.LinkController(localStrings);
+ lc.window = mockWindow;
+
+ mockControl.$replayAll();
+
+ lc.openUrls([URL1], cr.LinkKind.SELF);
+
+ mockControl.$verifyAll();
+}
+
+function testOpenUrlsForegroundTab() {
+ var lc = new cr.LinkController(localStrings);
+ lc.window = mockWindow;
+
+ chrome.tabs.create(new ObjectEqualsMatcher({url: URL1, selected: true}));
+ chrome.tabs.create(new ObjectEqualsMatcher({
+ url: 'http://www.google.com/#hash',
+ selected: false
+ }));
+
+ mockControl.$replayAll();
+
+ lc.openUrls([URL1, URL2], cr.LinkKind.FOREGROUND_TAB);
+
+ mockControl.$verifyAll();
+}
+
+function testOpenUrlsBackgroundTab() {
+ var lc = new cr.LinkController(localStrings);
+ lc.window = mockWindow;
+
+ chrome.tabs.create(new ObjectEqualsMatcher({url: URL1, selected: false}));
+ chrome.tabs.create(new ObjectEqualsMatcher({
+ url: 'http://www.google.com/#hash',
+ selected: false
+ }));
+
+ mockControl.$replayAll();
+
+ lc.openUrls([URL1, URL2], cr.LinkKind.BACKGROUND_TAB);
+
+ mockControl.$verifyAll();
+}
+
+function testOpenUrlsWindow() {
+ var lc = new cr.LinkController(localStrings);
+ lc.window = mockWindow;
+
+ var callbackMatcher = new SaveArgumentMatcher;
+ chrome.windows.create(new ObjectEqualsMatcher({url: URL1, incognito: false}),
+ callbackMatcher);
+ chrome.tabs.create(new ObjectEqualsMatcher({
+ url: 'http://www.google.com/#hash',
+ windowId: WINDOW_ID,
+ selected: false
+ }));
+
+ mockControl.$replayAll();
+
+ lc.openUrls([URL1, URL2], cr.LinkKind.WINDOW);
+ callbackMatcher.arg({id: WINDOW_ID});
+
+ mockControl.$verifyAll();
+}
+
+function testOpenUrlsIncognito() {
+ var lc = new cr.LinkController(localStrings);
+ lc.window = mockWindow;
+
+ var callbackMatcher = new SaveArgumentMatcher;
+ chrome.windows.create(new ObjectEqualsMatcher({url: URL1, incognito: true}),
+ callbackMatcher);
+ chrome.tabs.create(new ObjectEqualsMatcher({
+ url: 'http://www.google.com/#hash',
+ windowId: WINDOW_ID,
+ selected: false
+ }));
+
+ mockControl.$replayAll();
+
+ lc.openUrls([URL1, URL2], cr.LinkKind.INCOGNITO);
+ callbackMatcher.arg({id: WINDOW_ID});
+
+ mockControl.$verifyAll();
+}
+
+</script>
+</body>
+</html>
diff --git a/chrome/browser/resources/bookmark_manager/js/cr/promise.js b/chrome/browser/resources/bookmark_manager/js/cr/promise.js
index 3e8944f..a9d233a 100644
--- a/chrome/browser/resources/bookmark_manager/js/cr/promise.js
+++ b/chrome/browser/resources/bookmark_manager/js/cr/promise.js
@@ -15,16 +15,20 @@ cr.define('cr', function() {
/**
* Creates a future promise.
- * @param {Function=} opt_callback Callback.
+ * @param {*=} opt_value The value to set the promise to. If set completes
+ * the promise immediately.
* @constructor
*/
- function Promise(opt_callback) {
+ function Promise(opt_value) {
/**
* An array of the callbacks.
* @type {!Array.<!Function>}
* @private
*/
- this.callbacks_ = opt_callback ? [opt_callback] : [];
+ this.callbacks_ = [];
+
+ if (arguments.length > 0)
+ this.value = opt_value;
}
Promise.prototype = {
@@ -133,10 +137,11 @@ cr.define('cr', function() {
/**
* Creates a new future promise that is fulfilled when any of the promises are
- * fulfilled.
+ * fulfilled. The value of the returned promise will be the value of the first
+ * fulfilled promise.
* @param {...!Promise} var_args The promises used to build up the new
* promise.
- * @return {!Promise} The new promise that will be fulfilled when any of th
+ * @return {!Promise} The new promise that will be fulfilled when any of the
* passed in promises are fulfilled.
*/
Promise.any = function(var_args) {
@@ -151,6 +156,41 @@ cr.define('cr', function() {
};
/**
+ * Creates a new future promise that is fulfilled when all of the promises are
+ * fulfilled. The value of the returned promise is an array of the values of
+ * the promises passed in.
+ * @param {...!Promise} var_args The promises used to build up the new
+ * promise.
+ * @return {!Promise} The promise that wraps all the promises in the array.
+ */
+ Promise.all = function(var_args) {
+ var p = new Promise;
+ var args = Array.prototype.slice.call(arguments);
+ var count = args.length;
+ if (!count) {
+ p.value = [];
+ return p;
+ }
+
+ function f(v) {
+ count--;
+ if (!count) {
+ p.value = args.map(function(argP) {
+ return argP.value;
+ });
+ }
+ }
+
+ // Do not use count here since count may be decremented in the call to
+ // addListener if the promise is already done.
+ for (var i = 0; i < args.length; i++) {
+ args[i].addListener(f);
+ }
+
+ return p;
+ };
+
+ /**
* Wraps an event in a future promise.
* @param {!EventTarget} target The object that dispatches the event.
* @param {string} type The type of the event.
diff --git a/chrome/browser/resources/bookmark_manager/js/cr/promise_test.html b/chrome/browser/resources/bookmark_manager/js/cr/promise_test.html
index 19e3d1a..5c9ae1d 100644
--- a/chrome/browser/resources/bookmark_manager/js/cr/promise_test.html
+++ b/chrome/browser/resources/bookmark_manager/js/cr/promise_test.html
@@ -107,9 +107,9 @@ function testCallbacks4() {
calls2++;
assertEquals(V, v);
}
- var p = new Promise(f1);
+ var p = new Promise(V);
+ p.addListener(f1);
p.addListener(f2);
- p.value = V;
assertEquals(1, calls1);
assertEquals(1, calls2);
}
@@ -195,6 +195,32 @@ function testAny() {
assertEquals(2, any.value);
}
+function testAll() {
+ var p1 = new Promise;
+ var p2 = new Promise;
+ var p3 = new Promise;
+
+ var pAll = Promise.all(p1, p2, p3);
+ p1.value = 1;
+ p2.value = 2;
+ p3.value = 3;
+ assertArrayEquals([1, 2, 3], pAll.value);
+}
+
+function testAllEmpty() {
+ var pAll = Promise.all();
+ assertArrayEquals([], pAll.value);
+}
+
+function testAllAlreadyDone() {
+ var p1 = new Promise(1);
+ var p2 = new Promise(2);
+ var p3 = new Promise(3);
+
+ var pAll = Promise.all(p1, p2, p3);
+ assertArrayEquals([1, 2, 3], pAll.value);
+}
+
function testEvent() {
var p = Promise.event(document.body, 'foo');
var e = new cr.Event('foo');