merge mozilla-central to b2g-inbound on a CLOSED TREE
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
JS build system changes are apparently requiring clobbers.
|
||||
Bug 948583, first part, apparently requires a clobber. (Ideas for fixing this involve removing jsopcode.tbl, which is a bit too big to do while holding up this patch.)
|
||||
|
|
|
@ -778,7 +778,7 @@ PrefCache.prototype = {
|
|||
this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) {
|
||||
this.value = aOptions.defaultValue;
|
||||
let runCallback = () => {
|
||||
if (aCallback && aOptions.callbackNow) {
|
||||
if (aCallback) {
|
||||
aCallback(aName, this.value);
|
||||
if (aOptions.callbackOnce) {
|
||||
runCallback = () => {};
|
||||
|
@ -788,7 +788,9 @@ this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) {
|
|||
|
||||
let settings = Utils.win.navigator.mozSettings;
|
||||
if (!settings) {
|
||||
runCallback();
|
||||
if (aOptions.callbackNow) {
|
||||
runCallback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -798,7 +800,9 @@ this.SettingCache = function SettingCache(aName, aCallback, aOptions = {}) {
|
|||
|
||||
req.addEventListener('success', () => {
|
||||
this.value = req.result[aName] == undefined ? aOptions.defaultValue : req.result[aName];
|
||||
runCallback();
|
||||
if (aOptions.callbackNow) {
|
||||
runCallback();
|
||||
}
|
||||
});
|
||||
|
||||
settings.addObserver(aName,
|
||||
|
|
|
@ -34,8 +34,12 @@ var FeedHandler = {
|
|||
return false;
|
||||
}
|
||||
|
||||
while (container.firstChild)
|
||||
container.removeChild(container.firstChild);
|
||||
for (let i = container.childNodes.length - 1; i >= 0; --i) {
|
||||
let node = container.childNodes[i];
|
||||
if (isSubview && node.localName == "label")
|
||||
continue;
|
||||
container.removeChild(node);
|
||||
}
|
||||
|
||||
if (!feeds || feeds.length <= 1)
|
||||
return false;
|
||||
|
|
|
@ -283,7 +283,13 @@ let gSyncUI = {
|
|||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject;
|
||||
if (xps.fxAccountsEnabled) {
|
||||
switchToTabHavingURI("about:accounts", true);
|
||||
fxAccounts.getSignedInUser().then(userData => {
|
||||
if (userData) {
|
||||
this.openPrefs();
|
||||
} else {
|
||||
switchToTabHavingURI("about:accounts", true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("Weave:AccountSetup");
|
||||
if (win)
|
||||
|
|
|
@ -123,7 +123,9 @@
|
|||
|
||||
<panelview id="PanelUI-socialapi" flex="1"/>
|
||||
|
||||
<panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);"></panelview>
|
||||
<panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
|
||||
<label value="&feedsMenu.label;" class="panel-subview-header"/>
|
||||
</panelview>
|
||||
|
||||
<panelview id="PanelUI-helpView" flex="1">
|
||||
<label value="&helpMenu.label;" class="panel-subview-header"/>
|
||||
|
|
|
@ -84,11 +84,11 @@
|
|||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.addObserver(this, "browser-search-engine-modified", false);
|
||||
|
||||
this._addedObserver = true;
|
||||
this._initialized = true;
|
||||
|
||||
this.searchService.init((function search_init_cb(aStatus) {
|
||||
// Bail out if the binding's been destroyed
|
||||
if (this._destroyed)
|
||||
if (!this._initialized)
|
||||
return;
|
||||
|
||||
if (Components.isSuccessCode(aStatus)) {
|
||||
|
@ -101,13 +101,12 @@
|
|||
]]></constructor>
|
||||
|
||||
<destructor><![CDATA[
|
||||
this._destroyed = true;
|
||||
if (this._initialized) {
|
||||
this._initialized = false;
|
||||
|
||||
if (this._addedObserver) {
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(this, "browser-search-engine-modified");
|
||||
this._addedObserver = false;
|
||||
}
|
||||
|
||||
// Make sure to break the cycle from _textbox to us. Otherwise we leak
|
||||
|
|
|
@ -5,7 +5,7 @@ whitelist = {
|
|||
'nightly': {},
|
||||
}
|
||||
|
||||
all_platforms = ['win32', 'linux32', 'linux64', 'macosx-universal']
|
||||
all_platforms = ['win64', 'win32', 'linux32', 'linux64', 'macosx-universal']
|
||||
|
||||
for platform in all_platforms:
|
||||
whitelist['nightly'][platform] = [
|
||||
|
@ -19,7 +19,7 @@ for platform in ['linux32', 'linux64', 'macosx-universal']:
|
|||
'mk_add_options MOZ_MAKE_FLAGS="-j4"',
|
||||
]
|
||||
|
||||
for platform in ['linux32', 'linux64', 'macosx-universal', 'win32']:
|
||||
for platform in ['linux32', 'linux64', 'macosx-universal', 'win32', 'win64']:
|
||||
whitelist['nightly'][platform] += ['ac_add_options --enable-signmar']
|
||||
whitelist['nightly'][platform] += ['ac_add_options --enable-js-diagnostics']
|
||||
|
||||
|
@ -62,6 +62,10 @@ whitelist['nightly']['win32'] += [
|
|||
'fi',
|
||||
'ac_add_options --enable-metro',
|
||||
]
|
||||
whitelist['nightly']['win64'] += [
|
||||
'. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"',
|
||||
'ac_add_options --enable-metro',
|
||||
]
|
||||
|
||||
for platform in all_platforms:
|
||||
whitelist['release'][platform] = [
|
||||
|
@ -71,6 +75,8 @@ for platform in all_platforms:
|
|||
'export BUILDING_RELEASE=1',
|
||||
]
|
||||
whitelist['release']['win32'] += ['mk_add_options MOZ_PGO=1']
|
||||
whitelist['release']['win64'] += ['mk_add_options MOZ_PGO=1']
|
||||
|
||||
whitelist['release']['linux32'] += [
|
||||
'export MOZILLA_OFFICIAL=1',
|
||||
'export MOZ_TELEMETRY_REPORTING=1',
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
mk_add_options MOZ_PGO=1
|
||||
|
||||
ac_add_options --enable-official-branding
|
||||
. $topsrcdir/build/win64/mozconfig.vs2010
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# This make file should be identical to the beta mozconfig, apart from the
|
||||
# safeguard below
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-win64"
|
||||
. "$topsrcdir/browser/config/mozconfigs/win64/common-opt"
|
||||
|
||||
mk_add_options MOZ_PGO=1
|
||||
|
@ -9,5 +10,6 @@ ac_add_options --enable-official-branding
|
|||
# safeguard against someone forgetting to re-set EARLY_BETA_OR_EARLIER in
|
||||
# defines.sh during the beta cycle
|
||||
export BUILDING_RELEASE=1
|
||||
. $topsrcdir/build/win64/mozconfig.vs2010
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
|
|
@ -11,9 +11,9 @@ const {Cc, Ci, Cu} = require("chrome");
|
|||
let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
|
||||
let Heritage = require("sdk/core/heritage");
|
||||
|
||||
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
|
||||
loader.lazyGetter(this, "Telemetry", () => require("devtools/shared/telemetry"));
|
||||
loader.lazyGetter(this, "WebConsoleFrame", () => require("devtools/webconsole/webconsole").WebConsoleFrame);
|
||||
loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
|
||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
||||
loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm");
|
||||
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
|
||||
|
@ -110,7 +110,6 @@ HUD_SERVICE.prototype =
|
|||
function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow)
|
||||
{
|
||||
let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow);
|
||||
this._browserConsoleID = hud.hudId;
|
||||
this.consoles.set(hud.hudId, hud);
|
||||
return hud.init();
|
||||
},
|
||||
|
@ -242,6 +241,7 @@ HUD_SERVICE.prototype =
|
|||
connect().then(getTarget).then(openWindow).then((aWindow) => {
|
||||
this.openBrowserConsole(target, aWindow, aWindow)
|
||||
.then((aBrowserConsole) => {
|
||||
this._browserConsoleID = aBrowserConsole.hudId;
|
||||
this._browserConsoleDefer.resolve(aBrowserConsole);
|
||||
this._browserConsoleDefer = null;
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
|
||||
loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
|
||||
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
|
||||
loader.lazyGetter(this, "HUDService", () => require("devtools/webconsole/hudservice"));
|
||||
loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
|
||||
|
||||
|
|
|
@ -49,10 +49,7 @@ function test()
|
|||
EventUtils.synthesizeKey(c, {}, hud.iframeWindow);
|
||||
}
|
||||
|
||||
hud.jsterm.execute(null, () => {
|
||||
// executeSoon() is needed to get out of the execute() event loop.
|
||||
executeSoon(onReadProperty.bind(null, msg));
|
||||
});
|
||||
hud.jsterm.execute(null, onReadProperty.bind(null, msg));
|
||||
}
|
||||
|
||||
function onReadProperty(deadObjectMessage)
|
||||
|
@ -72,7 +69,6 @@ function test()
|
|||
|
||||
function onFetched()
|
||||
{
|
||||
ok(true, "variables view fetched");
|
||||
hud.jsterm.execute("delete window.foobarzTezt; 2013-26", onCalcResult);
|
||||
}
|
||||
|
||||
|
|
|
@ -95,24 +95,37 @@ function testGen() {
|
|||
testNext();
|
||||
};
|
||||
EventUtils.synthesizeKey("VK_END", {});
|
||||
yield undefined;
|
||||
yield;
|
||||
|
||||
let oldScrollTop = scrollBox.scrollTop;
|
||||
|
||||
content.console.log("test message 151");
|
||||
|
||||
scrollBox.onscroll = () => {
|
||||
if (scrollBox.scrollTop == oldScrollTop) {
|
||||
// Wait for scroll to change.
|
||||
return;
|
||||
}
|
||||
scrollBox.onscroll = null;
|
||||
isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)");
|
||||
hud = testDriver = null;
|
||||
finishTest();
|
||||
};
|
||||
waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "test message 151",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
}).then(() => {
|
||||
scrollBox.onscroll = () => {
|
||||
if (scrollBox.scrollTop == oldScrollTop) {
|
||||
// Wait for scroll to change.
|
||||
return;
|
||||
}
|
||||
scrollBox.onscroll = null;
|
||||
isnot(scrollBox.scrollTop, oldScrollTop, "scroll location updated (moved to bottom again)");
|
||||
testNext();
|
||||
};
|
||||
});
|
||||
|
||||
yield undefined;
|
||||
|
||||
hud = testDriver = null;
|
||||
finishTest();
|
||||
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
let WebConsoleUtils, TargetFactory, require;
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
(() => {
|
||||
|
|
|
@ -14,7 +14,7 @@ loader.lazyServiceGetter(this, "clipboardHelper",
|
|||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
|
||||
loader.lazyImporter(this, "promise", "resource://gre/modules/Promise.jsm", "Promise");
|
||||
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
|
||||
loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
|
||||
loader.lazyGetter(this, "AutocompletePopup",
|
||||
() => require("devtools/shared/autocomplete-popup").AutocompletePopup);
|
||||
|
|
|
@ -129,6 +129,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY shareSelectCmd.accesskey "s">
|
||||
<!ENTITY shareVideoCmd.label "Share This Video">
|
||||
<!ENTITY shareVideoCmd.accesskey "s">
|
||||
<!ENTITY feedsMenu.label "Subscribe">
|
||||
<!ENTITY subscribeToPageMenupopup.label "Subscribe to This Page">
|
||||
<!ENTITY subscribeToPageMenuitem.label "Subscribe to This Page…">
|
||||
<!ENTITY addCurPagesCmd.label "Bookmark All Tabs…">
|
||||
|
|
|
@ -161,11 +161,6 @@ var BrowserUI = {
|
|||
Util.dumpLn("Exception in delay load module:", ex.message);
|
||||
}
|
||||
|
||||
if (WindowsPrefSync) {
|
||||
// Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
|
||||
WindowsPrefSync.init();
|
||||
}
|
||||
|
||||
// check for left over crash reports and submit them if found.
|
||||
BrowserUI.startupCrashCheck();
|
||||
|
||||
|
|
|
@ -185,8 +185,7 @@ var Browser = {
|
|||
// Should we restore the previous session (crash or some other event)
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"]
|
||||
.getService(Ci.nsISessionStore);
|
||||
let shouldRestore = ss.shouldRestore()
|
||||
|| (3 == Services.prefs.getIntPref("browser.startup.page"));
|
||||
let shouldRestore = ss.shouldRestore();
|
||||
if (shouldRestore) {
|
||||
let bringFront = false;
|
||||
// First open any commandline URLs, except the homepage
|
||||
|
|
|
@ -9,6 +9,7 @@ const Cr = Components.results;
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
|
||||
|
@ -199,6 +200,10 @@ SessionStore.prototype = {
|
|||
break;
|
||||
case "final-ui-startup":
|
||||
observerService.removeObserver(this, "final-ui-startup");
|
||||
if (WindowsPrefSync) {
|
||||
// Pulls in Desktop controlled prefs and pushes out Metro controlled prefs
|
||||
WindowsPrefSync.init();
|
||||
}
|
||||
this.init();
|
||||
break;
|
||||
case "domwindowopened":
|
||||
|
@ -340,9 +345,12 @@ SessionStore.prototype = {
|
|||
this._lastSaveTime = Date.now();
|
||||
|
||||
// Nothing to restore, notify observers things are complete
|
||||
if (!this._shouldRestore) {
|
||||
if (!this.shouldRestore()) {
|
||||
this._clearCache();
|
||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored", "");
|
||||
|
||||
// If nothing is being restored, we only have our single Metro window.
|
||||
this._orderedWindows.push(aWindow.__SSID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,7 +734,7 @@ SessionStore.prototype = {
|
|||
},
|
||||
|
||||
shouldRestore: function ss_shouldRestore() {
|
||||
return this._shouldRestore;
|
||||
return this._shouldRestore || (3 == Services.prefs.getIntPref("browser.startup.page"));
|
||||
},
|
||||
|
||||
restoreLastSession: function ss_restoreLastSession(aBringToFront) {
|
||||
|
|
|
@ -34,7 +34,7 @@ if test -d "$1"; then
|
|||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL")
|
||||
fi
|
||||
$2
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust)
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust $ac_sub_configure)
|
||||
])
|
||||
|
||||
define([AC_OUTPUT_SUBDIRS],
|
||||
|
|
|
@ -18,6 +18,14 @@ class File(object):
|
|||
stat = os.stat(path)
|
||||
self._times = (stat.st_atime, stat.st_mtime)
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
@property
|
||||
def mtime(self):
|
||||
return self._times[1]
|
||||
|
||||
def update_time(self):
|
||||
'''If the file hasn't changed since the instance was created,
|
||||
restore its old modification time.'''
|
||||
|
@ -97,7 +105,7 @@ def dump(dump_file, shell):
|
|||
pickle.dump(config_files, f)
|
||||
|
||||
|
||||
def adjust(dump_file):
|
||||
def adjust(dump_file, configure):
|
||||
if not os.path.exists(dump_file):
|
||||
return
|
||||
|
||||
|
@ -110,6 +118,11 @@ def adjust(dump_file):
|
|||
pass
|
||||
|
||||
for f in config_files:
|
||||
# Still touch config.status if configure is newer than its original
|
||||
# mtime.
|
||||
if configure and os.path.basename(f.path) == 'config.status' and \
|
||||
os.path.getmtime(configure) > f.mtime:
|
||||
continue
|
||||
f.update_time()
|
||||
|
||||
os.remove(dump_file)
|
||||
|
@ -121,4 +134,4 @@ if __name__ == '__main__':
|
|||
if sys.argv[1] == 'dump':
|
||||
dump(CONFIG_DUMP, sys.argv[2])
|
||||
elif sys.argv[1] == 'adjust':
|
||||
adjust(CONFIG_DUMP)
|
||||
adjust(CONFIG_DUMP, sys.argv[2] if len(sys.argv) > 2 else None)
|
||||
|
|
|
@ -1158,6 +1158,10 @@ arm*)
|
|||
mips|mipsel)
|
||||
CPU_ARCH="mips"
|
||||
;;
|
||||
|
||||
aarch64*)
|
||||
CPU_ARCH=aarch64
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$OS_TARGET"; then
|
||||
|
|
|
@ -160,25 +160,6 @@ nsJSUtils::CompileFunction(JSContext* aCx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS AutoDontReportUncaught {
|
||||
JSContext* mContext;
|
||||
bool mWasSet;
|
||||
|
||||
public:
|
||||
AutoDontReportUncaught(JSContext* aContext) : mContext(aContext) {
|
||||
MOZ_ASSERT(aContext);
|
||||
mWasSet = JS::ContextOptionsRef(mContext).dontReportUncaught();
|
||||
if (!mWasSet) {
|
||||
JS::ContextOptionsRef(mContext).setDontReportUncaught(true);
|
||||
}
|
||||
}
|
||||
~AutoDontReportUncaught() {
|
||||
if (!mWasSet) {
|
||||
JS::ContextOptionsRef(mContext).setDontReportUncaught(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
const nsAString& aScript,
|
||||
|
|
|
@ -90,6 +90,25 @@ public:
|
|||
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS AutoDontReportUncaught {
|
||||
JSContext* mContext;
|
||||
bool mWasSet;
|
||||
|
||||
public:
|
||||
AutoDontReportUncaught(JSContext* aContext) : mContext(aContext) {
|
||||
MOZ_ASSERT(aContext);
|
||||
mWasSet = JS::ContextOptionsRef(mContext).dontReportUncaught();
|
||||
if (!mWasSet) {
|
||||
JS::ContextOptionsRef(mContext).setDontReportUncaught(true);
|
||||
}
|
||||
}
|
||||
~AutoDontReportUncaught() {
|
||||
if (!mWasSet) {
|
||||
JS::ContextOptionsRef(mContext).setDontReportUncaught(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class nsDependentJSString : public nsDependentString
|
||||
{
|
||||
|
|
|
@ -151,7 +151,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
|
|||
mCx = cx;
|
||||
|
||||
// Make sure the JS engine doesn't report exceptions we want to re-throw
|
||||
if (mExceptionHandling == eRethrowContentExceptions ||
|
||||
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
|
||||
mExceptionHandling == eRethrowExceptions) {
|
||||
mSavedJSContextOptions = JS::ContextOptionsRef(cx);
|
||||
JS::ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
|
|
|
@ -610,14 +610,238 @@ Promise::Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback)
|
|||
return Then(resolveCb, aRejectCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* The CountdownHolder class encapsulates Promise.all countdown functions and
|
||||
* the countdown holder parts of the Promises spec. It maintains the result
|
||||
* array and AllResolveHandlers use SetValue() to set the array indices.
|
||||
*/
|
||||
class CountdownHolder MOZ_FINAL : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CountdownHolder)
|
||||
|
||||
CountdownHolder(const GlobalObject& aGlobal, Promise* aPromise, uint32_t aCountdown)
|
||||
: mPromise(aPromise), mCountdown(aCountdown)
|
||||
{
|
||||
MOZ_ASSERT(aCountdown != 0);
|
||||
JSContext* cx = aGlobal.GetContext();
|
||||
JSAutoCompartment ac(cx, aGlobal.Get());
|
||||
mValues = JS_NewArrayObject(cx, aCountdown, nullptr);
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
~CountdownHolder()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
void SetValue(uint32_t index, const JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
MOZ_ASSERT(mCountdown > 0);
|
||||
|
||||
JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
|
||||
JSAutoCompartment ac(cx, mValues);
|
||||
|
||||
{
|
||||
AutoDontReportUncaught silenceReporting(cx);
|
||||
if (!JS_DefineElement(cx, mValues, index, aValue, nullptr, nullptr, JSPROP_ENUMERATE)) {
|
||||
MOZ_ASSERT(JS_IsExceptionPending(cx));
|
||||
JS::Rooted<JS::Value> exn(cx);
|
||||
JS_GetPendingException(cx, &exn);
|
||||
|
||||
mPromise->MaybeReject(cx, exn);
|
||||
}
|
||||
}
|
||||
|
||||
--mCountdown;
|
||||
if (mCountdown == 0) {
|
||||
JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*mValues));
|
||||
mPromise->MaybeResolve(cx, result);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
uint32_t mCountdown;
|
||||
JS::Heap<JSObject*> mValues;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(CountdownHolder)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(CountdownHolder)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CountdownHolder)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CountdownHolder)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CountdownHolder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mValues)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CountdownHolder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CountdownHolder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
||||
tmp->mValues = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
/**
|
||||
* An AllResolveHandler is the per-promise part of the Promise.all() algorithm.
|
||||
* Every Promise in the handler is handed an instance of this as a resolution
|
||||
* handler and it sets the relevant index in the CountdownHolder.
|
||||
*/
|
||||
class AllResolveHandler MOZ_FINAL : public PromiseNativeHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(AllResolveHandler)
|
||||
|
||||
AllResolveHandler(CountdownHolder* aHolder, uint32_t aIndex)
|
||||
: mCountdownHolder(aHolder), mIndex(aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aHolder);
|
||||
}
|
||||
|
||||
~AllResolveHandler()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ResolvedCallback(JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
mCountdownHolder->SetValue(mIndex, aValue);
|
||||
}
|
||||
|
||||
void
|
||||
RejectedCallback(JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
// Should never be attached to Promise as a reject handler.
|
||||
MOZ_ASSERT(false, "AllResolveHandler should never be attached to a Promise's reject handler!");
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<CountdownHolder> mCountdownHolder;
|
||||
uint32_t mIndex;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AllResolveHandler)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AllResolveHandler)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AllResolveHandler)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseNativeHandler)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_1(AllResolveHandler, mCountdownHolder)
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::All(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
||||
window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (aIterable.Length() == 0) {
|
||||
JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0, nullptr));
|
||||
if (!empty) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return nullptr;
|
||||
}
|
||||
Optional<JS::Handle<JS::Value>> optValue(aCx, JS::ObjectValue(*empty));
|
||||
return Promise::Resolve(aGlobal, aCx, optValue, aRv);
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(window);
|
||||
nsRefPtr<CountdownHolder> holder =
|
||||
new CountdownHolder(aGlobal, promise, aIterable.Length());
|
||||
|
||||
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
|
||||
|
||||
for (uint32_t i = 0; i < aIterable.Length(); ++i) {
|
||||
Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
|
||||
nsRefPtr<Promise> nextPromise = Promise::Cast(aGlobal, aCx, optValue, aRv);
|
||||
|
||||
MOZ_ASSERT(!aRv.Failed());
|
||||
|
||||
nsRefPtr<PromiseNativeHandler> resolveHandler =
|
||||
new AllResolveHandler(holder, i);
|
||||
|
||||
nsRefPtr<PromiseCallback> resolveCb =
|
||||
new NativePromiseCallback(resolveHandler, Resolved);
|
||||
// Every promise gets its own resolve callback, which will set the right
|
||||
// index in the array to the resolution value.
|
||||
nextPromise->AppendCallbacks(resolveCb, rejectCb);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::Cast(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
|
||||
{
|
||||
// If a Promise was passed, just return it.
|
||||
JS::Rooted<JS::Value> value(aCx, aValue.WasPassed() ? aValue.Value() :
|
||||
JS::UndefinedValue());
|
||||
if (value.isObject()) {
|
||||
JS::Rooted<JSObject*> valueObj(aCx, &value.toObject());
|
||||
Promise* nextPromise;
|
||||
nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsRefPtr<Promise> addRefed = nextPromise;
|
||||
return addRefed.forget();
|
||||
}
|
||||
}
|
||||
|
||||
return Promise::Resolve(aGlobal, aCx, aValue, aRv);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::Race(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Sequence<JS::Value>& aIterable, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
||||
window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(window);
|
||||
nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(promise);
|
||||
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
|
||||
|
||||
for (uint32_t i = 0; i < aIterable.Length(); ++i) {
|
||||
Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
|
||||
nsRefPtr<Promise> nextPromise = Promise::Cast(aGlobal, aCx, optValue, aRv);
|
||||
// According to spec, Cast can throw, but our implementation never does.
|
||||
// Remove this when subclassing is supported.
|
||||
MOZ_ASSERT(!aRv.Failed());
|
||||
nextPromise->AppendCallbacks(resolveCb, rejectCb);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
void
|
||||
Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
|
||||
{
|
||||
nsRefPtr<PromiseCallback> resolveCb =
|
||||
new NativePromiseCallback(aRunnable, Resolved);
|
||||
new NativePromiseCallback(aRunnable, Resolved);
|
||||
|
||||
nsRefPtr<PromiseCallback> rejectCb =
|
||||
new NativePromiseCallback(aRunnable, Rejected);
|
||||
new NativePromiseCallback(aRunnable, Rejected);
|
||||
|
||||
AppendCallbacks(resolveCb, rejectCb);
|
||||
}
|
||||
|
@ -657,7 +881,7 @@ Promise::RunTask()
|
|||
{
|
||||
MOZ_ASSERT(mState != Pending);
|
||||
|
||||
nsTArray<nsRefPtr<PromiseCallback> > callbacks;
|
||||
nsTArray<nsRefPtr<PromiseCallback>> callbacks;
|
||||
callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
|
||||
: mRejectCallbacks);
|
||||
mResolveCallbacks.Clear();
|
||||
|
@ -756,6 +980,7 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||
mResolvePending = true;
|
||||
|
||||
if (aValue.isObject()) {
|
||||
AutoDontReportUncaught silenceReporting(aCx);
|
||||
JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
|
||||
|
||||
// Thenables.
|
||||
|
@ -856,6 +1081,13 @@ Promise::RunResolveTask(JS::Handle<JS::Value> aValue,
|
|||
return;
|
||||
}
|
||||
|
||||
// Promise.all() or Promise.race() implementations will repeatedly call
|
||||
// Resolve/RejectInternal rather than using the Maybe... forms. Stop SetState
|
||||
// from asserting.
|
||||
if (mState != Pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetResult(aValue);
|
||||
SetState(aState);
|
||||
RunTask();
|
||||
|
|
|
@ -90,6 +90,20 @@ public:
|
|||
already_AddRefed<Promise>
|
||||
Catch(const Optional<nsRefPtr<AnyCallback>>& aRejectCallback);
|
||||
|
||||
// FIXME(nsm): Bug 956197
|
||||
static already_AddRefed<Promise>
|
||||
All(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Cast(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
|
||||
|
||||
// FIXME(nsm): Bug 956197
|
||||
static already_AddRefed<Promise>
|
||||
Race(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
|
||||
|
||||
void AppendNativeHandler(PromiseNativeHandler* aRunnable);
|
||||
|
||||
private:
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
[test_bug883683.html]
|
||||
[test_promise.html]
|
||||
[test_promise_utils.html]
|
||||
[test_resolve.html]
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Promise.all, Promise.cast, Promise.race</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
function promiseUtilitiesDefined() {
|
||||
ok(Promise.all, "Promise.all must be defined when Promise is enabled.");
|
||||
ok(Promise.cast, "Promise.cast must be defined when Promise is enabled.");
|
||||
ok(Promise.race, "Promise.race must be defined when Promise is enabled.");
|
||||
runTest();
|
||||
}
|
||||
|
||||
function promiseAllEmptyArray() {
|
||||
var p = Promise.all([]);
|
||||
ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
|
||||
p.then(function(values) {
|
||||
ok(Array.isArray(values), "Resolved value should be an array.");
|
||||
is(values.length, 0, "Resolved array length should match iterable's length.");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseAllArray() {
|
||||
var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
|
||||
ok(p instanceof Promise, "Return value of Promise.all should be a Promise.");
|
||||
p.then(function(values) {
|
||||
ok(Array.isArray(values), "Resolved value should be an array.");
|
||||
is(values.length, 3, "Resolved array length should match iterable's length.");
|
||||
is(values[0], 1, "Array values should match.");
|
||||
ok(values[1] instanceof Date, "Array values should match.");
|
||||
is(values[2], "firefox", "Array values should match.");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseAllWaitsForAllPromises() {
|
||||
var arr = [
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 1), 50);
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 2), 10);
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, new Promise(function(resolve2) {
|
||||
resolve2(3);
|
||||
})), 10);
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 4), 20);
|
||||
})
|
||||
];
|
||||
|
||||
var p = Promise.all(arr);
|
||||
p.then(function(values) {
|
||||
ok(Array.isArray(values), "Resolved value should be an array.");
|
||||
is(values.length, 4, "Resolved array length should match iterable's length.");
|
||||
is(values[0], 1, "Array values should match.");
|
||||
is(values[1], 2, "Array values should match.");
|
||||
is(values[2], 3, "Array values should match.");
|
||||
is(values[3], 4, "Array values should match.");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "Promise.all shouldn't fail when iterable has no rejected Promises.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseAllRejectFails() {
|
||||
var arr = [
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 1), 50);
|
||||
}),
|
||||
new Promise(function(resolve, reject) {
|
||||
setTimeout(reject.bind(undefined, 2), 10);
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 3), 10);
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve.bind(undefined, 4), 20);
|
||||
})
|
||||
];
|
||||
|
||||
var p = Promise.all(arr);
|
||||
p.then(function(values) {
|
||||
ok(false, "Promise.all shouldn't resolve when iterable has rejected Promises.");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(true, "Promise.all should reject when iterable has rejected Promises.");
|
||||
is(e, 2, "Rejection value should match.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseAllCastError() {
|
||||
var p = Promise.all([Promise.resolve(2), { then: function() { foo(); } }]);
|
||||
ok(p instanceof Promise, "Should cast to a Promise.");
|
||||
p.then(function(v) {
|
||||
ok(false, "promiseAllCastError: should've rejected.");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(e instanceof ReferenceError, "promiseCastThenableError");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
// Check that the resolved array is enumerable.
|
||||
function promiseAllEnumerable() {
|
||||
var p = Promise.all([1, new Date(), Promise.resolve("firefox")]);
|
||||
p.then(function(v) {
|
||||
var count = 0;
|
||||
for (key in v) {
|
||||
++count;
|
||||
ok(v[key] === 1 || v[key] instanceof Date || v[key] === "firefox",
|
||||
"Enumerated properties don't match.");
|
||||
}
|
||||
is(count, 3, "Resolved array from Promise.all should be enumerable");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(false, "promiseAllEnumerable: should've resolved.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCastNoArg() {
|
||||
var p = Promise.cast();
|
||||
ok(p instanceof Promise, "Should cast to a Promise.");
|
||||
p.then(function(v) {
|
||||
is(v, undefined, "Resolved value should be undefined.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCastInteger() {
|
||||
var p = Promise.cast(5);
|
||||
ok(p instanceof Promise, "Should cast to a Promise.");
|
||||
p.then(function(v) {
|
||||
is(v, 5, "Resolved value should match original.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCastArray() {
|
||||
var p = Promise.cast([1,2,3]);
|
||||
ok(p instanceof Promise, "Should cast to a Promise.");
|
||||
p.then(function(v) {
|
||||
ok(Array.isArray(v), "Resolved value should be an Array");
|
||||
is(v.length, 3, "Length should match");
|
||||
is(v[0], 1, "Resolved value should match original");
|
||||
is(v[1], 2, "Resolved value should match original");
|
||||
is(v[2], 3, "Resolved value should match original");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCastThenable() {
|
||||
var p = Promise.cast({ then: function(resolve) { resolve(2); } });
|
||||
ok(p instanceof Promise, "Should cast to a Promise.");
|
||||
p.then(function(v) {
|
||||
is(v, 2, "Should resolve to 2.");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(false, "promiseCastThenable should've resolved");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCastPromise() {
|
||||
var original = Promise.resolve(true);
|
||||
var cast = Promise.cast(original);
|
||||
|
||||
ok(cast instanceof Promise, "Should cast to a Promise.");
|
||||
is(cast, original, "Should return original Promise.");
|
||||
runTest();
|
||||
}
|
||||
|
||||
function promiseRaceEmpty() {
|
||||
var p = Promise.race([]);
|
||||
ok(p instanceof Promise, "Should return a Promise.");
|
||||
p.then(function() {
|
||||
ok(false, "Should not resolve");
|
||||
}, function() {
|
||||
ok(false, "Should not reject");
|
||||
});
|
||||
// Per spec, An empty race never resolves or rejects.
|
||||
setTimeout(function() {
|
||||
ok(true);
|
||||
runTest();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
function promiseRaceValuesArray() {
|
||||
var p = Promise.race([true, new Date(), 3]);
|
||||
ok(p instanceof Promise, "Should return a Promise.");
|
||||
p.then(function(winner) {
|
||||
is(winner, true, "First value should win.");
|
||||
runTest();
|
||||
}, function(err) {
|
||||
ok(false, "Should not fail " + err + ".");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseRacePromiseArray() {
|
||||
function timeoutPromise(n) {
|
||||
return new Promise(function(resolve) {
|
||||
setTimeout(function() {
|
||||
resolve(n);
|
||||
}, n);
|
||||
});
|
||||
}
|
||||
|
||||
var arr = [
|
||||
timeoutPromise(50),
|
||||
timeoutPromise(20),
|
||||
timeoutPromise(30),
|
||||
timeoutPromise(100)
|
||||
];
|
||||
|
||||
var p = Promise.race(arr);
|
||||
p.then(function(winner) {
|
||||
is(winner, 20, "Fastest timeout should win.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseRaceReject() {
|
||||
var p = Promise.race([
|
||||
Promise.reject(new Error("Fail bad!")),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve, 0);
|
||||
})
|
||||
]);
|
||||
|
||||
p.then(function() {
|
||||
ok(false, "Should not resolve when winning Promise rejected.");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(true, "Should be rejected");
|
||||
ok(e instanceof Error, "Should reject with Error.");
|
||||
ok(e.message == "Fail bad!", "Message should match.");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseRaceThrow() {
|
||||
var p = Promise.race([
|
||||
new Promise(function(resolve) {
|
||||
nonExistent();
|
||||
}),
|
||||
new Promise(function(resolve) {
|
||||
setTimeout(resolve, 0);
|
||||
})
|
||||
]);
|
||||
|
||||
p.then(function() {
|
||||
ok(false, "Should not resolve when winning Promise had an error.");
|
||||
runTest();
|
||||
}, function(e) {
|
||||
ok(true, "Should be rejected");
|
||||
ok(e instanceof ReferenceError, "Should reject with ReferenceError for function nonExistent().");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [
|
||||
promiseUtilitiesDefined,
|
||||
promiseAllEmptyArray,
|
||||
promiseAllArray,
|
||||
promiseAllWaitsForAllPromises,
|
||||
promiseAllRejectFails,
|
||||
promiseAllCastError,
|
||||
promiseAllEnumerable,
|
||||
|
||||
promiseCastNoArg,
|
||||
promiseCastInteger,
|
||||
promiseCastArray,
|
||||
promiseCastThenable,
|
||||
promiseCastPromise,
|
||||
|
||||
promiseRaceEmpty,
|
||||
promiseRaceValuesArray,
|
||||
promiseRacePromiseArray,
|
||||
promiseRaceReject,
|
||||
promiseRaceThrow,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
test();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -33,4 +33,13 @@ interface Promise {
|
|||
|
||||
[NewObject]
|
||||
Promise catch(optional AnyCallback? rejectCallback);
|
||||
|
||||
[NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
|
||||
static Promise all(sequence<any> iterable);
|
||||
|
||||
[NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
|
||||
static Promise cast(optional any value);
|
||||
|
||||
[NewObject, Throws, Func="mozilla::dom::Promise::EnabledForScope"]
|
||||
static Promise race(sequence<any> iterable);
|
||||
};
|
||||
|
|
|
@ -876,8 +876,7 @@ void ReportLoadError(JSContext* aCx, const nsAString& aURL,
|
|||
break;
|
||||
|
||||
default:
|
||||
JS_ReportError(aCx, "Failed to load script: %s (nsresult = 0x%x)",
|
||||
url.get(), aLoadResult);
|
||||
JS_ReportError(aCx, "Failed to load script (nsresult = 0x%x)", aLoadResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -391,7 +391,6 @@ protected:
|
|||
gfx::DrawTarget*
|
||||
BorrowDrawTargetForQuadrantUpdate(const nsIntRect& aBounds,
|
||||
ContextSource aSource);
|
||||
void ReturnDrawTarget(gfx::DrawTarget* aReturned);
|
||||
|
||||
static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ BasicThebesLayer::Validate(LayerManager::DrawThebesLayerCallback aCallback,
|
|||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
|
||||
Mutated();
|
||||
ctx = nullptr;
|
||||
mContentClient->ReturnDrawTarget(target);
|
||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||
|
||||
RenderTraceInvalidateEnd(this, "FFFF00");
|
||||
} else {
|
||||
|
|
|
@ -70,7 +70,7 @@ ClientThebesLayer::PaintThebes()
|
|||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PaintThebes", this));
|
||||
Mutated();
|
||||
ctx = nullptr;
|
||||
mContentClient->ReturnDrawTarget(target);
|
||||
mContentClient->ReturnDrawTargetToBuffer(target);
|
||||
} else {
|
||||
// It's possible that state.mRegionToInvalidate is nonempty here,
|
||||
// if we are shrinking the valid region to nothing. So use mRegionToDraw
|
||||
|
|
|
@ -656,7 +656,7 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
|
|||
if (isClippingCheap) {
|
||||
destDT->PopClip();
|
||||
}
|
||||
ReturnDrawTarget(destDT);
|
||||
ReturnDrawTargetToBuffer(destDT);
|
||||
|
||||
if (aSource.HaveBufferOnWhite()) {
|
||||
MOZ_ASSERT(HaveBufferOnWhite());
|
||||
|
@ -675,7 +675,7 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
|
|||
if (isClippingCheap) {
|
||||
destDT->PopClip();
|
||||
}
|
||||
ReturnDrawTarget(destDT);
|
||||
ReturnDrawTargetToBuffer(destDT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,7 +895,7 @@ DeprecatedContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer
|
|||
if (isClippingCheap) {
|
||||
destDT->PopClip();
|
||||
}
|
||||
ReturnDrawTarget(destDT);
|
||||
ReturnDrawTargetToBuffer(destDT);
|
||||
|
||||
if (aSource.HaveBufferOnWhite()) {
|
||||
MOZ_ASSERT(HaveBufferOnWhite());
|
||||
|
@ -914,7 +914,7 @@ DeprecatedContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer
|
|||
if (isClippingCheap) {
|
||||
destDT->PopClip();
|
||||
}
|
||||
ReturnDrawTarget(destDT);
|
||||
ReturnDrawTargetToBuffer(destDT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
uint32_t aFlags) = 0;
|
||||
virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
|
||||
const RotatedContentBuffer::PaintState& aPaintState) = 0;
|
||||
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) = 0;
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
|
||||
|
||||
virtual void PrepareFrame() {}
|
||||
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
|
||||
}
|
||||
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ public:
|
|||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
|
||||
}
|
||||
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ public:
|
|||
{
|
||||
return RotatedContentBuffer::BorrowDrawTargetForPainting(aLayer, aPaintState);
|
||||
}
|
||||
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ public:
|
|||
uint32_t aFlags) MOZ_OVERRIDE;
|
||||
virtual gfx::DrawTarget* BorrowDrawTargetForPainting(ThebesLayer* aLayer,
|
||||
const PaintState& aPaintState) MOZ_OVERRIDE;
|
||||
virtual void ReturnDrawTarget(gfx::DrawTarget* aReturned) MOZ_OVERRIDE
|
||||
virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE
|
||||
{
|
||||
BorrowDrawTarget::ReturnDrawTarget(aReturned);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
float APZCTreeManager::sDPI = 72.0;
|
||||
float APZCTreeManager::sDPI = 160.0;
|
||||
|
||||
APZCTreeManager::APZCTreeManager()
|
||||
: mTreeLock("APZCTreeLock"),
|
||||
|
|
|
@ -140,7 +140,7 @@ static bool gTouchActionPropertyEnabled = false;
|
|||
* accidentally processing taps as touch moves, and from very short/accidental
|
||||
* touches moving the screen.
|
||||
*/
|
||||
static float gTouchStartTolerance = 1.0f/2.0f;
|
||||
static float gTouchStartTolerance = 1.0f/4.5f;
|
||||
|
||||
/**
|
||||
* Default touch behavior (is used when not touch behavior is set).
|
||||
|
|
|
@ -574,7 +574,7 @@ struct JSClass {
|
|||
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
||||
// previously allowed, but is now an ES5 violation and thus unsupported.
|
||||
//
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 29)
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 30)
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
|
|
|
@ -556,10 +556,8 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
#if 0 /* pending addressing Firebug's use of this method */
|
||||
if (!GlobalObject::warnOnceAboutWatch(cx, obj))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if (args.length() <= 1) {
|
||||
js_ReportMissingArg(cx, args.calleev(), 1);
|
||||
|
@ -595,10 +593,8 @@ obj_unwatch(JSContext *cx, unsigned argc, Value *vp)
|
|||
if (!obj)
|
||||
return false;
|
||||
|
||||
#if 0 /* pending addressing Firebug's use of this method */
|
||||
if (!GlobalObject::warnOnceAboutWatch(cx, obj))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
RootedId id(cx);
|
||||
if (args.length() != 0) {
|
||||
|
|
|
@ -970,6 +970,11 @@ arm*)
|
|||
mips|mipsel)
|
||||
CPU_ARCH="mips"
|
||||
;;
|
||||
|
||||
aarch64*)
|
||||
CPU_ARCH=aarch64
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
if test -z "$OS_TARGET"; then
|
||||
|
|
|
@ -5918,6 +5918,16 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
}
|
||||
|
||||
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
/* Handle __proto__ specially because it's not binary. */
|
||||
if (pn2->isKind(PNK_MUTATEPROTO)) {
|
||||
if (!EmitTree(cx, bce, pn2->pn_kid))
|
||||
return false;
|
||||
obj = nullptr;
|
||||
if (!Emit1(cx, bce, JSOP_MUTATEPROTO))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
|
||||
ParseNode *pn3 = pn2->pn_left;
|
||||
bool isIndex = false;
|
||||
|
@ -5966,12 +5976,9 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (!bce->makeAtomIndex(pn3->pn_atom, &index))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Disable NEWOBJECT on initializers that set __proto__, which has
|
||||
* a non-standard setter on objects.
|
||||
*/
|
||||
if (pn3->pn_atom == cx->names().proto)
|
||||
obj = nullptr;
|
||||
MOZ_ASSERT((op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER) ||
|
||||
pn3->pn_atom != cx->names().proto,
|
||||
"__proto__ shouldn't have been generated as an initprop");
|
||||
|
||||
if (obj) {
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
|
|
|
@ -235,6 +235,14 @@ class FullParseHandler
|
|||
return literal;
|
||||
}
|
||||
|
||||
bool addPrototypeMutation(ParseNode *literal, uint32_t begin, ParseNode *expr) {
|
||||
ParseNode *mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
|
||||
if (!mutation)
|
||||
return false;
|
||||
literal->append(mutation);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
|
||||
ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
|
||||
if (!propdef)
|
||||
|
|
|
@ -139,6 +139,7 @@ class UpvarCookie
|
|||
F(FORHEAD) \
|
||||
F(ARGSBODY) \
|
||||
F(SPREAD) \
|
||||
F(MUTATEPROTO) \
|
||||
\
|
||||
/* Unary operators. */ \
|
||||
F(TYPEOF) \
|
||||
|
|
|
@ -6807,6 +6807,7 @@ Parser<ParseHandler>::objectLiteral()
|
|||
|
||||
JSOp op = JSOP_INITPROP;
|
||||
Node propname;
|
||||
uint32_t begin;
|
||||
switch (ltok) {
|
||||
case TOK_NUMBER:
|
||||
atom = DoubleToAtom(context, tokenStream.currentToken().number());
|
||||
|
@ -6825,6 +6826,10 @@ Parser<ParseHandler>::objectLiteral()
|
|||
propname = handler.newIdentifier(atom, pos());
|
||||
if (!propname)
|
||||
return null();
|
||||
if (atom == context->names().proto) {
|
||||
begin = pos().begin;
|
||||
op = JSOP_MUTATEPROTO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -6893,7 +6898,7 @@ Parser<ParseHandler>::objectLiteral()
|
|||
return null();
|
||||
}
|
||||
|
||||
if (op == JSOP_INITPROP) {
|
||||
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO) {
|
||||
TokenKind tt = tokenStream.getToken();
|
||||
Node propexpr;
|
||||
if (tt == TOK_COLON) {
|
||||
|
@ -6909,11 +6914,15 @@ Parser<ParseHandler>::objectLiteral()
|
|||
* so that we can later assume singleton objects delegate to
|
||||
* the default Object.prototype.
|
||||
*/
|
||||
if (!handler.isConstant(propexpr) || atom == context->names().proto)
|
||||
if (!handler.isConstant(propexpr) || op == JSOP_MUTATEPROTO)
|
||||
handler.setListFlag(literal, PNX_NONCONST);
|
||||
|
||||
if (!handler.addPropertyDefinition(literal, propname, propexpr))
|
||||
if (op == JSOP_MUTATEPROTO
|
||||
? !handler.addPrototypeMutation(literal, begin, propexpr)
|
||||
: !handler.addPropertyDefinition(literal, propname, propexpr))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
}
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
else if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
|
||||
|
@ -6959,7 +6968,7 @@ Parser<ParseHandler>::objectLiteral()
|
|||
* any part of an accessor property.
|
||||
*/
|
||||
AssignmentType assignType;
|
||||
if (op == JSOP_INITPROP)
|
||||
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO)
|
||||
assignType = VALUE;
|
||||
else if (op == JSOP_INITPROP_GETTER)
|
||||
assignType = GET;
|
||||
|
|
|
@ -113,6 +113,7 @@ class SyntaxParseHandler
|
|||
bool addArrayElement(Node literal, Node element) { return true; }
|
||||
|
||||
Node newObjectLiteral(uint32_t begin) { return NodeGeneric; }
|
||||
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
bool addShorthandPropertyDefinition(Node literal, Node name) { return true; }
|
||||
bool addAccessorPropertyDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
|
|
|
@ -1676,6 +1676,30 @@ BaselineCompiler::emit_JSOP_INITELEM()
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*MutateProtoFn)(JSContext *cx, HandleObject obj, HandleValue newProto);
|
||||
static const VMFunction MutateProtoInfo = FunctionInfo<MutateProtoFn>(MutatePrototype);
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_MUTATEPROTO()
|
||||
{
|
||||
// Keep values on the stack for the decompiler.
|
||||
frame.syncStack(0);
|
||||
|
||||
masm.extractObject(frame.addressOfStackValue(frame.peek(-2)), R0.scratchReg());
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R1);
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(R1);
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (!callVM(MutateProtoInfo))
|
||||
return false;
|
||||
|
||||
frame.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_INITPROP()
|
||||
{
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace jit {
|
|||
_(JSOP_INITELEM) \
|
||||
_(JSOP_INITELEM_GETTER) \
|
||||
_(JSOP_INITELEM_SETTER) \
|
||||
_(JSOP_MUTATEPROTO) \
|
||||
_(JSOP_INITPROP) \
|
||||
_(JSOP_INITPROP_GETTER) \
|
||||
_(JSOP_INITPROP_SETTER) \
|
||||
|
|
|
@ -3707,6 +3707,21 @@ CodeGenerator::visitInitElemGetterSetter(LInitElemGetterSetter *lir)
|
|||
return callVM(InitElemGetterSetterInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool(*MutatePrototypeFn)(JSContext *cx, HandleObject obj, HandleValue value);
|
||||
static const VMFunction MutatePrototypeInfo =
|
||||
FunctionInfo<MutatePrototypeFn>(MutatePrototype);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitMutateProto(LMutateProto *lir)
|
||||
{
|
||||
Register objReg = ToRegister(lir->getObject());
|
||||
|
||||
pushArg(ToValue(lir, LMutateProto::ValueIndex));
|
||||
pushArg(objReg);
|
||||
|
||||
return callVM(MutatePrototypeInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool(*InitPropFn)(JSContext *cx, HandleObject obj,
|
||||
HandlePropertyName name, HandleValue value);
|
||||
static const VMFunction InitPropInfo =
|
||||
|
|
|
@ -146,6 +146,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitAbortPar(LAbortPar *lir);
|
||||
bool visitInitElem(LInitElem *lir);
|
||||
bool visitInitElemGetterSetter(LInitElemGetterSetter *lir);
|
||||
bool visitMutateProto(LMutateProto *lir);
|
||||
bool visitInitProp(LInitProp *lir);
|
||||
bool visitInitPropGetterSetter(LInitPropGetterSetter *lir);
|
||||
bool visitCreateThis(LCreateThis *lir);
|
||||
|
|
|
@ -1587,6 +1587,11 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
return jsop_initprop(name);
|
||||
}
|
||||
|
||||
case JSOP_MUTATEPROTO:
|
||||
{
|
||||
return jsop_mutateproto();
|
||||
}
|
||||
|
||||
case JSOP_INITPROP_GETTER:
|
||||
case JSOP_INITPROP_SETTER: {
|
||||
PropertyName *name = info().getAtom(pc)->asPropertyName();
|
||||
|
@ -5523,6 +5528,17 @@ IonBuilder::jsop_initelem_array()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_mutateproto()
|
||||
{
|
||||
MDefinition *value = current->pop();
|
||||
MDefinition *obj = current->peek(-1);
|
||||
|
||||
MMutateProto *mutate = MMutateProto::New(alloc(), obj, value);
|
||||
current->add(mutate);
|
||||
return resumeAfter(mutate);
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::jsop_initprop(PropertyName *name)
|
||||
{
|
||||
|
|
|
@ -557,6 +557,7 @@ class IonBuilder : public MIRGenerator
|
|||
bool jsop_initelem();
|
||||
bool jsop_initelem_array();
|
||||
bool jsop_initelem_getter_setter();
|
||||
bool jsop_mutateproto();
|
||||
bool jsop_initprop(PropertyName *name);
|
||||
bool jsop_initprop_getter_setter(PropertyName *name);
|
||||
bool jsop_regexp(RegExpObject *reobj);
|
||||
|
|
|
@ -620,6 +620,26 @@ class LInitElemGetterSetter : public LCallInstructionHelper<0, 2 + BOX_PIECES, 0
|
|||
}
|
||||
};
|
||||
|
||||
// Takes in an Object and a Value.
|
||||
class LMutateProto : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(MutateProto)
|
||||
|
||||
LMutateProto(const LAllocation &object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
|
||||
static const size_t ValueIndex = 1;
|
||||
|
||||
const LAllocation *getObject() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *getValue() {
|
||||
return getOperand(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Takes in an Object and a Value.
|
||||
class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
_(AbortPar) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
_(MutateProto) \
|
||||
_(InitProp) \
|
||||
_(InitPropGetterSetter) \
|
||||
_(CheckOverRecursed) \
|
||||
|
|
|
@ -279,6 +279,16 @@ LIRGenerator::visitInitElemGetterSetter(MInitElemGetterSetter *ins)
|
|||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitMutateProto(MMutateProto *ins)
|
||||
{
|
||||
LMutateProto *lir = new(alloc()) LMutateProto(useRegisterAtStart(ins->getObject()));
|
||||
if (!useBoxAtStart(lir, LMutateProto::ValueIndex, ins->getValue()))
|
||||
return false;
|
||||
|
||||
return add(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitInitProp(MInitProp *ins)
|
||||
{
|
||||
|
|
|
@ -79,6 +79,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitAbortPar(MAbortPar *ins);
|
||||
bool visitInitElem(MInitElem *ins);
|
||||
bool visitInitElemGetterSetter(MInitElemGetterSetter *ins);
|
||||
bool visitMutateProto(MMutateProto *ins);
|
||||
bool visitInitProp(MInitProp *ins);
|
||||
bool visitInitPropGetterSetter(MInitPropGetterSetter *ins);
|
||||
bool visitCheckOverRecursed(MCheckOverRecursed *ins);
|
||||
|
|
|
@ -1624,6 +1624,42 @@ class MAbortPar : public MAryControlInstruction<0, 0>
|
|||
}
|
||||
};
|
||||
|
||||
// Setting __proto__ in an object literal.
|
||||
class MMutateProto
|
||||
: public MAryInstruction<2>,
|
||||
public MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >
|
||||
{
|
||||
protected:
|
||||
MMutateProto(MDefinition *obj, MDefinition *value)
|
||||
{
|
||||
setOperand(0, obj);
|
||||
setOperand(1, value);
|
||||
setResultType(MIRType_None);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(MutateProto)
|
||||
|
||||
static MMutateProto *New(TempAllocator &alloc, MDefinition *obj, MDefinition *value)
|
||||
{
|
||||
return new(alloc) MMutateProto(obj, value);
|
||||
}
|
||||
|
||||
MDefinition *getObject() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *getValue() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
bool possiblyCalls() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Slow path for adding a property to an object without a known base.
|
||||
class MInitProp
|
||||
: public MAryInstruction<2>,
|
||||
|
|
|
@ -93,6 +93,7 @@ namespace jit {
|
|||
_(NewStringObject) \
|
||||
_(InitElem) \
|
||||
_(InitElemGetterSetter) \
|
||||
_(MutateProto) \
|
||||
_(InitProp) \
|
||||
_(InitPropGetterSetter) \
|
||||
_(Start) \
|
||||
|
|
|
@ -186,6 +186,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
UNSAFE_OP(NewDerivedTypedObject)
|
||||
UNSAFE_OP(InitElem)
|
||||
UNSAFE_OP(InitElemGetterSetter)
|
||||
UNSAFE_OP(MutateProto)
|
||||
UNSAFE_OP(InitProp)
|
||||
UNSAFE_OP(InitPropGetterSetter)
|
||||
SAFE_OP(Start)
|
||||
|
|
|
@ -187,6 +187,16 @@ SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, Handle
|
|||
return SetConstOperation(cx, obj, name, rval);
|
||||
}
|
||||
|
||||
bool
|
||||
MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value)
|
||||
{
|
||||
// Copy the incoming value. This may be overwritten; the return value is discarded.
|
||||
RootedValue rval(cx, value);
|
||||
|
||||
RootedId id(cx, NameToId(cx->names().proto));
|
||||
return baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false);
|
||||
}
|
||||
|
||||
bool
|
||||
InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value)
|
||||
{
|
||||
|
@ -194,8 +204,8 @@ InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v
|
|||
RootedValue rval(cx, value);
|
||||
RootedId id(cx, NameToId(name));
|
||||
|
||||
if (name == cx->names().proto)
|
||||
return baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false);
|
||||
MOZ_ASSERT(name != cx->names().proto,
|
||||
"__proto__ should have been handled by JSOP_MUTATEPROTO");
|
||||
return DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr, JSPROP_ENUMERATE, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -575,6 +575,7 @@ bool CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
|
|||
|
||||
bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
|
||||
bool SetConst(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
|
||||
bool MutatePrototype(JSContext *cx, HandleObject obj, HandleValue value);
|
||||
bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
|
||||
|
||||
template<bool Equal>
|
||||
|
|
|
@ -260,7 +260,7 @@ MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was cal
|
|||
MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
|
||||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_UNUSED210, 210, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_PROTO_SETTING_SLOW, 210, 0, JSEXN_TYPEERR, "mutating the [[Prototype]] of an object will cause your code to run very slowly; instead create the object with the correct initial [[Prototype]] value using Object.create")
|
||||
MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
|
||||
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 212, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
|
||||
MSG_DEF(JSMSG_UNUSED213, 213, 0, JSEXN_NONE, "")
|
||||
|
|
|
@ -4482,8 +4482,8 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
|
|||
JS_PUBLIC_API(bool)
|
||||
JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
|
||||
{
|
||||
static const unsigned TINY_LENGTH = 1000;
|
||||
static const unsigned HUGE_LENGTH = 100*1000;
|
||||
static const size_t TINY_LENGTH = 1000;
|
||||
static const size_t HUGE_LENGTH = 100 * 1000;
|
||||
|
||||
// These are heuristics which the caller may choose to ignore (e.g., for
|
||||
// testing purposes).
|
||||
|
@ -4493,11 +4493,13 @@ JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, si
|
|||
if (length < TINY_LENGTH)
|
||||
return false;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
// If the parsing task would have to wait for GC to complete, it'll probably
|
||||
// be faster to just start it synchronously on the main thread unless the
|
||||
// script is huge.
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
|
||||
return false;
|
||||
#endif // JS_THREADSAFE
|
||||
}
|
||||
|
||||
return cx->runtime()->canUseParallelParsing();
|
||||
|
|
|
@ -410,7 +410,8 @@ OPDEF(JSOP_UNUSED192, 192,"unused192", NULL, 1, 0, 0, JOF_BYTE)
|
|||
|
||||
OPDEF(JSOP_CALLELEM, 193, "callelem", NULL, 1, 2, 1, JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
|
||||
|
||||
OPDEF(JSOP_UNUSED194, 194,"unused194", NULL, 1, 0, 0, JOF_BYTE)
|
||||
/* __proto__: v inside an object initializer. */
|
||||
OPDEF(JSOP_MUTATEPROTO, 194, "mutateproto",NULL, 1, 2, 1, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* Get an extant property value, throwing ReferenceError if the identified
|
||||
|
|
|
@ -379,10 +379,12 @@ struct ParseTask
|
|||
~ParseTask();
|
||||
};
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
// Return whether, if a new parse task was started, it would need to wait for
|
||||
// an in-progress GC to complete before starting.
|
||||
extern bool
|
||||
OffThreadParsingMustWaitForGC(JSRuntime *rt);
|
||||
#endif
|
||||
|
||||
// Compression tasks are allocated on the stack by their triggering thread,
|
||||
// which will block on the compression completing as the task goes out of scope
|
||||
|
|
|
@ -148,6 +148,14 @@ static bool
|
|||
ProtoSetter(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Do this here, rather than in |ProtoSetterImpl|, so even likely-buggy
|
||||
// use of the __proto__ setter on unacceptable values, where no subsequent
|
||||
// use occurs on an acceptable value, will trigger a warning.
|
||||
RootedObject callee(cx, &args.callee());
|
||||
if (!GlobalObject::warnOnceAboutPrototypeMutation(cx, callee))
|
||||
return false;
|
||||
|
||||
return CallNonGenericMethod(cx, TestProtoThis, ProtoSetterImpl, args);
|
||||
}
|
||||
|
||||
|
@ -501,18 +509,17 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> globa
|
|||
}
|
||||
|
||||
/* static */ bool
|
||||
GlobalObject::warnOnceAboutWatch(JSContext *cx, HandleObject obj)
|
||||
GlobalObject::warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->global());
|
||||
HeapSlot &v = global->getSlotRef(WARNED_WATCH_DEPRECATED);
|
||||
HeapSlot &v = global->getSlotRef(slot);
|
||||
if (v.isUndefined()) {
|
||||
// Warn only once per global object.
|
||||
if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr,
|
||||
JSMSG_OBJECT_WATCH_DEPRECATED))
|
||||
errorNumber))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
v.init(global, HeapSlot::Slot, WARNED_WATCH_DEPRECATED, BooleanValue(true));
|
||||
v.init(global, HeapSlot::Slot, slot, BooleanValue(true));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,8 @@ class GlobalObject : public JSObject
|
|||
static const unsigned DATE_TIME_FORMAT_PROTO = NUMBER_FORMAT_PROTO + 1;
|
||||
static const unsigned REGEXP_STATICS = DATE_TIME_FORMAT_PROTO + 1;
|
||||
static const unsigned WARNED_WATCH_DEPRECATED = REGEXP_STATICS + 1;
|
||||
static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_WATCH_DEPRECATED + 1;
|
||||
static const unsigned WARNED_PROTO_SETTING_SLOW = WARNED_WATCH_DEPRECATED + 1;
|
||||
static const unsigned RUNTIME_CODEGEN_ENABLED = WARNED_PROTO_SETTING_SLOW + 1;
|
||||
static const unsigned DEBUGGERS = RUNTIME_CODEGEN_ENABLED + 1;
|
||||
static const unsigned INTRINSICS = DEBUGGERS + 1;
|
||||
static const unsigned FLOAT32X4_TYPE_OBJECT = INTRINSICS + 1;
|
||||
|
@ -151,6 +152,13 @@ class GlobalObject : public JSObject
|
|||
setSlot(INTRINSICS, ObjectValue(*obj));
|
||||
}
|
||||
|
||||
// Emit the specified warning if the given slot in |obj|'s global isn't
|
||||
// true, then set the slot to true. Thus calling this method warns once
|
||||
// for each global object it's called on, and every other call does
|
||||
// nothing.
|
||||
static bool
|
||||
warnOnceAbout(JSContext *cx, HandleObject obj, uint32_t slot, unsigned errorNumber);
|
||||
|
||||
public:
|
||||
Value getConstructor(JSProtoKey key) const {
|
||||
JS_ASSERT(key <= JSProto_LIMIT);
|
||||
|
@ -605,7 +613,20 @@ class GlobalObject : public JSObject
|
|||
|
||||
// Warn about use of the deprecated watch/unwatch functions in the global
|
||||
// in which |obj| was created, if no prior warning was given.
|
||||
static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj);
|
||||
static bool warnOnceAboutWatch(JSContext *cx, HandleObject obj) {
|
||||
// Temporarily disabled until we've provided a watch/unwatch workaround for
|
||||
// debuggers like Firebug (bug 934669).
|
||||
//return warnOnceAbout(cx, obj, WARNED_WATCH_DEPRECATED, JSMSG_OBJECT_WATCH_DEPRECATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Warn about use of the given __proto__ setter to attempt to mutate an
|
||||
// object's [[Prototype]], if no prior warning was given.
|
||||
static bool warnOnceAboutPrototypeMutation(JSContext *cx, HandleObject protoSetter) {
|
||||
// Temporarily disabled until the second half of bug 948583 lands.
|
||||
//return warnOnceAbout(cx, protoSetter, WARNED_PROTO_SETTING_SLOW, JSMSG_PROTO_SETTING_SLOW);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getOrCreateEval(JSContext *cx, Handle<GlobalObject*> global,
|
||||
MutableHandleObject eval);
|
||||
|
|
|
@ -1658,7 +1658,6 @@ CASE(JSOP_UNUSED189)
|
|||
CASE(JSOP_UNUSED190)
|
||||
CASE(JSOP_UNUSED191)
|
||||
CASE(JSOP_UNUSED192)
|
||||
CASE(JSOP_UNUSED194)
|
||||
CASE(JSOP_UNUSED196)
|
||||
CASE(JSOP_UNUSED201)
|
||||
CASE(JSOP_UNUSED205)
|
||||
|
@ -3112,6 +3111,28 @@ CASE(JSOP_ENDINIT)
|
|||
}
|
||||
END_CASE(JSOP_ENDINIT)
|
||||
|
||||
CASE(JSOP_MUTATEPROTO)
|
||||
{
|
||||
/* Load the new [[Prototype]] value into rval. */
|
||||
MOZ_ASSERT(REGS.stackDepth() >= 2);
|
||||
RootedValue &rval = rootValue0;
|
||||
rval = REGS.sp[-1];
|
||||
|
||||
/* Load the object being initialized into lval/obj. */
|
||||
RootedObject &obj = rootObject0;
|
||||
obj = ®S.sp[-2].toObject();
|
||||
MOZ_ASSERT(obj->is<JSObject>());
|
||||
|
||||
RootedId &id = rootId0;
|
||||
id = NameToId(cx->names().proto);
|
||||
|
||||
if (!baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval, false))
|
||||
goto error;
|
||||
|
||||
REGS.sp--;
|
||||
}
|
||||
END_CASE(JSOP_MUTATEPROTO);
|
||||
|
||||
CASE(JSOP_INITPROP)
|
||||
{
|
||||
/* Load the property's initial value into rval. */
|
||||
|
@ -3129,13 +3150,8 @@ CASE(JSOP_INITPROP)
|
|||
RootedId &id = rootId0;
|
||||
id = NameToId(name);
|
||||
|
||||
if (JS_UNLIKELY(name == cx->names().proto)
|
||||
? !baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval,
|
||||
script->strict())
|
||||
: !DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE, 0, 0, 0)) {
|
||||
if (!DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr, JSPROP_ENUMERATE, 0, 0, 0))
|
||||
goto error;
|
||||
}
|
||||
|
||||
REGS.sp--;
|
||||
}
|
||||
|
|
|
@ -2075,6 +2075,8 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoIncrementalSearchResetter incrementalSearchResetter;
|
||||
|
||||
// Don't check defaultPrevented value because other browsers don't prevent
|
||||
// the key navigation of list control even if preventDefault() is called.
|
||||
|
||||
|
@ -2124,41 +2126,45 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
|
|||
1, 1);
|
||||
break;
|
||||
case NS_VK_RETURN:
|
||||
if (mComboboxFrame) {
|
||||
nsWeakFrame weakFrame(this);
|
||||
if (IsInDropDownMode()) {
|
||||
// If the select element is a dropdown style, Enter key should be
|
||||
// consumed everytime since Enter key may be pressed accidentally after
|
||||
// the dropdown is closed by Enter key press.
|
||||
aKeyEvent->PreventDefault();
|
||||
|
||||
if (mComboboxFrame->IsDroppedDown()) {
|
||||
// At closing dropdown, users may not expect there is additional
|
||||
// behavior for this key event. Therefore, let's consume the event.
|
||||
aKeyEvent->PreventDefault();
|
||||
nsWeakFrame weakFrame(this);
|
||||
ComboboxFinish(mEndSelectionIndex);
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// XXX This is strange. On other browsers, "change" event is fired
|
||||
// immediately after the selected item is changed rather than
|
||||
// Enter key is pressed.
|
||||
FireOnChange();
|
||||
if (!weakFrame.IsAlive()) {
|
||||
// If the keydown event causes destroying this, fired keypress on
|
||||
// another element may cause another action which may not be
|
||||
// expected by the user.
|
||||
aKeyEvent->PreventDefault();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If this is single select listbox, Enter key doesn't cause anything.
|
||||
if (!GetMultiple()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
newIndex = mEndSelectionIndex;
|
||||
break;
|
||||
case NS_VK_ESCAPE: {
|
||||
nsWeakFrame weakFrame(this);
|
||||
// XXX When the Escape keydown causes closing dropdown, it shouldn't
|
||||
// cause any additonal actions. We should call preventDefault() here.
|
||||
AboutToRollup();
|
||||
if (!weakFrame.IsAlive()) {
|
||||
// If the keydown event causes destroying this, fired keypress on
|
||||
// another element may cause another action which may not be
|
||||
// expected by the user.
|
||||
aKeyEvent->PreventDefault();
|
||||
// If the select element is a listbox style, Escape key causes nothing.
|
||||
if (!IsInDropDownMode()) {
|
||||
return NS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
AboutToRollup();
|
||||
// If the select element is a dropdown style, Enter key should be
|
||||
// consumed everytime since Escape key may be pressed accidentally after
|
||||
// the dropdown is closed by Escepe key.
|
||||
aKeyEvent->PreventDefault();
|
||||
return NS_OK;
|
||||
}
|
||||
case NS_VK_PAGE_UP: {
|
||||
int32_t itemsPerPage =
|
||||
|
@ -2194,14 +2200,12 @@ nsListControlFrame::KeyDown(nsIDOMEvent* aKeyEvent)
|
|||
#endif
|
||||
|
||||
default: // printable key will be handled by keypress event.
|
||||
incrementalSearchResetter.Cancel();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aKeyEvent->PreventDefault();
|
||||
|
||||
// Cancel incremental search if it's being performed.
|
||||
GetIncrementalString().Truncate();
|
||||
|
||||
// Actually process the new index and let the selection code
|
||||
// do the scrolling for us
|
||||
PostHandleKeyEvent(newIndex, 0, keyEvent->IsShift(), isControlOrMeta);
|
||||
|
@ -2218,6 +2222,8 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoIncrementalSearchResetter incrementalSearchResetter;
|
||||
|
||||
const WidgetKeyboardEvent* keyEvent =
|
||||
aKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
|
||||
MOZ_ASSERT(keyEvent,
|
||||
|
@ -2250,17 +2256,25 @@ nsListControlFrame::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
// NOTE: If keyCode of keypress event is not 0, charCode is always 0.
|
||||
// Therefore, all non-printable keys are not handled after this block.
|
||||
if (!keyEvent->charCode) {
|
||||
// Backspace key will delete the last char in the string
|
||||
// XXX Backspace key causes "go back the history" on Windows. Shouldn't we
|
||||
// prevent its default action if incremental search is used since
|
||||
// getting focus? When I tested this, it worked accidentally.
|
||||
if (keyEvent->keyCode == NS_VK_BACK && !GetIncrementalString().IsEmpty()) {
|
||||
GetIncrementalString().Truncate(GetIncrementalString().Length() - 1);
|
||||
// Backspace key will delete the last char in the string. Otherwise,
|
||||
// non-printable keypress should reset incremental search.
|
||||
if (keyEvent->keyCode == NS_VK_BACK) {
|
||||
incrementalSearchResetter.Cancel();
|
||||
if (!GetIncrementalString().IsEmpty()) {
|
||||
GetIncrementalString().Truncate(GetIncrementalString().Length() - 1);
|
||||
}
|
||||
aKeyEvent->PreventDefault();
|
||||
} else {
|
||||
// XXX When a select element has focus, even if the key causes nothing,
|
||||
// it might be better to call preventDefault() here because nobody
|
||||
// should expect one of other elements including chrome handles the
|
||||
// key event.
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
incrementalSearchResetter.Cancel();
|
||||
|
||||
// We ate the key if we got this far.
|
||||
aKeyEvent->PreventDefault();
|
||||
|
||||
|
|
|
@ -445,6 +445,27 @@ private:
|
|||
// for incremental typing navigation
|
||||
static nsAString& GetIncrementalString ();
|
||||
static DOMTimeStamp gLastKeyTime;
|
||||
|
||||
class MOZ_STACK_CLASS AutoIncrementalSearchResetter
|
||||
{
|
||||
public:
|
||||
AutoIncrementalSearchResetter() :
|
||||
mCancelled(false)
|
||||
{
|
||||
}
|
||||
~AutoIncrementalSearchResetter()
|
||||
{
|
||||
if (!mCancelled) {
|
||||
nsListControlFrame::GetIncrementalString().Truncate();
|
||||
}
|
||||
}
|
||||
void Cancel()
|
||||
{
|
||||
mCancelled = true;
|
||||
}
|
||||
private:
|
||||
bool mCancelled;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* nsListControlFrame_h___ */
|
||||
|
|
|
@ -799,7 +799,7 @@ void nsDisplayNotation::Paint(nsDisplayListBuilder* aBuilder,
|
|||
rect.TopRight() + gfxPoint(std::min(e / 2.0, -w + .4*h), h + .4*w),
|
||||
rect.TopRight()
|
||||
};
|
||||
gfxCtx->Polygon(p, sizeof(p));
|
||||
gfxCtx->Polygon(p, MOZ_ARRAY_LENGTH(p));
|
||||
gfxCtx->Fill();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -560,6 +560,7 @@ function getStreamContent(inputStream)
|
|||
function BuildConditionSandbox(aURL) {
|
||||
var sandbox = new Components.utils.Sandbox(aURL.spec);
|
||||
var xr = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULRuntime);
|
||||
var appInfo = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULAppInfo);
|
||||
sandbox.isDebugBuild = gDebug.isDebugBuild;
|
||||
sandbox.xulRuntime = {widgetToolkit: xr.widgetToolkit, OS: xr.OS, __exposedProps__: { widgetToolkit: "r", OS: "r", XPCOMABI: "r", shell: "r" } };
|
||||
|
||||
|
@ -600,6 +601,7 @@ function BuildConditionSandbox(aURL) {
|
|||
|
||||
// Shortcuts for widget toolkits.
|
||||
sandbox.B2G = xr.widgetToolkit == "gonk";
|
||||
sandbox.B2GDT = appInfo.name.toLowerCase() == "b2g" && !sandbox.B2G;
|
||||
sandbox.Android = xr.OS == "Android" && !sandbox.B2G;
|
||||
sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
|
||||
sandbox.gtk2Widget = xr.widgetToolkit == "gtk2";
|
||||
|
|
|
@ -17,6 +17,10 @@ LIBS = \
|
|||
$(DEPTH)/netwerk/srtp/src/$(LIB_PREFIX)nksrtp_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
|
||||
ifdef JS_SHARED_LIBRARY
|
||||
LIBS += $(MOZ_JS_LIBS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_ALSA
|
||||
LIBS += \
|
||||
$(MOZ_ALSA_LIBS) \
|
||||
|
|
|
@ -288,6 +288,9 @@ static const bool config_ivsalloc =
|
|||
# ifdef __tile__
|
||||
# define LG_QUANTUM 4
|
||||
# endif
|
||||
# ifdef __aarch64__
|
||||
# define LG_QUANTUM 4
|
||||
# endif
|
||||
# ifndef LG_QUANTUM
|
||||
# error "No LG_QUANTUM definition for architecture; specify via CPPFLAGS"
|
||||
# endif
|
||||
|
|
|
@ -1102,7 +1102,7 @@ static unsigned ncpus;
|
|||
#if (defined(SOLARIS) || defined(__FreeBSD__)) && \
|
||||
(defined(__sparc) || defined(__sparcv9) || defined(__ia64))
|
||||
#define pagesize_2pow ((size_t) 13)
|
||||
#elif defined(__powerpc64__)
|
||||
#elif defined(__powerpc64__) || defined(__aarch64__)
|
||||
#define pagesize_2pow ((size_t) 16)
|
||||
#else
|
||||
#define pagesize_2pow ((size_t) 12)
|
||||
|
|
|
@ -122,14 +122,14 @@
|
|||
defined(_POWER) || defined(__powerpc__) || \
|
||||
defined(__ppc__) || defined(__hppa) || \
|
||||
defined(_MIPSEB) || defined(__ARMEB__) || \
|
||||
defined(__s390__) || \
|
||||
defined(__s390__) || defined(__AARCH64EB__) || \
|
||||
(defined(__sh__) && defined(__LITTLE_ENDIAN__)) || \
|
||||
(defined(__ia64) && defined(__BIG_ENDIAN__))
|
||||
# define MOZ_BIG_ENDIAN 1
|
||||
#elif defined(__i386) || defined(__i386__) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_MIPSEL) || defined(__ARMEL__) || \
|
||||
defined(__alpha__) || \
|
||||
defined(__alpha__) || defined(__AARCH64EL__) || \
|
||||
(defined(__sh__) && defined(__BIG_ENDIAN__)) || \
|
||||
(defined(__ia64) && !defined(__BIG_ENDIAN__))
|
||||
# define MOZ_LITTLE_ENDIAN 1
|
||||
|
|
|
@ -161,6 +161,9 @@
|
|||
#elif defined __s390__
|
||||
#define RETURN_INSTR 0x07fe0000 /* br %r14 */
|
||||
|
||||
#elif defined __aarch64__
|
||||
#define RETURN_INSTR 0xd65f03c0 /* ret */
|
||||
|
||||
#elif defined __ia64
|
||||
struct ia64_instr { uint32_t i[4]; };
|
||||
static const ia64_instr _return_instr =
|
||||
|
|
|
@ -818,7 +818,7 @@ pref("browser.snippets.geoUrl", "https://geo.mozilla.org/country.json");
|
|||
pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
|
||||
|
||||
// These prefs require a restart to take effect.
|
||||
pref("browser.snippets.enabled", false);
|
||||
pref("browser.snippets.enabled", true);
|
||||
pref("browser.snippets.syncPromo.enabled", false);
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
|
|
|
@ -716,6 +716,8 @@ public abstract class GeckoApp
|
|||
message.optString("className"), message.optString("action"), message.optString("title"));
|
||||
} else if (event.equals("Locale:Set")) {
|
||||
setLocale(message.getString("locale"));
|
||||
} else if (event.equals("SystemUI:Visibility")) {
|
||||
setSystemUiVisible(message.getBoolean("visible"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
||||
|
@ -1580,6 +1582,7 @@ public abstract class GeckoApp
|
|||
registerEventListener("Intent:Open");
|
||||
registerEventListener("Intent:GetHandlers");
|
||||
registerEventListener("Locale:Set");
|
||||
registerEventListener("SystemUI:Visibility");
|
||||
|
||||
if (SmsManager.getInstance() != null) {
|
||||
SmsManager.getInstance().start();
|
||||
|
@ -2109,6 +2112,7 @@ public abstract class GeckoApp
|
|||
unregisterEventListener("Intent:Open");
|
||||
unregisterEventListener("Intent:GetHandlers");
|
||||
unregisterEventListener("Locale:Set");
|
||||
unregisterEventListener("SystemUI:Visibility");
|
||||
|
||||
deleteTempFiles();
|
||||
|
||||
|
@ -2815,4 +2819,17 @@ public abstract class GeckoApp
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setSystemUiVisible(final boolean visible) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (visible) {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
} else {
|
||||
mMainLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,8 +168,11 @@ public final class HomeConfig {
|
|||
mLayoutType = panelConfig.mLayoutType;
|
||||
|
||||
mViews = new ArrayList<ViewConfig>();
|
||||
for (ViewConfig viewConfig : panelConfig.mViews) {
|
||||
mViews.add(new ViewConfig(viewConfig));
|
||||
List<ViewConfig> viewConfigs = panelConfig.mViews;
|
||||
if (viewConfigs != null) {
|
||||
for (ViewConfig viewConfig : viewConfigs) {
|
||||
mViews.add(new ViewConfig(viewConfig));
|
||||
}
|
||||
}
|
||||
mFlags = panelConfig.mFlags.clone();
|
||||
|
||||
|
|
|
@ -80,8 +80,12 @@ public abstract class CustomListPreference extends Preference implements View.On
|
|||
protected abstract int getPreferenceLayoutResource();
|
||||
|
||||
/**
|
||||
* Set whether this object's UI should display this as the default item. To ensure proper ordering,
|
||||
* this method should only be called after this Preference is added to the PreferenceCategory.
|
||||
* Set whether this object's UI should display this as the default item.
|
||||
* Note: This must be called from the UI thread because it touches the view hierarchy.
|
||||
*
|
||||
* To ensure proper ordering, this method should only be called after this Preference
|
||||
* is added to the PreferenceCategory.
|
||||
*
|
||||
* @param isDefault Flag indicating if this represents the default list item.
|
||||
*/
|
||||
public void setIsDefault(boolean isDefault) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.json.JSONObject;
|
|||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
public class SearchPreferenceCategory extends CustomListCategory implements GeckoEventListener {
|
||||
public static final String LOGTAG = "SearchPrefCategory";
|
||||
|
@ -81,7 +82,7 @@ public class SearchPreferenceCategory extends CustomListCategory implements Geck
|
|||
JSONObject engineJSON = engines.getJSONObject(i);
|
||||
final String engineName = engineJSON.getString("name");
|
||||
|
||||
SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
|
||||
final SearchEnginePreference enginePreference = new SearchEnginePreference(getContext(), this);
|
||||
enginePreference.setSearchEngineFromJSON(engineJSON);
|
||||
enginePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@Override
|
||||
|
@ -100,7 +101,12 @@ public class SearchPreferenceCategory extends CustomListCategory implements Geck
|
|||
// We set this here, not in setSearchEngineFromJSON, because it allows us to
|
||||
// keep a reference to the default engine to use when the AlertDialog
|
||||
// callbacks are used.
|
||||
enginePreference.setIsDefault(true);
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
enginePreference.setIsDefault(true);
|
||||
}
|
||||
});
|
||||
mDefaultReference = enginePreference;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
|
|
После Ширина: | Высота: | Размер: 797 B |
После Ширина: | Высота: | Размер: 193 B |
После Ширина: | Высота: | Размер: 664 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/ab_done.png
До Ширина: | Высота: | Размер: 737 B После Ширина: | Высота: | Размер: 574 B |
После Ширина: | Высота: | Размер: 324 B |
После Ширина: | Высота: | Размер: 846 B |
После Ширина: | Высота: | Размер: 199 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/copy.png
До Ширина: | Высота: | Размер: 199 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/cut.png
До Ширина: | Высота: | Размер: 564 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/menu_light.png
До Ширина: | Высота: | Размер: 148 B После Ширина: | Высота: | Размер: 144 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/paste.png
До Ширина: | Высота: | Размер: 337 B |
Двоичные данные
mobile/android/base/resources/drawable-hdpi/select_all.png
До Ширина: | Высота: | Размер: 216 B |
После Ширина: | Высота: | Размер: 569 B |
После Ширина: | Высота: | Размер: 166 B |
После Ширина: | Высота: | Размер: 459 B |
Двоичные данные
mobile/android/base/resources/drawable-mdpi/ab_done.png
До Ширина: | Высота: | Размер: 552 B После Ширина: | Высота: | Размер: 442 B |
После Ширина: | Высота: | Размер: 249 B |
После Ширина: | Высота: | Размер: 587 B |