merge mozilla-central to b2g-inbound on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2014-01-24 15:34:03 +01:00
commit eeb0c3bef6
132 changed files with 1415 additions and 249 deletions

View File

@ -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.)

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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"/>

View File

@ -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

View File

@ -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',

View File

@ -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"

View File

@ -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"

View File

@ -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;
})

View File

@ -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"));

View File

@ -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);
}

View File

@ -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() {

View File

@ -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", {});
(() => {

View File

@ -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);

View File

@ -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…">

View File

@ -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();

View File

@ -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

View File

@ -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) {

View File

@ -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],

View File

@ -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)

View File

@ -1158,6 +1158,10 @@ arm*)
mips|mipsel)
CPU_ARCH="mips"
;;
aarch64*)
CPU_ARCH=aarch64
;;
esac
if test -z "$OS_TARGET"; then

View File

@ -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,

View File

@ -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
{

View File

@ -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);

View File

@ -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();

View File

@ -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:

View File

@ -2,4 +2,5 @@
[test_bug883683.html]
[test_promise.html]
[test_promise_utils.html]
[test_resolve.html]

View File

@ -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>

View File

@ -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);
};

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -28,7 +28,7 @@
namespace mozilla {
namespace layers {
float APZCTreeManager::sDPI = 72.0;
float APZCTreeManager::sDPI = 160.0;
APZCTreeManager::APZCTreeManager()
: mTreeLock("APZCTreeLock"),

View File

@ -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).

View File

@ -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 \

View File

@ -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) {

View File

@ -970,6 +970,11 @@ arm*)
mips|mipsel)
CPU_ARCH="mips"
;;
aarch64*)
CPU_ARCH=aarch64
;;
esac
if test -z "$OS_TARGET"; then

View File

@ -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());

View File

@ -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)

View File

@ -139,6 +139,7 @@ class UpvarCookie
F(FORHEAD) \
F(ARGSBODY) \
F(SPREAD) \
F(MUTATEPROTO) \
\
/* Unary operators. */ \
F(TYPEOF) \

View File

@ -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;

View File

@ -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; }

View File

@ -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()
{

View File

@ -90,6 +90,7 @@ namespace jit {
_(JSOP_INITELEM) \
_(JSOP_INITELEM_GETTER) \
_(JSOP_INITELEM_SETTER) \
_(JSOP_MUTATEPROTO) \
_(JSOP_INITPROP) \
_(JSOP_INITPROP_GETTER) \
_(JSOP_INITPROP_SETTER) \

View File

@ -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 =

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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>
{

View File

@ -36,6 +36,7 @@
_(AbortPar) \
_(InitElem) \
_(InitElemGetterSetter) \
_(MutateProto) \
_(InitProp) \
_(InitPropGetterSetter) \
_(CheckOverRecursed) \

View File

@ -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)
{

View File

@ -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);

View File

@ -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>,

View File

@ -93,6 +93,7 @@ namespace jit {
_(NewStringObject) \
_(InitElem) \
_(InitElemGetterSetter) \
_(MutateProto) \
_(InitProp) \
_(InitPropGetterSetter) \
_(Start) \

View File

@ -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)

View File

@ -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);
}

View File

@ -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>

View File

@ -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, "")

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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 = &REGS.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--;
}

View File

@ -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();

View File

@ -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___ */

View File

@ -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;

View File

@ -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";

View File

@ -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) \

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 =

View File

@ -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

View File

@ -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);
}
}
});
}
}

View File

@ -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();

View File

@ -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) {

View File

@ -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) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 552 B

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Some files were not shown because too many files have changed in this diff Show More