diff --git a/config/config.mk b/config/config.mk index 410a3c8621dd..7700801067b0 100644 --- a/config/config.mk +++ b/config/config.mk @@ -87,20 +87,12 @@ endif CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf -ifeq ($(OS_ARCH),QNX) -ifeq ($(OS_TARGET),NTO) -LD := qcc -Vgcc_ntox86 -nostdlib -else -LD := $(CC) -endif -endif - # # Strip off the excessively long version numbers on these platforms, # but save the version to allow multiple versions of the same base # platform to be built in the same tree. # -ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD OSF1 SunOS,$(OS_ARCH))) +ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD SunOS,$(OS_ARCH))) OS_RELEASE := $(basename $(OS_RELEASE)) # Allow the user to ignore the OS_VERSION, which is usually irrelevant. diff --git a/config/rules.mk b/config/rules.mk index b494376b5a10..e919d99a64ee 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -500,17 +500,6 @@ endif # HAS_EXTRAEXPORTS endif # IS_COMPONENT endif # AIX -# -# OSF1: add -B symbolic flag for components -# -ifeq ($(OS_ARCH),OSF1) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -B symbolic -endif -endif -endif - # # Linux: add -Bsymbolic flag for components # diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index a421bd5299f0..6fb752bb87d7 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -607,10 +607,7 @@ PRInt32 nsGenericElement::GetScrollTop() { nsIScrollableFrame* sf = GetScrollFrame(); - - return sf ? - nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().y) : - 0; + return sf ? sf->GetScrollPositionCSSPixels().y : 0; } NS_IMETHODIMP @@ -626,9 +623,7 @@ nsGenericElement::SetScrollTop(PRInt32 aScrollTop) { nsIScrollableFrame* sf = GetScrollFrame(); if (sf) { - nsPoint pt = sf->GetScrollPosition(); - sf->ScrollToCSSPixels(nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x), - aScrollTop)); + sf->ScrollToCSSPixels(nsIntPoint(sf->GetScrollPositionCSSPixels().x, aScrollTop)); } return NS_OK; } @@ -637,10 +632,7 @@ PRInt32 nsGenericElement::GetScrollLeft() { nsIScrollableFrame* sf = GetScrollFrame(); - - return sf ? - nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().x) : - 0; + return sf ? sf->GetScrollPositionCSSPixels().x : 0; } NS_IMETHODIMP @@ -656,9 +648,7 @@ nsGenericElement::SetScrollLeft(PRInt32 aScrollLeft) { nsIScrollableFrame* sf = GetScrollFrame(); if (sf) { - nsPoint pt = sf->GetScrollPosition(); - sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft, - nsPresContext::AppUnitsToIntCSSPixels(pt.y))); + sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft, sf->GetScrollPositionCSSPixels().y)); } return NS_OK; } diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 19083ab0ce24..aaf31f8ae1a0 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -4645,23 +4645,20 @@ nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder, return nullptr; } CanvasRenderingContext2DUserDataAzure *userData = nullptr; - if (aBuilder->IsPaintingToWindow()) { - // Make the layer tell us whenever a transaction finishes (including - // the current transaction), so we can clear our invalidation state and - // start invalidating again. We need to do this for the layer that is - // being painted to a window (there shouldn't be more than one at a time, - // and if there is, flushing the invalidation state more often than - // necessary is harmless). + // Make the layer tell us whenever a transaction finishes (including + // the current transaction), so we can clear our invalidation state and + // start invalidating again. We need to do this for all layers since + // callers of DrawWindow may be expecting to receive normal invalidation + // notifications after this paint. - // The layer will be destroyed when we tear down the presentation - // (at the latest), at which time this userData will be destroyed, - // releasing the reference to the element. - // The userData will receive DidTransactionCallbacks, which flush the - // the invalidation state to indicate that the canvas is up to date. - userData = new CanvasRenderingContext2DUserDataAzure(this); - canvasLayer->SetDidTransactionCallback( - CanvasRenderingContext2DUserDataAzure::DidTransactionCallback, userData); - } + // The layer will be destroyed when we tear down the presentation + // (at the latest), at which time this userData will be destroyed, + // releasing the reference to the element. + // The userData will receive DidTransactionCallbacks, which flush the + // the invalidation state to indicate that the canvas is up to date. + userData = new CanvasRenderingContext2DUserDataAzure(this); + canvasLayer->SetDidTransactionCallback( + CanvasRenderingContext2DUserDataAzure::DidTransactionCallback, userData); canvasLayer->SetUserData(&g2DContextLayerUserData, userData); CanvasLayer::Data data; diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index 80bdfe2c2b57..b6e6cfe18784 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -332,7 +332,6 @@ public: static DeltaValues AccelerateWheelDelta(widget::WheelEvent* aEvent, bool aAllowScrollSpeedOverride); - static bool IsAccelerationEnabled(); enum { kScrollSeriesTimeout = 80 @@ -588,12 +587,6 @@ nsMouseWheelTransaction::GetIgnoreMoveDelayTime() return Preferences::GetUint("mousewheel.transaction.ignoremovedelay", 100); } -bool -nsMouseWheelTransaction::IsAccelerationEnabled() -{ - return GetAccelerationStart() >= 0 && GetAccelerationFactor() > 0; -} - DeltaValues nsMouseWheelTransaction::AccelerateWheelDelta(widget::WheelEvent* aEvent, bool aAllowScrollSpeedOverride) diff --git a/content/html/content/test/forms/test_formnovalidate_attribute.html b/content/html/content/test/forms/test_formnovalidate_attribute.html index 8ab9b070f3e6..6028df25e1a7 100644 --- a/content/html/content/test/forms/test_formnovalidate_attribute.html +++ b/content/html/content/test/forms/test_formnovalidate_attribute.html @@ -61,7 +61,6 @@ var observers = os.enumerateObservers("invalidformsubmit"); */ if (observers.hasMoreElements()) { - document.getElementById('av').addEventListener("invalid", function(aEvent) { aEvent.target.removeAttribute("invalid", arguments.callee, false); ok(true, "formnovalidate should not apply on if not set on the submit " + @@ -133,6 +132,8 @@ if (observers.hasMoreElements()) { SimpleTest.waitForFocus(function() { document.getElementById('a').click(); }); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); } diff --git a/content/html/content/test/test_bug605124-1.html b/content/html/content/test/test_bug605124-1.html index 71fd253cb771..9e100941d99b 100644 --- a/content/html/content/test/test_bug605124-1.html +++ b/content/html/content/test/test_bug605124-1.html @@ -98,6 +98,8 @@ if (observers.hasMoreElements()) { checkPseudoClass(textarea, false); checkPseudoClass(input, false); checkPseudoClass(select, false); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); } diff --git a/content/html/content/test/test_bug605125-1.html b/content/html/content/test/test_bug605125-1.html index 9c9abd9f3233..43b3de0cc91b 100644 --- a/content/html/content/test/test_bug605125-1.html +++ b/content/html/content/test/test_bug605125-1.html @@ -104,6 +104,8 @@ if (observers.hasMoreElements()) { checkPseudoClass(textarea, false); checkPseudoClass(input, false); checkPseudoClass(select, false); +} else { + todo(false, "No 'invalidformsubmit' observers. Skip test."); } diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index a8435f7ee0c7..13a0bcfa85cd 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -54,6 +54,8 @@ #include "nsIDOMGlobalPropertyInitializer.h" +using namespace mozilla::dom::power; + // This should not be in the namespace. DOMCI_DATA(Navigator, mozilla::dom::Navigator) @@ -1029,11 +1031,11 @@ Navigator::GetMozPower(nsIDOMMozPowerManager** aPower) *aPower = nullptr; if (!mPowerManager) { - nsCOMPtr win = do_QueryReferent(mWindow); - NS_ENSURE_TRUE(win, NS_OK); + nsCOMPtr window = do_QueryReferent(mWindow); + NS_ENSURE_TRUE(window, NS_OK); - mPowerManager = new power::PowerManager(); - mPowerManager->Init(win); + mPowerManager = PowerManager::CheckPermissionAndCreateInstance(window); + NS_ENSURE_TRUE(mPowerManager, NS_OK); } nsCOMPtr power(mPowerManager); diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d5f284b984e5..656ddd08153f 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -540,6 +540,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache; #include "LockedFile.h" #include "GeneratedEvents.h" #include "mozilla/Likely.h" +#include "nsDebug.h" #undef None // something included above defines this preprocessor symbol, maybe Xlib headers #include "WebGLContext.h" @@ -2073,8 +2074,10 @@ SetParentToWindow(nsGlobalWindow *win, JSObject **parent) if (MOZ_UNLIKELY(!*parent)) { // The only known case where this can happen is when the inner window has - // been torn down. See bug 691178 comment 11. - MOZ_ASSERT(win->IsClosedOrClosing()); + // been torn down. See bug 691178 comment 11. Should be a fatal MOZ_ASSERT, + // but we've found a way to hit it too often in mochitests. See bugs 777875 + // 778424, 781078. + NS_ASSERTION(win->IsClosedOrClosing(), "win should be closed or closing"); return NS_ERROR_FAILURE; } return NS_OK; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index a88830f850d9..6abdd59ffed3 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4322,11 +4322,13 @@ nsGlobalWindow::GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY, return GetScrollXY(aScrollX, aScrollY, true); } - if (aScrollX) - *aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x); - if (aScrollY) - *aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y); - + nsIntPoint scrollPosCSSPixels = sf->GetScrollPositionCSSPixels(); + if (aScrollX) { + *aScrollX = scrollPosCSSPixels.x; + } + if (aScrollY) { + *aScrollY = scrollPosCSSPixels.y; + } return NS_OK; } diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index f2ca18717496..fe1f1beb237f 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -654,6 +654,12 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect, } mFrontSurface = surface; + if (!surface) { + ImageContainer* container = GetImageContainer(); + if (container) { + container->SetCurrentImage(nullptr); + } + } RecvNPN_InvalidateRect(updatedRect); PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)", diff --git a/dom/power/PowerManager.cpp b/dom/power/PowerManager.cpp index a817a4bfe90f..9a9790b4a982 100644 --- a/dom/power/PowerManager.cpp +++ b/dom/power/PowerManager.cpp @@ -6,9 +6,10 @@ #include "mozilla/Hal.h" #include "PowerManager.h" #include "WakeLock.h" -#include "nsContentUtils.h" #include "nsDOMClassInfoID.h" #include "nsIDOMWakeLockListener.h" +#include "nsIDocument.h" +#include "nsIPermissionManager.h" #include "nsIPowerManagerService.h" #include "nsIPrincipal.h" #include "nsPIDOMWindow.h" @@ -57,33 +58,9 @@ PowerManager::Shutdown() return NS_OK; } -bool -PowerManager::CheckPermission() -{ - if (nsContentUtils::IsCallerChrome()) { - return true; - } - - nsCOMPtr win = do_QueryReferent(mWindow); - NS_ENSURE_TRUE(win, false); - nsCOMPtr doc = do_QueryInterface(win->GetExtantDocument()); - NS_ENSURE_TRUE(doc, false); - - nsCOMPtr uri; - doc->NodePrincipal()->GetURI(getter_AddRefs(uri)); - - if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.power.whitelist")) { - return false; - } - - return true; -} - NS_IMETHODIMP PowerManager::Reboot() { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - nsCOMPtr pmService = do_GetService(POWERMANAGERSERVICE_CONTRACTID); NS_ENSURE_STATE(pmService); @@ -96,8 +73,6 @@ PowerManager::Reboot() NS_IMETHODIMP PowerManager::PowerOff() { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - nsCOMPtr pmService = do_GetService(POWERMANAGERSERVICE_CONTRACTID); NS_ENSURE_STATE(pmService); @@ -110,8 +85,6 @@ PowerManager::PowerOff() NS_IMETHODIMP PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - // already added? bail out. if (mListeners.Contains(aListener)) return NS_OK; @@ -123,8 +96,6 @@ PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener) NS_IMETHODIMP PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - mListeners.RemoveElement(aListener); return NS_OK; } @@ -132,8 +103,6 @@ PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener) NS_IMETHODIMP PowerManager::GetWakeLockState(const nsAString &aTopic, nsAString &aState) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - nsCOMPtr pmService = do_GetService(POWERMANAGERSERVICE_CONTRACTID); NS_ENSURE_STATE(pmService); @@ -163,11 +132,6 @@ PowerManager::Callback(const nsAString &aTopic, const nsAString &aState) NS_IMETHODIMP PowerManager::GetScreenEnabled(bool *aEnabled) { - if (!CheckPermission()) { - *aEnabled = true; - return NS_OK; - } - *aEnabled = hal::GetScreenEnabled(); return NS_OK; } @@ -175,10 +139,6 @@ PowerManager::GetScreenEnabled(bool *aEnabled) NS_IMETHODIMP PowerManager::SetScreenEnabled(bool aEnabled) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - - // TODO bug 707589: When the screen's state changes, all visible windows - // should fire a visibility change event. hal::SetScreenEnabled(aEnabled); return NS_OK; } @@ -186,11 +146,6 @@ PowerManager::SetScreenEnabled(bool aEnabled) NS_IMETHODIMP PowerManager::GetScreenBrightness(double *aBrightness) { - if (!CheckPermission()) { - *aBrightness = 1; - return NS_OK; - } - *aBrightness = hal::GetScreenBrightness(); return NS_OK; } @@ -198,8 +153,6 @@ PowerManager::GetScreenBrightness(double *aBrightness) NS_IMETHODIMP PowerManager::SetScreenBrightness(double aBrightness) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG); hal::SetScreenBrightness(aBrightness); return NS_OK; @@ -208,11 +161,6 @@ PowerManager::SetScreenBrightness(double aBrightness) NS_IMETHODIMP PowerManager::GetCpuSleepAllowed(bool *aAllowed) { - if (!CheckPermission()) { - *aAllowed = true; - return NS_OK; - } - *aAllowed = hal::GetCpuSleepAllowed(); return NS_OK; } @@ -220,12 +168,40 @@ PowerManager::GetCpuSleepAllowed(bool *aAllowed) NS_IMETHODIMP PowerManager::SetCpuSleepAllowed(bool aAllowed) { - NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR); - hal::SetCpuSleepAllowed(aAllowed); return NS_OK; } +already_AddRefed +PowerManager::CheckPermissionAndCreateInstance(nsPIDOMWindow* aWindow) +{ + nsPIDOMWindow* innerWindow = aWindow->IsInnerWindow() ? + aWindow : + aWindow->GetCurrentInnerWindow(); + + // Need the document for security check. + nsCOMPtr document = innerWindow->GetExtantDoc(); + NS_ENSURE_TRUE(document, nullptr); + + nsCOMPtr principal = document->NodePrincipal(); + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + NS_ENSURE_TRUE(permMgr, nullptr); + + PRUint32 permission = nsIPermissionManager::DENY_ACTION; + permMgr->TestPermissionFromPrincipal(principal, "power", &permission); + + if (permission != nsIPermissionManager::ALLOW_ACTION) { + return nullptr; + } + + nsRefPtr powerManager = new PowerManager(); + powerManager->Init(aWindow); + + return powerManager.forget(); +} + } // power } // dom } // mozilla diff --git a/dom/power/PowerManager.h b/dom/power/PowerManager.h index 266873200b15..4bec150a665b 100644 --- a/dom/power/PowerManager.h +++ b/dom/power/PowerManager.h @@ -12,6 +12,8 @@ #include "nsIDOMWindow.h" #include "nsWeakReference.h" +class nsPIDOMWindow; + namespace mozilla { namespace dom { namespace power { @@ -31,8 +33,10 @@ public: nsresult Init(nsIDOMWindow *aWindow); nsresult Shutdown(); + static already_AddRefed + CheckPermissionAndCreateInstance(nsPIDOMWindow*); + private: - bool CheckPermission(); nsWeakPtr mWindow; nsTArray > mListeners; diff --git a/dom/power/test/browser_bug697132.js b/dom/power/test/browser_bug697132.js index 7cdfb8f0e4a2..d0f933aed0b8 100644 --- a/dom/power/test/browser_bug697132.js +++ b/dom/power/test/browser_bug697132.js @@ -1,10 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + "use strict"; waitForExplicitFinish(); -let kPrefNode = "dom.power.whitelist"; -let kPageSource1 = "data:text/html,1"; -let kPageSource2 = "data:text/html,2"; +let kUrlSource = "http://mochi.test:8888/"; +let kDataSource = "data:text/html,"; let gOldPref; let gWin, gWin1, gWin2; @@ -13,7 +16,7 @@ let gLock, gLock1, gLock2; let gCurStepIndex = -1; let gSteps = [ function basicWakeLock() { - gTab = gBrowser.addTab(kPageSource1); + gTab = gBrowser.addTab(kUrlSource); gWin = gBrowser.getBrowserForTab(gTab).contentWindow; let browser = gBrowser.getBrowserForTab(gTab); @@ -51,7 +54,7 @@ let gSteps = [ }, true); }, function multiWakeLock() { - gTab = gBrowser.addTab(kPageSource1); + gTab = gBrowser.addTab(kUrlSource); gWin = gBrowser.getBrowserForTab(gTab).contentWindow; let browser = gBrowser.getBrowserForTab(gTab); @@ -100,9 +103,9 @@ let gSteps = [ }, true); }, function crossTabWakeLock1() { - gTab1 = gBrowser.addTab(kPageSource1); + gTab1 = gBrowser.addTab(kUrlSource); gWin1 = gBrowser.getBrowserForTab(gTab1).contentWindow; - gTab2 = gBrowser.addTab(kPageSource1); + gTab2 = gBrowser.addTab(kUrlSource); gWin2 = gBrowser.getBrowserForTab(gTab2).contentWindow; gBrowser.selectedTab = gTab1; @@ -138,7 +141,7 @@ let gSteps = [ gWin2.removeEventListener("pageshow", onPageShow, true); executeSoon(runNextStep); }, true); - gWin2.location = kPageSource2; + gWin2.location = kDataSource; }, function crossTabWakeLock3() { is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked", @@ -166,7 +169,7 @@ let gSteps = [ gWin2.removeEventListener("pageshow", onPageShow, true); executeSoon(runNextStep); }, true); - gWin2.location = kPageSource2; + gWin2.location = kDataSource; }, function crossTabWakeLock6() { is(gWin1.navigator.mozPower.getWakeLockState("test"), "unlocked", @@ -219,18 +222,12 @@ function runNextStep() { if (gCurStepIndex < gSteps.length) { gSteps[gCurStepIndex](); } else { - Services.prefs.setCharPref(kPrefNode, gOldPref); + SpecialPowers.removePermission("power", kUrlSource); finish(); } } function test() { - try { - gOldPref = Services.prefs.getCharPref(kPrefNode); - } catch (e) { - gOldPref = ""; - } - // data url inherits its parent's principal, which is |about:| here. - Services.prefs.setCharPref(kPrefNode, "about:"); + SpecialPowers.addPermission("power", true, kUrlSource); runNextStep(); } diff --git a/dom/power/test/test_power_basics.html b/dom/power/test/test_power_basics.html index f66154d43aa9..33d87d874d85 100644 --- a/dom/power/test/test_power_basics.html +++ b/dom/power/test/test_power_basics.html @@ -16,6 +16,18 @@ ok('mozPower' in navigator, "navigator.mozPower should exist"); +/** Test permission **/ + +SpecialPowers.removePermission("power", document); + +power = navigator.mozPower; +ok(!power, "Shouldn't be able to access power manager without permission."); + +SpecialPowers.addPermission("power", true, document); + +power = navigator.mozPower; +ok(power, "Shouldn be able to access power manager with permission."); + diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index 4cee58a6f9bc..10d2cd52938d 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -541,7 +541,7 @@ RadioInterfaceLayer.prototype = { newInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED && (!newInfo.roaming || this._isDataRoamingEnabled()); let haveDataConnection = - newInfo.type != GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; + newInfo.type != RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN; if (isRegistered && haveDataConnection) { debug("Radio is ready for data connection."); @@ -680,8 +680,9 @@ RadioInterfaceLayer.prototype = { case nsIRadioInterfaceLayer.CALL_STATE_DIALING: // Fall through... case nsIRadioInterfaceLayer.CALL_STATE_CONNECTED: gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; - gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, - nsIAudioManager.FORCE_NONE); + let force = this.speakerEnabled ? nsIAudioManager.FORCE_SPEAKER + : nsIAudioManager.FORCE_NONE; + gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force); debug("Active call, put audio system into PHONE_STATE_IN_CALL: " + gAudioManager.phoneState); break; diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index 91f966d9a821..5286aaa51171 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -53,14 +53,14 @@ const PDU_HEX_OCTET_SIZE = 4; const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"]; -let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false; -let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false; -// This flag defaults to true since on RIL v6 and later, we get the -// version number via the UNSOLICITED_RIL_CONNECTED parcel. -let RILQUIRKS_V5_LEGACY = true; -let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = false; -let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = false; -let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = false; +let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = libcutils.property_get("ro.moz.ril.callstate_extra_int"); +let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = libcutils.property_get("ro.moz.ril.callstate_down_is_up"); +// This may change at runtime since in RIL v6 and later, we get the version +// number via the UNSOLICITED_RIL_CONNECTED parcel. +let RILQUIRKS_V5_LEGACY = libcutils.property_get("ro.moz.ril.v5_legacy"); +let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = libcutils.property_get("ro.moz.ril.dial_emergency_call"); +let RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = libcutils.property_get("ro.moz.ril.emergency_by_default"); +let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = libcutils.property_get("ro.moz.ril.simstate_extra_field"); // Marker object. let PENDING_NETWORK_TYPE = {}; @@ -691,71 +691,6 @@ let RIL = { } }, - - /** - * Set quirk flags based on the RIL model detected. Note that this - * requires the RIL being "warmed up" first, which happens when on - * an incoming or outgoing voice call or data call. - */ - rilQuirksInitialized: false, - initRILQuirks: function initRILQuirks() { - if (this.rilQuirksInitialized) { - return; - } - - let ril_impl = libcutils.property_get("gsm.version.ril-impl"); - if (DEBUG) debug("Detected RIL implementation " + ril_impl); - switch (ril_impl) { - case "Samsung RIL(IPC) v2.0": - // The Samsung Galaxy S2 I-9100 radio sends an extra Uint32 in the - // call state. - let model_id = libcutils.property_get("ril.model_id"); - if (DEBUG) debug("Detected RIL model " + model_id); - if (!model_id) { - // On some RIL models, the RIL has to be "warmed up" for us to read this property. - // It apparently isn't warmed up yet, going to try again later. - if (DEBUG) debug("Could not detect correct model_id. Going to try later."); - return; - } - if (model_id == "I9100") { - if (DEBUG) { - debug("Detected I9100, enabling " + - "RILQUIRKS_CALLSTATE_EXTRA_UINT32, " + - "RILQUIRKS_DATACALLSTATE_DOWN_IS_UP, " + - "RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL."); - } - RILQUIRKS_CALLSTATE_EXTRA_UINT32 = true; - RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = true; - RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = true; - } - if (model_id == "I9023" || model_id == "I9020") { - if (DEBUG) { - debug("Detected I9020/I9023, enabling " + - "RILQUIRKS_DATACALLSTATE_DOWN_IS_UP"); - } - RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = true; - } - break; - case "Qualcomm RIL 1.0": - let product_model = libcutils.property_get("ro.product.model"); - if (DEBUG) debug("Detected product model " + product_model); - if (product_model == "otoro1") { - if (DEBUG) debug("Enabling RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS."); - RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = true; - } - if (DEBUG) { - debug("Detected Qualcomm RIL 1.0, " + - "disabling RILQUIRKS_V5_LEGACY and " + - "enabling RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE."); - } - RILQUIRKS_V5_LEGACY = false; - RILQUIRKS_MODEM_DEFAULTS_TO_EMERGENCY_MODE = true; - break; - } - - this.rilQuirksInitialized = true; - }, - /** * Parse an integer from a string, falling back to a default value * if the the provided value is not a string or does not contain a valid @@ -2261,8 +2196,6 @@ let RIL = { }, _processVoiceRegistrationState: function _processVoiceRegistrationState(state) { - this.initRILQuirks(); - let rs = this.voiceRegistrationState; let stateChanged = this._processCREG(rs, state); if (stateChanged && rs.connected) { @@ -2951,8 +2884,6 @@ RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, opti return; } - this.initRILQuirks(); - let calls_length = 0; // The RIL won't even send us the length integer if there are no active calls. // So only read this integer if the parcel actually has it. @@ -3477,7 +3408,6 @@ RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) { return; } - this.initRILQuirks(); if (!length) { this._processDataCallList(null); return; @@ -3736,7 +3666,6 @@ RIL[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) { // Prevent response id collision between UNSOLICITED_RIL_CONNECTED and // UNSOLICITED_VOICE_RADIO_TECH_CHANGED for Akami on gingerbread branch. if (!length) { - this.initRILQuirks(); return; } diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index 1d952e4adb55..26a1d956159d 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -1578,6 +1578,25 @@ DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aP mDevice->Draw(4, 0); } +TemporaryRef +DrawTargetD2D::ConvertRectToGeometry(const D2D1_RECT_F& aRect) +{ + RefPtr rectGeom; + factory()->CreateRectangleGeometry(&aRect, byRef(rectGeom)); + return rectGeom.forget(); +} + +static D2D1_RECT_F +IntersectRect(const D2D1_RECT_F& aRect1, const D2D1_RECT_F& aRect2) +{ + D2D1_RECT_F result; + result.left = max(aRect1.left, aRect2.left); + result.top = max(aRect1.top, aRect2.top); + result.right = min(aRect1.right, aRect2.right); + result.bottom = min(aRect1.bottom, aRect2.bottom); + return result; +} + TemporaryRef DrawTargetD2D::GetClippedGeometry() { @@ -1585,46 +1604,58 @@ DrawTargetD2D::GetClippedGeometry() return mCurrentClippedGeometry; } - RefPtr currentSink; - - factory()->CreatePathGeometry(byRef(mCurrentClippedGeometry)); - mCurrentClippedGeometry->Open(byRef(currentSink)); - + // if pathGeom is null then pathRect represents the path. + RefPtr pathGeom; + D2D1_RECT_F pathRect; std::vector::iterator iter = mPushedClips.begin(); - if (iter->mPath) { + RefPtr tmpGeometry; + factory()->CreatePathGeometry(byRef(tmpGeometry)); + RefPtr currentSink; + tmpGeometry->Open(byRef(currentSink)); iter->mPath->GetGeometry()->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, iter->mTransform, currentSink); + currentSink->Close(); + pathGeom = tmpGeometry.forget(); } else { - RefPtr rectGeom; - factory()->CreateRectangleGeometry(iter->mBounds, byRef(rectGeom)); - rectGeom->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, - D2D1::IdentityMatrix(), currentSink); + pathRect = iter->mBounds; } - currentSink->Close(); iter++; for (;iter != mPushedClips.end(); iter++) { + if (!pathGeom) { + if (iter->mPath) { + pathGeom = ConvertRectToGeometry(pathRect); + } else { + pathRect = IntersectRect(pathRect, iter->mBounds); + continue; + } + } + RefPtr newGeom; factory()->CreatePathGeometry(byRef(newGeom)); + RefPtr currentSink; newGeom->Open(byRef(currentSink)); if (iter->mPath) { - mCurrentClippedGeometry->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT, - iter->mTransform, currentSink); + pathGeom->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT, + iter->mTransform, currentSink); } else { - RefPtr rectGeom; - factory()->CreateRectangleGeometry(iter->mBounds, byRef(rectGeom)); - mCurrentClippedGeometry->CombineWithGeometry(rectGeom, D2D1_COMBINE_MODE_INTERSECT, - D2D1::IdentityMatrix(), currentSink); + RefPtr rectGeom = ConvertRectToGeometry(iter->mBounds); + pathGeom->CombineWithGeometry(rectGeom, D2D1_COMBINE_MODE_INTERSECT, + D2D1::IdentityMatrix(), currentSink); } currentSink->Close(); - mCurrentClippedGeometry = newGeom; + pathGeom = newGeom.forget(); } + if (!pathGeom) { + pathGeom = ConvertRectToGeometry(pathRect); + } + mCurrentClippedGeometry = pathGeom.forget(); return mCurrentClippedGeometry; } diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index 3cea6b7968d9..88069ba9ce2c 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -182,6 +182,7 @@ private: const DrawOptions &aOptions = DrawOptions()); TemporaryRef CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat); + TemporaryRef ConvertRectToGeometry(const D2D1_RECT_F& aRect); TemporaryRef GetClippedGeometry(); TemporaryRef CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f); @@ -205,7 +206,7 @@ private: RefPtr mDevice; RefPtr mTexture; RefPtr mCurrentClipMaskTexture; - RefPtr mCurrentClippedGeometry; + RefPtr mCurrentClippedGeometry; mutable RefPtr mRT; // We store this to prevent excessive SetTextRenderingParams calls. diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 484f9462d5e0..8502de83c4f3 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -181,6 +181,13 @@ public: * EndTransaction returns. */ virtual void BeginTransactionWithTarget(gfxContext* aTarget) = 0; + + enum EndTransactionFlags { + END_DEFAULT = 0, + END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase + END_NO_COMPOSITE = 1 << 1 // Do not composite after drawing thebes layer contents. + }; + /** * Attempts to end an "empty transaction". There must have been no * changes to the layer tree since the BeginTransaction(). @@ -189,7 +196,7 @@ public: * returns false, and the caller must proceed with a normal layer tree * update and EndTransaction. */ - virtual bool EndEmptyTransaction() = 0; + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) = 0; /** * Function called to draw the contents of each ThebesLayer. @@ -223,11 +230,6 @@ public: const nsIntRegion& aRegionToInvalidate, void* aCallbackData); - enum EndTransactionFlags { - END_DEFAULT = 0, - END_NO_IMMEDIATE_REDRAW = 1 << 0 // Do not perform the drawing phase - }; - /** * Finish the construction phase of the transaction, perform the * drawing phase, and end the transaction. @@ -239,6 +241,9 @@ public: void* aCallbackData, EndTransactionFlags aFlags = END_DEFAULT) = 0; + virtual bool HasShadowManagerInternal() const { return false; } + bool HasShadowManager() const { return HasShadowManagerInternal(); } + bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; } /** diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index dfab8595c156..195a4ff89f0a 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -421,6 +421,12 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback, mTransactionIncomplete = false; + if (aFlags & END_NO_COMPOSITE) { + // TODO: We should really just set mTarget to null and make sure we can handle that further down the call chain + nsRefPtr surf = gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(1, 1), gfxASurface::CONTENT_COLOR); + mTarget = new gfxContext(surf); + } + if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) { nsIntRect clipRect; if (HasShadowManager()) { @@ -450,9 +456,19 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback, } } - PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr); - if (mWidget) { - FlashWidgetUpdateArea(mTarget); + if (aFlags & END_NO_COMPOSITE) { + if (IsRetained()) { + // Clip the destination out so that we don't draw to it, and + // only end up validating ThebesLayers. + mTarget->Clip(gfxRect(0, 0, 0, 0)); + PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr); + } + // If we're not retained, then don't composite means do nothing at all. + } else { + PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr); + if (mWidget) { + FlashWidgetUpdateArea(mTarget); + } } if (!mTransactionIncomplete) { @@ -508,13 +524,13 @@ BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext) } bool -BasicLayerManager::EndEmptyTransaction() +BasicLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) { if (!mRoot) { return false; } - return EndTransactionInternal(nullptr, nullptr); + return EndTransactionInternal(nullptr, nullptr, aFlags); } void @@ -1039,9 +1055,9 @@ BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback, } bool -BasicShadowLayerManager::EndEmptyTransaction() +BasicShadowLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) { - if (!BasicLayerManager::EndEmptyTransaction()) { + if (!BasicLayerManager::EndEmptyTransaction(aFlags)) { // Return without calling ForwardTransaction. This leaves the // ShadowLayerForwarder transaction open; the following // EndTransaction will complete it. diff --git a/gfx/layers/basic/BasicLayers.h b/gfx/layers/basic/BasicLayers.h index 44e9de6f31d9..eae41858d109 100644 --- a/gfx/layers/basic/BasicLayers.h +++ b/gfx/layers/basic/BasicLayers.h @@ -87,7 +87,7 @@ public: virtual void BeginTransaction(); virtual void BeginTransactionWithTarget(gfxContext* aTarget); - virtual bool EndEmptyTransaction(); + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); virtual void EndTransaction(DrawThebesLayerCallback aCallback, void* aCallbackData, EndTransactionFlags aFlags = END_DEFAULT); @@ -150,8 +150,6 @@ public: void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed); virtual bool IsCompositingCheap() { return false; } - virtual bool HasShadowManagerInternal() const { return false; } - bool HasShadowManager() const { return HasShadowManagerInternal(); } virtual PRInt32 GetMaxTextureSize() const { return PR_INT32_MAX; } protected: @@ -221,7 +219,7 @@ public: virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering, ScreenRotation aRotation) MOZ_OVERRIDE; virtual void BeginTransactionWithTarget(gfxContext* aTarget); - virtual bool EndEmptyTransaction(); + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); virtual void EndTransaction(DrawThebesLayerCallback aCallback, void* aCallbackData, EndTransactionFlags aFlags = END_DEFAULT); diff --git a/gfx/layers/basic/BasicThebesLayer.cpp b/gfx/layers/basic/BasicThebesLayer.cpp index 047edd666c37..287fcc3aebc0 100644 --- a/gfx/layers/basic/BasicThebesLayer.cpp +++ b/gfx/layers/basic/BasicThebesLayer.cpp @@ -27,9 +27,7 @@ BasicThebesLayer::CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize referenceSurface = defaultTarget->CurrentSurface(); } else { nsIWidget* widget = BasicManager()->GetRetainerWidget(); - if (widget) { - referenceSurface = widget->GetThebesSurface(); - } else { + if (!widget || !(referenceSurface = widget->GetThebesSurface())) { referenceSurface = BasicManager()->GetTarget()->CurrentSurface(); } } diff --git a/gfx/layers/d3d10/ContainerLayerD3D10.cpp b/gfx/layers/d3d10/ContainerLayerD3D10.cpp index 93d522add42c..0641501404b0 100644 --- a/gfx/layers/d3d10/ContainerLayerD3D10.cpp +++ b/gfx/layers/d3d10/ContainerLayerD3D10.cpp @@ -28,82 +28,95 @@ ContainerLayerD3D10::~ContainerLayerD3D10() RemoveChild(mFirstChild); } } +template +static void +ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter) +{ + aChild->SetParent(aContainer); + if (!aAfter) { + Layer *oldFirstChild = aContainer->GetFirstChild(); + aContainer->mFirstChild = aChild; + aChild->SetNextSibling(oldFirstChild); + aChild->SetPrevSibling(nullptr); + if (oldFirstChild) { + oldFirstChild->SetPrevSibling(aChild); + } else { + aContainer->mLastChild = aChild; + } + NS_ADDREF(aChild); + aContainer->DidInsertChild(aChild); + return; + } + for (Layer *child = aContainer->GetFirstChild(); + child; child = child->GetNextSibling()) { + if (aAfter == child) { + Layer *oldNextSibling = child->GetNextSibling(); + child->SetNextSibling(aChild); + aChild->SetNextSibling(oldNextSibling); + if (oldNextSibling) { + oldNextSibling->SetPrevSibling(aChild); + } else { + aContainer->mLastChild = aChild; + } + aChild->SetPrevSibling(child); + NS_ADDREF(aChild); + aContainer->DidInsertChild(aChild); + return; + } + } + NS_WARNING("Failed to find aAfter layer!"); +} + +template +static void +ContainerRemoveChild(Container* aContainer, Layer* aChild) +{ + if (aContainer->GetFirstChild() == aChild) { + aContainer->mFirstChild = aContainer->GetFirstChild()->GetNextSibling(); + if (aContainer->mFirstChild) { + aContainer->mFirstChild->SetPrevSibling(nullptr); + } else { + aContainer->mLastChild = nullptr; + } + aChild->SetNextSibling(nullptr); + aChild->SetPrevSibling(nullptr); + aChild->SetParent(nullptr); + aContainer->DidRemoveChild(aChild); + NS_RELEASE(aChild); + return; + } + Layer *lastChild = nullptr; + for (Layer *child = aContainer->GetFirstChild(); child; + child = child->GetNextSibling()) { + if (child == aChild) { + // We're sure this is not our first child. So lastChild != NULL. + lastChild->SetNextSibling(child->GetNextSibling()); + if (child->GetNextSibling()) { + child->GetNextSibling()->SetPrevSibling(lastChild); + } else { + aContainer->mLastChild = lastChild; + } + child->SetNextSibling(nullptr); + child->SetPrevSibling(nullptr); + child->SetParent(nullptr); + aContainer->DidRemoveChild(aChild); + NS_RELEASE(aChild); + return; + } + lastChild = child; + } +} void ContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter) { - aChild->SetParent(this); - if (!aAfter) { - Layer *oldFirstChild = GetFirstChild(); - mFirstChild = aChild; - aChild->SetNextSibling(oldFirstChild); - aChild->SetPrevSibling(nullptr); - if (oldFirstChild) { - oldFirstChild->SetPrevSibling(aChild); - } else { - mLastChild = aChild; - } - NS_ADDREF(aChild); - DidInsertChild(aChild); - return; - } - for (Layer *child = GetFirstChild(); - child; child = child->GetNextSibling()) { - if (aAfter == child) { - Layer *oldNextSibling = child->GetNextSibling(); - child->SetNextSibling(aChild); - aChild->SetNextSibling(oldNextSibling); - if (oldNextSibling) { - oldNextSibling->SetPrevSibling(aChild); - } else { - mLastChild = aChild; - } - aChild->SetPrevSibling(child); - NS_ADDREF(aChild); - DidInsertChild(aChild); - return; - } - } - NS_WARNING("Failed to find aAfter layer!"); + ContainerInsertAfter(this, aChild, aAfter); } void ContainerLayerD3D10::RemoveChild(Layer *aChild) { - if (GetFirstChild() == aChild) { - mFirstChild = GetFirstChild()->GetNextSibling(); - if (mFirstChild) { - mFirstChild->SetPrevSibling(nullptr); - } else { - mLastChild = nullptr; - } - aChild->SetNextSibling(nullptr); - aChild->SetPrevSibling(nullptr); - aChild->SetParent(nullptr); - DidRemoveChild(aChild); - NS_RELEASE(aChild); - return; - } - Layer *lastChild = nullptr; - for (Layer *child = GetFirstChild(); child; - child = child->GetNextSibling()) { - if (child == aChild) { - // We're sure this is not our first child. So lastChild != NULL. - lastChild->SetNextSibling(child->GetNextSibling()); - if (child->GetNextSibling()) { - child->GetNextSibling()->SetPrevSibling(lastChild); - } else { - mLastChild = lastChild; - } - child->SetNextSibling(nullptr); - child->SetPrevSibling(nullptr); - child->SetParent(nullptr); - DidRemoveChild(aChild); - NS_RELEASE(aChild); - return; - } - lastChild = child; - } + ContainerRemoveChild(this, aChild); } Layer* @@ -368,18 +381,23 @@ ShadowContainerLayerD3D10::ShadowContainerLayerD3D10(LayerManagerD3D10 *aManager mImplData = static_cast(this); } -ShadowContainerLayerD3D10::~ShadowContainerLayerD3D10() {} +ShadowContainerLayerD3D10::~ShadowContainerLayerD3D10() +{ + while (mFirstChild) { + RemoveChild(mFirstChild); + } +} void ShadowContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter) { - mFirstChild = aChild; + ContainerInsertAfter(this, aChild, aAfter); } void ShadowContainerLayerD3D10::RemoveChild(Layer* aChild) { - + ContainerRemoveChild(this, aChild); } void @@ -409,6 +427,10 @@ ShadowContainerLayerD3D10::Validate() void ShadowContainerLayerD3D10::LayerManagerDestroyed() { + while (mFirstChild) { + GetFirstChildD3D10()->LayerManagerDestroyed(); + RemoveChild(mFirstChild); + } } } /* layers */ diff --git a/gfx/layers/d3d10/ContainerLayerD3D10.h b/gfx/layers/d3d10/ContainerLayerD3D10.h index aed548dbda6f..25e526fd1ca3 100644 --- a/gfx/layers/d3d10/ContainerLayerD3D10.h +++ b/gfx/layers/d3d10/ContainerLayerD3D10.h @@ -11,9 +11,18 @@ namespace mozilla { namespace layers { +template +static void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter); +template +static void ContainerRemoveChild(Container* aContainer, Layer* aChild); + class ContainerLayerD3D10 : public ContainerLayer, public LayerD3D10 { + template + friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter); + template + friend void ContainerRemoveChild(Container* aContainer, Layer* aChild); public: ContainerLayerD3D10(LayerManagerD3D10 *aManager); ~ContainerLayerD3D10(); @@ -47,6 +56,10 @@ public: class ShadowContainerLayerD3D10 : public ShadowContainerLayer, public LayerD3D10 { + template + friend void ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter); + template + friend void ContainerRemoveChild(Container* aContainer, Layer* aChild); public: ShadowContainerLayerD3D10(LayerManagerD3D10 *aManager); ~ShadowContainerLayerD3D10(); diff --git a/gfx/layers/d3d10/LayerManagerD3D10.cpp b/gfx/layers/d3d10/LayerManagerD3D10.cpp index 245e759f7031..3d5229dd925a 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.cpp +++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp @@ -200,7 +200,7 @@ LayerManagerD3D10::Initialize(bool force) mInputLayout = attachments->mInputLayout; } - if (HasShadowManager()) { + if (ShadowLayerForwarder::HasShadowManager()) { reporter.SetSuccessful(); return true; } @@ -335,12 +335,12 @@ LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget) } bool -LayerManagerD3D10::EndEmptyTransaction() +LayerManagerD3D10::EndEmptyTransaction(EndTransactionFlags aFlags) { if (!mRoot) return false; - EndTransaction(nullptr, nullptr); + EndTransaction(nullptr, nullptr, aFlags); return true; } @@ -362,7 +362,7 @@ LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback, Log(); #endif - Render(); + Render(aFlags); mCurrentCallbackInfo.Callback = nullptr; mCurrentCallbackInfo.CallbackData = nullptr; } @@ -703,10 +703,14 @@ LayerManagerD3D10::EnsureReadbackManager() } void -LayerManagerD3D10::Render() +LayerManagerD3D10::Render(EndTransactionFlags aFlags) { static_cast(mRoot->ImplData())->Validate(); + if (aFlags & END_NO_COMPOSITE) { + return; + } + SetupPipeline(); float black[] = { 0, 0, 0, 0 }; diff --git a/gfx/layers/d3d10/LayerManagerD3D10.h b/gfx/layers/d3d10/LayerManagerD3D10.h index cf05bba8ee56..befc58966190 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.h +++ b/gfx/layers/d3d10/LayerManagerD3D10.h @@ -85,7 +85,7 @@ public: virtual void BeginTransactionWithTarget(gfxContext* aTarget); - virtual bool EndEmptyTransaction(); + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); struct CallbackInfo { DrawThebesLayerCallback Callback; @@ -178,7 +178,7 @@ private: void VerifyBufferSize(); void EnsureReadbackManager(); - void Render(); + void Render(EndTransactionFlags aFlags); nsRefPtr mDevice; diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.cpp b/gfx/layers/d3d9/CanvasLayerD3D9.cpp index 69f4991a2a3e..45f7cc961414 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -187,6 +187,9 @@ void CanvasLayerD3D9::RenderLayer() { UpdateSurface(); + if (mD3DManager->CompositingDisabled()) { + return; + } FireDidTransactionCallback(); if (!mTexture) @@ -355,7 +358,7 @@ ShadowCanvasLayerD3D9::GetLayer() void ShadowCanvasLayerD3D9::RenderLayer() { - if (!mBuffer) { + if (!mBuffer || mD3DManager->CompositingDisabled()) { return; } diff --git a/gfx/layers/d3d9/ColorLayerD3D9.cpp b/gfx/layers/d3d9/ColorLayerD3D9.cpp index 7e70a756fac0..8a52661f0027 100644 --- a/gfx/layers/d3d9/ColorLayerD3D9.cpp +++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp @@ -19,6 +19,9 @@ RenderColorLayerD3D9(ColorLayer* aLayer, LayerManagerD3D9 *aManager) { // XXX we might be able to improve performance by using // IDirect3DDevice9::Clear + if (aManager->CompositingDisabled()) { + return; + } nsIntRect visibleRect = aLayer->GetEffectiveVisibleRegion().GetBounds(); diff --git a/gfx/layers/d3d9/ContainerLayerD3D9.cpp b/gfx/layers/d3d9/ContainerLayerD3D9.cpp index 34722afd7e00..9526cb2b23cc 100644 --- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp +++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp @@ -147,20 +147,23 @@ ContainerRender(Container* aContainer, aContainer->mSupportsComponentAlphaChildren = false; if (useIntermediate) { - aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); - HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1, - D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, - D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), - NULL); - if (FAILED(hr)) { - aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"), - hr); - return; - } - nsRefPtr renderSurface; - renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); - aManager->device()->SetRenderTarget(0, renderSurface); + if (!aManager->CompositingDisabled()) { + aManager->device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); + HRESULT hr = aManager->device()->CreateTexture(visibleRect.width, visibleRect.height, 1, + D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, + D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), + NULL); + if (FAILED(hr)) { + aManager->ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"), + hr); + return; + } + + nsRefPtr renderSurface; + renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); + aManager->device()->SetRenderTarget(0, renderSurface); + } if (aContainer->mVisibleRegion.GetNumRects() == 1 && (aContainer->GetContentFlags() & aContainer->CONTENT_OPAQUE)) { @@ -182,12 +185,14 @@ ContainerRender(Container* aContainer, ::OffsetRect(&src, visibleRect.x + PRInt32(transform.x0), visibleRect.y + PRInt32(transform.y0)); - hr = aManager->device()-> - StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); + if (!aManager->CompositingDisabled()) { + hr = aManager->device()-> + StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); + } } if (hr == S_OK) { aContainer->mSupportsComponentAlphaChildren = true; - } else { + } else if (!aManager->CompositingDisabled()) { aManager->device()-> Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); } @@ -256,7 +261,7 @@ ContainerRender(Container* aContainer, aManager->device()->SetScissorRect(&containerD3D9ClipRect); - if (useIntermediate) { + if (useIntermediate && !aManager->CompositingDisabled()) { aManager->device()->SetRenderTarget(0, previousRenderTarget); aManager->device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); aManager->device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); diff --git a/gfx/layers/d3d9/ImageLayerD3D9.cpp b/gfx/layers/d3d9/ImageLayerD3D9.cpp index 652f45e5b6e6..bcd7f4f59242 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.cpp +++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp @@ -355,7 +355,7 @@ void ImageLayerD3D9::RenderLayer() { ImageContainer *container = GetContainer(); - if (!container) { + if (!container || mD3DManager->CompositingDisabled()) { return; } @@ -609,6 +609,10 @@ ShadowImageLayerD3D9::GetLayer() void ShadowImageLayerD3D9::RenderLayer() { + if (mD3DManager->CompositingDisabled()) { + return; + } + if (mBuffer) { mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion()); } else if (mYCbCrImage) { diff --git a/gfx/layers/d3d9/LayerManagerD3D9.cpp b/gfx/layers/d3d9/LayerManagerD3D9.cpp index d847d8eb720b..789d4ab90c69 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.cpp +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp @@ -121,7 +121,7 @@ LayerManagerD3D9::EndConstruction() } bool -LayerManagerD3D9::EndEmptyTransaction() +LayerManagerD3D9::EndEmptyTransaction(EndTransactionFlags aFlags) { // If the device reset count from our last EndTransaction doesn't match // the current device reset count, the device must have been reset one or @@ -130,7 +130,7 @@ LayerManagerD3D9::EndEmptyTransaction() if (!mRoot || mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) return false; - EndTransaction(nullptr, nullptr); + EndTransaction(nullptr, nullptr, aFlags); return true; } @@ -149,6 +149,7 @@ LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback, // so we don't need to pass any global transform here. mRoot->ComputeEffectiveTransforms(gfx3DMatrix()); + SetCompositingDisabled(aFlags & END_NO_COMPOSITE); Render(); /* Clean this out for sanity */ mCurrentCallbackInfo.Callback = NULL; @@ -284,6 +285,12 @@ LayerManagerD3D9::Render() deviceManager()->SetupRenderState(); SetupPipeline(); + + if (CompositingDisabled()) { + static_cast(mRoot->ImplData())->RenderLayer(); + return; + } + nsIntRect rect; mWidget->GetClientBounds(rect); diff --git a/gfx/layers/d3d9/LayerManagerD3D9.h b/gfx/layers/d3d9/LayerManagerD3D9.h index d478f92b0baf..d5f563196eb4 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.h +++ b/gfx/layers/d3d9/LayerManagerD3D9.h @@ -98,7 +98,7 @@ public: void EndConstruction(); - virtual bool EndEmptyTransaction(); + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); struct CallbackInfo { DrawThebesLayerCallback Callback; @@ -176,6 +176,9 @@ public: void ReportFailure(const nsACString &aMsg, HRESULT aCode); + bool CompositingDisabled() { return mCompositingDisabled; } + void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; } + private: /* Default device manager instance */ static DeviceManagerD3D9 *mDefaultDeviceManager; @@ -208,6 +211,12 @@ private: */ PRUint32 mDeviceResetCount; + /* + * True if we should only be drawing layer contents, not + * compositing them to the target. + */ + bool mCompositingDisabled; + /* * Render the current layer tree to the active target. */ diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 3ff86edd1c4e..03af019b310b 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -237,6 +237,10 @@ ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback) mValidRegion = neededRegion; } + if (mD3DManager->CompositingDisabled()) { + return; + } + SetShaderTransformAndOpacity(); if (mode == SURFACE_COMPONENT_ALPHA) { @@ -655,7 +659,7 @@ ShadowThebesLayerD3D9::IsEmpty() void ShadowThebesLayerD3D9::RenderThebesLayer() { - if (!mBuffer) { + if (!mBuffer || mD3DManager->CompositingDisabled()) { return; } NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here"); diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp index 67af403f62ad..5d4dfdc4a074 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -229,6 +229,9 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination, const nsIntPoint& aOffset) { UpdateSurface(); + if (mOGLManager->CompositingDisabled()) { + return; + } FireDidTransactionCallback(); mOGLManager->MakeCurrent(); @@ -446,6 +449,9 @@ ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer, return; } + if (mOGLManager->CompositingDisabled()) { + return; + } mOGLManager->MakeCurrent(); gfx3DMatrix effectiveTransform = GetEffectiveTransform(); diff --git a/gfx/layers/opengl/ColorLayerOGL.cpp b/gfx/layers/opengl/ColorLayerOGL.cpp index 4a481df285aa..47ab0adaeeee 100644 --- a/gfx/layers/opengl/ColorLayerOGL.cpp +++ b/gfx/layers/opengl/ColorLayerOGL.cpp @@ -12,6 +12,10 @@ static void RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, const nsIntPoint& aOffset) { + if (aManager->CompositingDisabled()) { + return; + } + aManager->MakeCurrent(); // XXX we might be able to improve performance by using glClear diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index e5f6ad5fa6e7..0d423cec6fd9 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -179,12 +179,14 @@ ContainerRender(Container* aContainer, } aContainer->gl()->PushViewportRect(); - framebufferRect -= childOffset; - aManager->CreateFBOWithTexture(framebufferRect, - mode, - aPreviousFrameBuffer, - &frameBuffer, - &containerSurface); + framebufferRect -= childOffset; + if (!aManager->CompositingDisabled()) { + aManager->CreateFBOWithTexture(framebufferRect, + mode, + aPreviousFrameBuffer, + &frameBuffer, + &containerSurface); + } childOffset.x = visibleRect.x; childOffset.y = visibleRect.y; } else { @@ -239,45 +241,47 @@ ContainerRender(Container* aContainer, aManager->SetupPipeline(viewport.width, viewport.height, LayerManagerOGL::ApplyWorldTransform); aContainer->gl()->PopScissorRect(); - aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer); - aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0); + if (!aManager->CompositingDisabled()) { + aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer); - aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface); + aContainer->gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - MaskType maskType = MaskNone; - if (aContainer->GetMaskLayer()) { - if (!aContainer->GetTransform().CanDraw2D()) { - maskType = Mask3d; - } else { - maskType = Mask2d; + aContainer->gl()->fBindTexture(aManager->FBOTextureTarget(), containerSurface); + + MaskType maskType = MaskNone; + if (aContainer->GetMaskLayer()) { + if (!aContainer->GetTransform().CanDraw2D()) { + maskType = Mask3d; + } else { + maskType = Mask2d; + } } + ShaderProgramOGL *rgb = + aManager->GetFBOLayerProgram(maskType); + + rgb->Activate(); + rgb->SetLayerQuadRect(visibleRect); + rgb->SetLayerTransform(transform); + rgb->SetLayerOpacity(opacity); + rgb->SetRenderOffset(aOffset); + rgb->SetTextureUnit(0); + rgb->LoadMask(aContainer->GetMaskLayer()); + + if (rgb->GetTexCoordMultiplierUniformLocation() != -1) { + // 2DRect case, get the multiplier right for a sampler2DRect + rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height); + } + + // Drawing is always flipped, but when copying between surfaces we want to avoid + // this. Pass true for the flip parameter to introduce a second flip + // that cancels the other one out. + aManager->BindAndDrawQuad(rgb, true); + + // Clean up resources. This also unbinds the texture. + aContainer->gl()->fDeleteTextures(1, &containerSurface); } - ShaderProgramOGL *rgb = - aManager->GetFBOLayerProgram(maskType); - - rgb->Activate(); - rgb->SetLayerQuadRect(visibleRect); - rgb->SetLayerTransform(transform); - rgb->SetLayerOpacity(opacity); - rgb->SetRenderOffset(aOffset); - rgb->SetTextureUnit(0); - rgb->LoadMask(aContainer->GetMaskLayer()); - - if (rgb->GetTexCoordMultiplierUniformLocation() != -1) { - // 2DRect case, get the multiplier right for a sampler2DRect - rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height); - } - - // Drawing is always flipped, but when copying between surfaces we want to avoid - // this. Pass true for the flip parameter to introduce a second flip - // that cancels the other one out. - aManager->BindAndDrawQuad(rgb, true); - - // Clean up resources. This also unbinds the texture. - aContainer->gl()->fDeleteTextures(1, &containerSurface); } else { aContainer->gl()->PopScissorRect(); } diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index abd2c1531381..6af846cc0a57 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -225,7 +225,7 @@ ImageLayerOGL::RenderLayer(int, { nsRefPtr container = GetContainer(); - if (!container) + if (!container || mOGLManager->CompositingDisabled()) return; mOGLManager->MakeCurrent(); @@ -875,6 +875,9 @@ void ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset) { + if (mOGLManager->CompositingDisabled()) { + return; + } mOGLManager->MakeCurrent(); if (mImageContainerID) { ImageContainerParent::SetCompositorIDForImage(mImageContainerID, diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 8631600da77f..01716d58815d 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -380,12 +380,12 @@ LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget) } bool -LayerManagerOGL::EndEmptyTransaction() +LayerManagerOGL::EndEmptyTransaction(EndTransactionFlags aFlags) { if (!mRoot) return false; - EndTransaction(nullptr, nullptr); + EndTransaction(nullptr, nullptr, aFlags); return true; } @@ -411,6 +411,7 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback, mThebesLayerCallback = aCallback; mThebesLayerCallbackData = aCallbackData; + SetCompositingDisabled(aFlags & END_NO_COMPOSITE); Render(); @@ -774,6 +775,13 @@ LayerManagerOGL::Render() mGLContext->fScissor(0, 0, width, height); } + if (CompositingDisabled()) { + RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, + nsIntPoint(0, 0)); + mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0); + return; + } + mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST); // If the Java compositor is being used, this clear will be done in diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index d86409561600..d5913e7e2c45 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -102,7 +102,7 @@ public: void EndConstruction(); - virtual bool EndEmptyTransaction(); + virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); virtual void EndTransaction(DrawThebesLayerCallback aCallback, void* aCallbackData, EndTransactionFlags aFlags = END_DEFAULT); @@ -350,6 +350,9 @@ public: */ void SetSurfaceSize(int width, int height); + bool CompositingDisabled() { return mCompositingDisabled; } + void SetCompositingDisabled(bool aCompositingDisabled) { mCompositingDisabled = aCompositingDisabled; } + private: /** Widget associated with this layer manager */ nsIWidget *mWidget; @@ -391,6 +394,7 @@ private: /** Misc */ bool mHasBGRA; + bool mCompositingDisabled; /** * When rendering to an EGL surface (e.g. on Android), we rely on being told diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index 3ca49209f2aa..eb2e79a52efc 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -88,6 +88,8 @@ public: void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager, PRUint32 aFlags); + void EndUpdate(); + nsIntSize GetSize() { if (mTexImage) return mTexImage->GetSize(); @@ -108,6 +110,17 @@ protected: bool mInitialised; }; +void ThebesLayerBufferOGL::EndUpdate() +{ + if (mTexImage && mTexImage->InUpdate()) { + mTexImage->EndUpdate(); + } + + if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) { + mTexImageOnWhite->EndUpdate(); + } +} + void ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager, @@ -118,13 +131,7 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, if (!mTexImage || !Initialised()) return; - if (mTexImage->InUpdate()) { - mTexImage->EndUpdate(); - } - - if (mTexImageOnWhite && mTexImageOnWhite->InUpdate()) { - mTexImageOnWhite->EndUpdate(); - } + EndUpdate(); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { @@ -838,6 +845,11 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, } } + if (mOGLManager->CompositingDisabled()) { + mBuffer->EndUpdate(); + return; + } + // Drawing thebes layers can change the current context, reset it. gl()->MakeCurrent(); @@ -1099,7 +1111,7 @@ void ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset) { - if (!mBuffer) { + if (!mBuffer || mOGLManager->CompositingDisabled()) { return; } NS_ABORT_IF_FALSE(mBuffer, "should have a buffer here"); diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index e8b9866b590b..61526659a52d 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -86,9 +86,11 @@ class EvalScriptGuard EvalCacheLookup lookup_; EvalCache::AddPtr p_; + Rooted lookupStr_; + public: EvalScriptGuard(JSContext *cx) - : cx_(cx), script_(cx) + : cx_(cx), script_(cx), lookupStr_(cx) { lookup_.str = NULL; } @@ -98,6 +100,7 @@ class EvalScriptGuard CallDestroyScriptHook(cx_->runtime->defaultFreeOp(), script_); script_->isActiveEval = false; script_->isCachedEval = true; + lookup_.str = lookupStr_; if (lookup_.str && IsEvalCacheCandidate(script_)) cx_->runtime->evalCache.relookupOrAdd(p_, lookup_, script_); } @@ -105,6 +108,7 @@ class EvalScriptGuard void lookupInEvalCache(JSLinearString *str, JSFunction *caller, unsigned staticLevel) { + lookupStr_ = str; lookup_.str = str; lookup_.caller = caller; lookup_.staticLevel = staticLevel; diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 8c3202b0af93..a0ffcf58e61b 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -823,6 +823,8 @@ MapIteratorObject::next_impl(JSContext *cx, CallArgs args) } Value pair[2] = { range->front().key.get(), range->front().value }; + AutoValueArray root(cx, pair, 2); + JSObject *pairobj = NewDenseCopiedArray(cx, 2, pair); if (!pairobj) return false; @@ -970,7 +972,7 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp) if (args.hasDefined(0)) { ForOfIterator iter(cx, args[0]); while (iter.next()) { - JSObject *pairobj = js_ValueToNonNullObject(cx, iter.value()); + RootedObject pairobj(cx, js_ValueToNonNullObject(cx, iter.value())); if (!pairobj) return false; diff --git a/js/src/config/config.mk b/js/src/config/config.mk index 410a3c8621dd..7700801067b0 100644 --- a/js/src/config/config.mk +++ b/js/src/config/config.mk @@ -87,20 +87,12 @@ endif CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf -ifeq ($(OS_ARCH),QNX) -ifeq ($(OS_TARGET),NTO) -LD := qcc -Vgcc_ntox86 -nostdlib -else -LD := $(CC) -endif -endif - # # Strip off the excessively long version numbers on these platforms, # but save the version to allow multiple versions of the same base # platform to be built in the same tree. # -ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD OSF1 SunOS,$(OS_ARCH))) +ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD SunOS,$(OS_ARCH))) OS_RELEASE := $(basename $(OS_RELEASE)) # Allow the user to ignore the OS_VERSION, which is usually irrelevant. diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index b494376b5a10..e919d99a64ee 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -500,17 +500,6 @@ endif # HAS_EXTRAEXPORTS endif # IS_COMPONENT endif # AIX -# -# OSF1: add -B symbolic flag for components -# -ifeq ($(OS_ARCH),OSF1) -ifdef IS_COMPONENT -ifeq ($(GNU_CC)$(GNU_CXX),) -EXTRA_DSO_LDOPTS += -B symbolic -endif -endif -endif - # # Linux: add -Bsymbolic flag for components # diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index aa1f251e2def..6501bd3fc9eb 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -303,8 +303,10 @@ frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun, CompileOptions if (!GetOrderedBindings(cx, funsc.bindings, &names)) return false; + RootedPropertyName name(cx); for (unsigned i = 0; i < nargs; i++) { - if (!DefineArg(fn, names[i].maybeName, i, &parser)) + name = names[i].maybeName; + if (!DefineArg(fn, name, i, &parser)) return false; } } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index b53c8d150b17..7d19bc8790df 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -469,7 +469,7 @@ CheckStrictAssignment(JSContext *cx, Parser *parser, ParseNode *lhs) * tc's token stream if pn is NULL. */ bool -CheckStrictBinding(JSContext *cx, Parser *parser, PropertyName *name, ParseNode *pn) +CheckStrictBinding(JSContext *cx, Parser *parser, HandlePropertyName name, ParseNode *pn) { if (!parser->tc->sc->needStrictChecks()) return true; @@ -489,7 +489,7 @@ CheckStrictBinding(JSContext *cx, Parser *parser, PropertyName *name, ParseNode } static bool -ReportBadParameter(JSContext *cx, Parser *parser, JSAtom *name, unsigned errorNumber) +ReportBadParameter(JSContext *cx, Parser *parser, HandlePropertyName name, unsigned errorNumber) { Definition *dn = parser->tc->decls.lookupFirst(name); JSAutoByteString bytes; @@ -878,13 +878,13 @@ MakeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom, Parser *parser) * of CheckDestructuring and its friends. */ typedef bool -(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser); +(*Binder)(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser); static bool -BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser); +BindLet(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser); static bool -BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser); +BindVarOrConst(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser); struct frontend::BindData { BindData(JSContext *cx) : let(cx) {} @@ -1139,7 +1139,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL, * and the formals specified by the Function constructor. */ bool -frontend::DefineArg(ParseNode *pn, PropertyName *name, unsigned i, Parser *parser) +frontend::DefineArg(ParseNode *pn, HandlePropertyName name, unsigned i, Parser *parser) { JSContext *cx = parser->context; TreeContext *tc = parser->tc; @@ -1179,7 +1179,7 @@ frontend::DefineArg(ParseNode *pn, PropertyName *name, unsigned i, Parser *parse #if JS_HAS_DESTRUCTURING static bool -BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser) +BindDestructuringArg(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser) { TreeContext *tc = parser->tc; JS_ASSERT(tc->sc->inFunction()); @@ -1189,13 +1189,13 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser * bindings aren't added to tc->sc->bindings until after all arguments have * been parsed. */ - if (tc->decls.lookupFirst(atom)) { + if (tc->decls.lookupFirst(name)) { parser->reportError(NULL, JSMSG_DESTRUCT_DUP_ARG); return false; } ParseNode *pn = data->pn; - if (!CheckStrictBinding(cx, parser, atom->asPropertyName(), pn)) + if (!CheckStrictBinding(cx, parser, name, pn)) return false; /* @@ -1220,7 +1220,7 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser pn->setOp(JSOP_SETLOCAL); pn->pn_dflags |= PND_BOUND; - return Define(pn, atom, tc); + return Define(pn, name, tc); } #endif /* JS_HAS_DESTRUCTURING */ @@ -2020,11 +2020,11 @@ ReportRedeclaration(JSContext *cx, Parser *parser, ParseNode *pn, bool isConst, * data->pn in a slot of the block object. */ static bool -BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser) +BindLet(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser) { TreeContext *tc = parser->tc; ParseNode *pn = data->pn; - if (!CheckStrictBinding(cx, parser, atom->asPropertyName(), pn)) + if (!CheckStrictBinding(cx, parser, name, pn)) return false; Rooted blockObj(cx, data->let.blockObj); @@ -2040,10 +2040,10 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser) */ if (data->let.varContext == HoistVars) { JS_ASSERT(!tc->atBodyLevel()); - Definition *dn = tc->decls.lookupFirst(atom); + Definition *dn = tc->decls.lookupFirst(name); if (dn && dn->pn_blockid == tc->blockid()) - return ReportRedeclaration(cx, parser, pn, dn->isConst(), atom); - if (!Define(pn, atom, tc, true)) + return ReportRedeclaration(cx, parser, pn, dn->isConst(), name); + if (!Define(pn, name, tc, true)) return false; } @@ -2064,11 +2064,11 @@ BindLet(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser) * slot indexed by blockCount off the class-reserved slot base. */ bool redeclared; - RootedId id(cx, AtomToId(atom)); + RootedId id(cx, NameToId(name)); Shape *shape = StaticBlockObject::addVar(cx, blockObj, id, blockCount, &redeclared); if (!shape) { if (redeclared) - ReportRedeclaration(cx, parser, pn, false, atom); + ReportRedeclaration(cx, parser, pn, false, name); return false; } @@ -2163,20 +2163,18 @@ BindFunctionLocal(JSContext *cx, BindData *data, DefinitionList::Range &defs, Tr } static bool -BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom_, Parser *parser) +BindVarOrConst(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser) { - RootedAtom atom(cx, atom_); - TreeContext *tc = parser->tc; ParseNode *pn = data->pn; /* Default best op for pn is JSOP_NAME; we'll try to improve below. */ pn->setOp(JSOP_NAME); - if (!CheckStrictBinding(cx, parser, atom->asPropertyName(), pn)) + if (!CheckStrictBinding(cx, parser, name, pn)) return false; - StmtInfoTC *stmt = LexicalLookup(tc, atom, NULL, (StmtInfoTC *)NULL); + StmtInfoTC *stmt = LexicalLookup(tc, name, NULL, (StmtInfoTC *)NULL); if (stmt && stmt->type == STMT_WITH) { pn->pn_dflags |= PND_DEOPTIMIZED; @@ -2184,11 +2182,11 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom_, Parser *parser) return true; } - DefinitionList::Range defs = tc->decls.lookupMulti(atom); + DefinitionList::Range defs = tc->decls.lookupMulti(name); JS_ASSERT_IF(stmt, !defs.empty()); if (defs.empty()) { - if (!Define(pn, atom, tc)) + if (!Define(pn, name, tc)) return false; if (data->op == JSOP_DEFCONST) @@ -2210,32 +2208,32 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom_, Parser *parser) Definition *dn = defs.front(); Definition::Kind dn_kind = dn->kind(); if (dn_kind == Definition::ARG) { - JSAutoByteString name; - if (!js_AtomToPrintableString(cx, atom, &name)) + JSAutoByteString bytes; + if (!js_AtomToPrintableString(cx, name, &bytes)) return false; if (data->op == JSOP_DEFCONST) { - parser->reportError(pn, JSMSG_REDECLARED_PARAM, name.ptr()); + parser->reportError(pn, JSMSG_REDECLARED_PARAM, bytes.ptr()); return false; } - if (!parser->reportStrictWarning(pn, JSMSG_VAR_HIDES_ARG, name.ptr())) + if (!parser->reportStrictWarning(pn, JSMSG_VAR_HIDES_ARG, bytes.ptr())) return false; } else { bool error = (data->op == JSOP_DEFCONST || dn_kind == Definition::CONST || (dn_kind == Definition::LET && - (stmt->type != STMT_CATCH || OuterLet(tc, stmt, atom)))); + (stmt->type != STMT_CATCH || OuterLet(tc, stmt, name)))); if (cx->hasStrictOption() ? data->op != JSOP_DEFVAR || dn_kind != Definition::VAR : error) { - JSAutoByteString name; + JSAutoByteString bytes; Parser::Reporter reporter = error ? &Parser::reportError : &Parser::reportStrictWarning; - if (!js_AtomToPrintableString(cx, atom, &name) || + if (!js_AtomToPrintableString(cx, name, &bytes) || !(parser->*reporter)(pn, JSMSG_REDECLARED_VAR, - Definition::kindString(dn_kind), name.ptr())) + Definition::kindString(dn_kind), bytes.ptr())) { return false; } @@ -2329,8 +2327,10 @@ BindDestructuringVar(JSContext *cx, BindData *data, ParseNode *pn, Parser *parse { JS_ASSERT(pn->isKind(PNK_NAME)); + RootedPropertyName name(cx, pn->pn_atom->asPropertyName()); + data->pn = pn; - if (!data->binder(cx, data, pn->pn_atom, parser)) + if (!data->binder(cx, data, name, parser)) return false; /* @@ -3437,7 +3437,7 @@ Parser::tryStatement() case TOK_NAME: { - JSAtom *label = tokenStream.currentToken().name(); + RootedPropertyName label(context, tokenStream.currentToken().name()); pn3 = NewBindingNode(label, this); if (!pn3) return NULL; @@ -4148,7 +4148,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va return NULL; } - PropertyName *name = tokenStream.currentToken().name(); + RootedPropertyName name(context, tokenStream.currentToken().name()); pn2 = NewBindingNode(name, this, varContext); if (!pn2) return NULL; diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 54f0d5770eca..2a458093adca 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -327,7 +327,7 @@ Parser::reportStrictModeError(ParseNode *pn, unsigned errorNumber, ...) } bool -DefineArg(ParseNode *pn, PropertyName *name, unsigned i, Parser *parser); +DefineArg(ParseNode *pn, HandlePropertyName name, unsigned i, Parser *parser); } /* namespace frontend */ } /* namespace js */ diff --git a/js/src/jit-test/tests/sunspider/check-crypto-md5.js b/js/src/jit-test/tests/sunspider/check-crypto-md5.js index 2e450de3e4d4..a5c6e1835129 100644 --- a/js/src/jit-test/tests/sunspider/check-crypto-md5.js +++ b/js/src/jit-test/tests/sunspider/check-crypto-md5.js @@ -283,5 +283,10 @@ for (var i = 0; i <4; i++) { plainText += plainText; } +// root checks performed during integer conversion operations can poison +// crypto integers in this test. +if (relaxRootChecks) + relaxRootChecks(); + var md5Output = hex_md5(plainText); assertEq(md5Output, "a831e91e0f70eddcb70dc61c6f82f6cd") diff --git a/js/src/jit-test/tests/sunspider/check-crypto-sha1.js b/js/src/jit-test/tests/sunspider/check-crypto-sha1.js index d25d5adb1dbe..cb63af99f49d 100644 --- a/js/src/jit-test/tests/sunspider/check-crypto-sha1.js +++ b/js/src/jit-test/tests/sunspider/check-crypto-sha1.js @@ -221,5 +221,10 @@ for (var i = 0; i <4; i++) { plainText += plainText; } +// root checks performed during integer conversion operations can poison +// crypto integers in this test. +if (relaxRootChecks) + relaxRootChecks(); + var sha1Output = hex_sha1(plainText); assertEq(sha1Output, "2524d264def74cce2498bf112bedf00e6c0b796d") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 7af454183963..4f5dc1860dd6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -596,10 +596,12 @@ JS_ValueToUint64(JSContext *cx, jsval v, uint64_t *ip) } JS_PUBLIC_API(JSBool) -JS_ValueToInt32(JSContext *cx, jsval v, int32_t *ip) +JS_ValueToInt32(JSContext *cx, jsval vArg, int32_t *ip) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); + + RootedValue v(cx, vArg); assertSameCompartment(cx, v); if (v.isInt32()) { @@ -616,7 +618,7 @@ JS_ValueToInt32(JSContext *cx, jsval v, int32_t *ip) if (MOZ_DOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) { js_ReportValueError(cx, JSMSG_CANT_CONVERT, - JSDVG_SEARCH_STACK, v, NULL); + JSDVG_SEARCH_STACK, v, NullPtr()); return false; } @@ -4957,12 +4959,14 @@ JS_BindCallable(JSContext *cx, JSObject *targetArg, JSRawObject newThis) JSBool js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + JSFunctionSpec *fs = (JSFunctionSpec *) vp->toObject().toFunction()->getExtendedSlot(0).toPrivate(); JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0); if (argc < 1) { - js_ReportMissingArg(cx, *vp, 0); + js_ReportMissingArg(cx, args.calleev(), 0); return JS_FALSE; } @@ -5918,8 +5922,8 @@ JS_New(JSContext *cx, JSObject *ctorArg, unsigned argc, jsval *argv) if (!cx->stack.pushInvokeArgs(cx, argc, &args)) return NULL; - args.calleev().setObject(*ctor); - args.thisv().setNull(); + args.setCallee(ObjectValue(*ctor)); + args.setThis(NullValue()); PodCopy(args.array(), argv, argc); if (!InvokeConstructor(cx, args)) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 0bc12b64dded..070727202f57 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1053,15 +1053,16 @@ class JS_PUBLIC_API(AutoGCRooter) { STRING = -14, /* js::AutoStringRooter */ IDVECTOR = -15, /* js::AutoIdVector */ OBJVECTOR = -16, /* js::AutoObjectVector */ - SCRIPTVECTOR =-17, /* js::AutoScriptVector */ - PROPDESC = -18, /* js::PropDesc::AutoRooter */ - SHAPERANGE = -19, /* js::Shape::Range::AutoRooter */ - STACKSHAPE = -20, /* js::StackShape::AutoRooter */ - STACKBASESHAPE=-21,/* js::StackBaseShape::AutoRooter */ - BINDINGS = -22, /* js::Bindings::AutoRooter */ - GETTERSETTER =-23, /* js::AutoRooterGetterSetter */ - REGEXPSTATICS=-24, /* js::RegExpStatics::AutoRooter */ - HASHABLEVALUE=-25 + STRINGVECTOR =-17, /* js::AutoStringVector */ + SCRIPTVECTOR =-18, /* js::AutoScriptVector */ + PROPDESC = -19, /* js::PropDesc::AutoRooter */ + SHAPERANGE = -20, /* js::Shape::Range::AutoRooter */ + STACKSHAPE = -21, /* js::StackShape::AutoRooter */ + STACKBASESHAPE=-22,/* js::StackBaseShape::AutoRooter */ + BINDINGS = -23, /* js::Bindings::AutoRooter */ + GETTERSETTER =-24, /* js::AutoRooterGetterSetter */ + REGEXPSTATICS=-25, /* js::RegExpStatics::AutoRooter */ + HASHABLEVALUE=-26 }; private: @@ -1255,6 +1256,7 @@ class AutoVectorRooter : protected AutoGCRooter } size_t length() const { return vector.length(); } + bool empty() const { return vector.empty(); } bool append(const T &v) { return vector.append(v); } bool append(const AutoVectorRooter &other) { @@ -1381,8 +1383,15 @@ class CallReceiver friend CallReceiver CallReceiverFromArgv(Value *); Value *base() const { return argv_ - 2; } JSObject &callee() const { JS_ASSERT(!usedRval_); return argv_[-2].toObject(); } - Value &calleev() const { JS_ASSERT(!usedRval_); return argv_[-2]; } - Value &thisv() const { return argv_[-1]; } + + JS::HandleValue calleev() const { + JS_ASSERT(!usedRval_); + return JS::HandleValue::fromMarkedLocation(&argv_[-2]); + } + + JS::HandleValue thisv() const { + return JS::HandleValue::fromMarkedLocation(&argv_[-1]); + } JS::MutableHandleValue rval() const { setUsedRval(); @@ -1394,9 +1403,13 @@ class CallReceiver return argv_ - 1; } - void setCallee(Value calleev) { + void setCallee(Value calleev) const { clearUsedRval(); - this->calleev() = calleev; + argv_[-2] = calleev; + } + + void setThis(Value thisv) const { + argv_[-1] = thisv; } }; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 481b9a956356..8707e26d3ee5 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -1535,7 +1535,7 @@ array_join_sub(JSContext *cx, CallArgs &args, bool locale) // the annotations in this function apply to both toLocaleString and join. // Step 1 - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -1623,7 +1623,7 @@ array_join_sub(JSContext *cx, CallArgs &args, bool locale) if (!hole && !elt.isNullOrUndefined()) { if (locale) { - JSObject *robj = ToObject(cx, elt.address()); + JSObject *robj = ToObject(cx, elt); if (!robj) return false; RootedId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom)); @@ -1657,7 +1657,7 @@ array_toString(JSContext *cx, unsigned argc, Value *vp) JS_CHECK_RECURSION(cx, return false); CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -1677,8 +1677,8 @@ array_toString(JSContext *cx, unsigned argc, Value *vp) if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) return false; - ag.calleev() = join; - ag.thisv().setObject(*obj); + ag.setCallee(join); + ag.setThis(ObjectValue(*obj)); /* Do the call. */ if (!Invoke(cx, ag)) @@ -1808,7 +1808,7 @@ static JSBool array_reverse(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2078,7 +2078,7 @@ SortComparatorFunction::operator()(const Value &a, const Value &b, bool *lessOrE return false; ag.setCallee(fval); - ag.thisv() = UndefinedValue(); + ag.setThis(UndefinedValue()); ag[0] = a; ag[1] = b; @@ -2118,7 +2118,7 @@ js::array_sort(JSContext *cx, unsigned argc, Value *vp) fval.setNull(); } - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2358,7 +2358,7 @@ JSBool js::array_push(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2433,7 +2433,7 @@ JSBool js::array_pop(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; if (obj->isDenseArray()) @@ -2462,7 +2462,7 @@ JSBool js::array_shift(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return JS_FALSE; @@ -2514,7 +2514,7 @@ static JSBool array_unshift(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2636,7 +2636,7 @@ array_splice(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2855,11 +2855,13 @@ mjit::stubs::ArrayConcatTwoArrays(VMFrame &f) JSBool js::array_concat(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Treat our |this| object as the first argument; see ECMA 15.4.4.4. */ - Value *p = JS_ARGV(cx, vp) - 1; + Value *p = args.array() - 1; /* Create a new Array object and root it using *vp. */ - RootedObject aobj(cx, ToObject(cx, &vp[1])); + RootedObject aobj(cx, ToObject(cx, args.thisv())); if (!aobj) return false; @@ -2874,7 +2876,7 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp) return JS_FALSE; TryReuseArrayType(aobj, nobj); nobj->setArrayLength(cx, length); - vp->setObject(*nobj); + args.rval().setObject(*nobj); if (argc == 0) return JS_TRUE; argc--; @@ -2883,7 +2885,7 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp) nobj = NewDenseEmptyArray(cx); if (!nobj) return JS_FALSE; - vp->setObject(*nobj); + args.rval().setObject(*nobj); length = 0; } @@ -2932,7 +2934,7 @@ array_slice(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -3011,13 +3013,12 @@ static JSBool array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args) { uint32_t length, i, stop; - Value tosearch; int direction; JSBool hole; - RootedValue elt(cx); + RootedValue tosearch(cx), elt(cx); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; if (!js_GetLengthProperty(cx, obj, &length)) @@ -3139,7 +3140,7 @@ static inline bool array_readonlyCommon(JSContext *cx, CallArgs &args) { /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -3180,7 +3181,7 @@ array_readonlyCommon(JSContext *cx, CallArgs &args) if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag)) return false; ag.setCallee(ObjectValue(*callable)); - ag.thisv() = thisv; + ag.setThis(thisv); ag[0] = kValue; ag[1] = NumberValue(k); ag[2] = ObjectValue(*obj); @@ -3231,7 +3232,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -3281,7 +3282,7 @@ array_map(JSContext *cx, unsigned argc, Value *vp) if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag)) return false; ag.setCallee(ObjectValue(*callable)); - ag.thisv() = thisv; + ag.setThis(thisv); ag[0] = kValue; ag[1] = NumberValue(k); ag[2] = ObjectValue(*obj); @@ -3308,7 +3309,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -3361,7 +3362,7 @@ array_filter(JSContext *cx, unsigned argc, Value *vp) if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 3, &ag)) return false; ag.setCallee(ObjectValue(*callable)); - ag.thisv() = thisv; + ag.setThis(thisv); ag[0] = kValue; ag[1] = NumberValue(k); ag[2] = ObjectValue(*obj); @@ -3416,7 +3417,7 @@ static inline bool array_reduceCommon(JSContext *cx, CallArgs &args) { /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -3430,7 +3431,7 @@ array_reduceCommon(JSContext *cx, CallArgs &args) js_ReportMissingArg(cx, args.calleev(), 0); return false; } - JSObject *callable = ValueToCallable(cx, &args[0]); + RootedObject callable(cx, ValueToCallable(cx, &args[0])); if (!callable) return false; @@ -3479,7 +3480,7 @@ array_reduceCommon(JSContext *cx, CallArgs &args) if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 4, &ag)) return false; ag.setCallee(ObjectValue(*callable)); - ag.thisv() = UndefinedValue(); + ag.setThis(UndefinedValue()); ag[0] = accumulator; ag[1] = kValue; ag[2] = NumberValue(k); @@ -3811,9 +3812,9 @@ js_ArrayInfo(JSContext *cx, unsigned argc, Value *vp) JSObject *array; for (unsigned i = 0; i < args.length(); i++) { - Value arg = args[i]; + RootedValue arg(cx, args[i]); - char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, arg, NULL); + char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, arg, NullPtr()); if (!bytes) return JS_FALSE; if (arg.isPrimitive() || diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index a3a38b3cd211..b362f453e0b8 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -298,6 +298,9 @@ AtomizeInline(JSContext *cx, const jschar **pchars, size_t length, SkipRoot skip(cx, &chars); + /* Workaround for hash values in AddPtr being inadvertently poisoned. */ + SkipRoot skip2(cx, &p); + if (ocb == TakeCharOwnership) { key = js_NewString(cx, const_cast(chars), length); if (!key) diff --git a/js/src/jsbool.cpp b/js/src/jsbool.cpp index 1408d91d0574..22fcb08ad96e 100644 --- a/js/src/jsbool.cpp +++ b/js/src/jsbool.cpp @@ -205,8 +205,8 @@ BooleanGetPrimitiveValueSlow(JSContext *cx, JSObject &obj, Value *vp) InvokeArgsGuard ag; if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) return false; - ag.calleev() = cx->compartment->maybeGlobal()->booleanValueOf(); - ag.thisv().setObject(obj); + ag.setCallee(cx->compartment->maybeGlobal()->booleanValueOf()); + ag.setThis(ObjectValue(obj)); if (!Invoke(cx, ag)) return false; *vp = ag.rval(); diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index c35ceae7e009..bf3877456da7 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -810,8 +810,8 @@ js_ReportIsNotDefined(JSContext *cx, const char *name) } JSBool -js_ReportIsNullOrUndefined(JSContext *cx, int spindex, const Value &v, - JSString *fallback) +js_ReportIsNullOrUndefined(JSContext *cx, int spindex, HandleValue v, + HandleString fallback) { char *bytes; JSBool ok; @@ -844,11 +844,11 @@ js_ReportIsNullOrUndefined(JSContext *cx, int spindex, const Value &v, } void -js_ReportMissingArg(JSContext *cx, const Value &v, unsigned arg) +js_ReportMissingArg(JSContext *cx, HandleValue v, unsigned arg) { char argbuf[11]; char *bytes; - JSAtom *atom; + RootedAtom atom(cx); JS_snprintf(argbuf, sizeof argbuf, "%u", arg); bytes = NULL; @@ -867,7 +867,7 @@ js_ReportMissingArg(JSContext *cx, const Value &v, unsigned arg) JSBool js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber, - int spindex, const Value &v, JSString *fallback, + int spindex, HandleValue v, HandleString fallback, const char *arg1, const char *arg2) { char *bytes; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 49ec5cc5403c..cbb8a0c0fb8b 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1728,11 +1728,11 @@ js_ReportIsNotDefined(JSContext *cx, const char *name); * Report an attempt to access the property of a null or undefined value (v). */ extern JSBool -js_ReportIsNullOrUndefined(JSContext *cx, int spindex, const js::Value &v, - JSString *fallback); +js_ReportIsNullOrUndefined(JSContext *cx, int spindex, js::HandleValue v, + js::HandleString fallback); extern void -js_ReportMissingArg(JSContext *cx, const js::Value &v, unsigned arg); +js_ReportMissingArg(JSContext *cx, js::HandleValue v, unsigned arg); /* * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as @@ -1741,7 +1741,7 @@ js_ReportMissingArg(JSContext *cx, const js::Value &v, unsigned arg); */ extern JSBool js_ReportValueErrorFlags(JSContext *cx, unsigned flags, const unsigned errorNumber, - int spindex, const js::Value &v, JSString *fallback, + int spindex, js::HandleValue v, js::HandleString fallback, const char *arg1, const char *arg2); #define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \ @@ -1888,6 +1888,19 @@ class AutoObjectVector : public AutoVectorRooter JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; +class AutoStringVector : public AutoVectorRooter +{ + public: + explicit AutoStringVector(JSContext *cx + JS_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, STRINGVECTOR) + { + JS_GUARD_OBJECT_NOTIFIER_INIT; + } + + JS_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + class AutoShapeVector : public AutoVectorRooter { public: diff --git a/js/src/jsdate.cpp b/js/src/jsdate.cpp index c3155ff9de77..021a8d27e9f7 100644 --- a/js/src/jsdate.cpp +++ b/js/src/jsdate.cpp @@ -2589,8 +2589,10 @@ date_toISOString(JSContext *cx, unsigned argc, Value *vp) static JSBool date_toJSON(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Step 1. */ - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -2601,7 +2603,7 @@ date_toJSON(JSContext *cx, unsigned argc, Value *vp) /* Step 3. */ if (tv.isDouble() && !MOZ_DOUBLE_IS_FINITE(tv.toDouble())) { - vp->setNull(); + args.rval().setNull(); return true; } @@ -2618,16 +2620,16 @@ date_toJSON(JSContext *cx, unsigned argc, Value *vp) } /* Step 6. */ - InvokeArgsGuard args; - if (!cx->stack.pushInvokeArgs(cx, 0, &args)) + InvokeArgsGuard ag; + if (!cx->stack.pushInvokeArgs(cx, 0, &ag)) return false; - args.calleev() = toISO; - args.thisv().setObject(*obj); + ag.setCallee(toISO); + ag.setThis(ObjectValue(*obj)); - if (!Invoke(cx, args)) + if (!Invoke(cx, ag)) return false; - *vp = args.rval(); + args.rval().set(ag.rval()); return true; } diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 336bb0e5e0bf..75d85ad7228b 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -686,7 +686,7 @@ exn_toSource(JSContext *cx, unsigned argc, Value *vp) JS_CHECK_RECURSION(cx, return false); CallArgs args = CallArgsFromVp(argc, vp); - RootedObject obj(cx, ToObject(cx, &args.thisv())); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 890a1214a6b5..8b74a26cb69c 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -469,7 +469,8 @@ fun_hasInstance(JSContext *cx, HandleObject obj_, const Value *v, JSBool *bp) * Throw a runtime error if instanceof is called on a function that * has a non-object as its .prototype value. */ - js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, ObjectValue(*obj), NULL); + RootedValue val(cx, ObjectValue(*obj)); + js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, val, NullPtr()); return JS_FALSE; } @@ -745,13 +746,15 @@ fun_toStringHelper(JSContext *cx, JSObject *obj, unsigned indent) static JSBool fun_toString(JSContext *cx, unsigned argc, Value *vp) { - JS_ASSERT(IsFunctionObject(vp[0])); + CallArgs args = CallArgsFromVp(argc, vp); + JS_ASSERT(IsFunctionObject(args.calleev())); + uint32_t indent = 0; - if (argc != 0 && !ToUint32(cx, vp[2], &indent)) + if (args.length() != 0 && !ToUint32(cx, args[0], &indent)) return false; - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, args.thisv()); if (!obj) return false; @@ -759,7 +762,7 @@ fun_toString(JSContext *cx, unsigned argc, Value *vp) if (!str) return false; - vp->setString(str); + args.rval().setString(str); return true; } @@ -767,9 +770,10 @@ fun_toString(JSContext *cx, unsigned argc, Value *vp) static JSBool fun_toSource(JSContext *cx, unsigned argc, Value *vp) { - JS_ASSERT(IsFunctionObject(vp[0])); + CallArgs args = CallArgsFromVp(argc, vp); + JS_ASSERT(IsFunctionObject(args.calleev())); - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, args.thisv()); if (!obj) return false; @@ -777,7 +781,7 @@ fun_toSource(JSContext *cx, unsigned argc, Value *vp) if (!str) return false; - vp->setString(str); + args.rval().setString(str); return true; } #endif @@ -809,8 +813,8 @@ js_fun_call(JSContext *cx, unsigned argc, Value *vp) return JS_FALSE; /* Push fval, thisv, and the args. */ - args.calleev() = fval; - args.thisv() = thisv; + args.setCallee(fval); + args.setThis(thisv); PodCopy(args.array(), argv, argc); bool ok = Invoke(cx, args); @@ -855,8 +859,8 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp) return false; /* Push fval, obj, and aobj's elements as args. */ - args.calleev() = fval; - args.thisv() = vp[2]; + args.setCallee(fval); + args.setThis(vp[2]); /* Steps 7-8. */ cx->fp()->forEachUnaliasedActual(CopyTo(args.array())); @@ -886,8 +890,8 @@ js_fun_apply(JSContext *cx, unsigned argc, Value *vp) return false; /* Push fval, obj, and aobj's elements as args. */ - args.calleev() = fval; - args.thisv() = vp[2]; + args.setCallee(fval); + args.setThis(vp[2]); /* Steps 7-8. */ if (!GetElements(cx, aobj, length, args.array())) @@ -1017,10 +1021,10 @@ CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp) PodCopy(args.array() + argslen, vp + 2, argc); /* 15.3.4.5.1, 15.3.4.5.2 step 5. */ - args.calleev().setObject(*target); + args.setCallee(ObjectValue(*target)); if (!constructing) - args.thisv() = boundThis; + args.setThis(boundThis); if (constructing ? !InvokeConstructor(cx, args) : !Invoke(cx, args)) return false; @@ -1060,7 +1064,7 @@ fun_bind(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - Value &thisv = args.thisv(); + Value thisv = args.thisv(); /* Step 2. */ if (!js_IsCallable(thisv)) { @@ -1517,7 +1521,7 @@ js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native, void js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp) { - Value &thisv = call.thisv(); + Value thisv = call.thisv(); #ifdef DEBUG if (thisv.isObject()) { diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index df1271e21329..22b64880df91 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -110,7 +110,7 @@ js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call) * Check for SynthesizeFrame poisoning and fast constructors which * didn't check their callee properly. */ - Value &thisv = call.thisv(); + Value thisv = call.thisv(); JS_ASSERT(!thisv.isMagic()); #ifdef DEBUG @@ -120,15 +120,17 @@ js::BoxNonStrictThis(JSContext *cx, const CallReceiver &call) if (thisv.isNullOrUndefined()) { JSObject *thisp = call.callee().global().thisObject(cx); - JS_ASSERT(!IsPoisonedPtr(thisp)); if (!thisp) return false; - call.thisv().setObject(*thisp); + call.setThis(ObjectValue(*thisp)); return true; } - if (!thisv.isObject()) - return !!js_PrimitiveToObject(cx, &thisv); + if (!thisv.isObject()) { + if (!js_PrimitiveToObject(cx, &thisv)) + return false; + call.setThis(thisv); + } return true; } @@ -205,8 +207,8 @@ NoSuchMethod(JSContext *cx, unsigned argc, Value *vp) JSObject *obj = &vp[0].toObject(); JS_ASSERT(obj->getClass() == &js_NoSuchMethodClass); - args.calleev() = obj->getSlot(JSSLOT_FOUND_FUNCTION); - args.thisv() = vp[1]; + args.setCallee(obj->getSlot(JSSLOT_FOUND_FUNCTION)); + args.setThis(vp[1]); args[0] = obj->getSlot(JSSLOT_SAVED_ID); JSObject *argsobj = NewDenseCopiedArray(cx, argc, vp + 2); if (!argsobj) @@ -223,7 +225,9 @@ bool js::ReportIsNotFunction(JSContext *cx, const Value &v, MaybeConstruct construct) { unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION; - js_ReportValueError3(cx, error, JSDVG_SEARCH_STACK, v, NULL, NULL, NULL); + + RootedValue val(cx, v); + js_ReportValueError3(cx, error, JSDVG_SEARCH_STACK, val, NullPtr(), NULL, NULL); return false; } @@ -232,7 +236,9 @@ js::ReportIsNotFunction(JSContext *cx, const Value *vp, MaybeConstruct construct { ptrdiff_t spIndex = cx->stack.spIndexOf(vp); unsigned error = construct ? JSMSG_NOT_CONSTRUCTOR : JSMSG_NOT_FUNCTION; - js_ReportValueError3(cx, error, spIndex, *vp, NULL, NULL, NULL); + + RootedValue val(cx, *vp); + js_ReportValueError3(cx, error, spIndex, val, NullPtr(), NULL, NULL); return false; } @@ -321,7 +327,7 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct) InitialFrameFlags initial = (InitialFrameFlags) construct; if (args.calleev().isPrimitive()) - return ReportIsNotFunction(cx, &args.calleev(), construct); + return ReportIsNotFunction(cx, args.calleev().address(), construct); JSObject &callee = args.callee(); Class *clasp = callee.getClass(); @@ -334,7 +340,7 @@ js::InvokeKernel(JSContext *cx, CallArgs args, MaybeConstruct construct) #endif JS_ASSERT_IF(construct, !clasp->construct); if (!clasp->call) - return ReportIsNotFunction(cx, &args.calleev(), construct); + return ReportIsNotFunction(cx, args.calleev().address(), construct); return CallJSNative(cx, clasp->call, args); } @@ -369,8 +375,8 @@ js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, if (!cx->stack.pushInvokeArgs(cx, argc, &args)) return false; - args.calleev() = fval; - args.thisv() = thisv; + args.setCallee(fval); + args.setThis(thisv); PodCopy(args.array(), argv, argc); if (args.thisv().isObject()) { @@ -382,7 +388,7 @@ js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, JSObject *thisp = args.thisv().toObject().thisObject(cx); if (!thisp) return false; - args.thisv().setObject(*thisp); + args.setThis(ObjectValue(*thisp)); } if (!Invoke(cx, args)) @@ -397,10 +403,10 @@ js::InvokeConstructorKernel(JSContext *cx, CallArgs args) { JS_ASSERT(!FunctionClass.construct); - args.thisv().setMagic(JS_IS_CONSTRUCTING); + args.setThis(MagicValue(JS_IS_CONSTRUCTING)); if (!args.calleev().isObject()) - return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT); + return ReportIsNotFunction(cx, args.calleev().address(), CONSTRUCT); JSObject &callee = args.callee(); if (callee.isFunction()) { @@ -414,7 +420,7 @@ js::InvokeConstructorKernel(JSContext *cx, CallArgs args) } if (!fun->isInterpretedConstructor()) - return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT); + return ReportIsNotFunction(cx, args.calleev().address(), CONSTRUCT); if (!InvokeKernel(cx, args, CONSTRUCT)) return false; @@ -425,7 +431,7 @@ js::InvokeConstructorKernel(JSContext *cx, CallArgs args) Class *clasp = callee.getClass(); if (!clasp->construct) - return ReportIsNotFunction(cx, &args.calleev(), CONSTRUCT); + return ReportIsNotFunction(cx, args.calleev().address(), CONSTRUCT); return CallJSNativeConstructor(cx, clasp->construct, args); } @@ -437,8 +443,8 @@ js::InvokeConstructor(JSContext *cx, const Value &fval, unsigned argc, Value *ar if (!cx->stack.pushInvokeArgs(cx, argc, &args)) return false; - args.calleev() = fval; - args.thisv().setMagic(JS_THIS_POISON); + args.setCallee(fval); + args.setThis(MagicValue(JS_THIS_POISON)); PodCopy(args.array(), argv, argc); if (!InvokeConstructor(cx, args)) @@ -530,8 +536,10 @@ js::HasInstance(JSContext *cx, HandleObject obj, const Value *v, JSBool *bp) Class *clasp = obj->getClass(); if (clasp->hasInstance) return clasp->hasInstance(cx, obj, v, bp); + + RootedValue val(cx, ObjectValue(*obj)); js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, - JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL); + JSDVG_SEARCH_STACK, val, NullPtr()); return JS_FALSE; } @@ -880,8 +888,8 @@ DoIncDec(JSContext *cx, HandleScript script, jsbytecode *pc, const Value &v, Val #define FETCH_OBJECT(cx, n, obj) \ JS_BEGIN_MACRO \ - Value *vp_ = ®s.sp[n]; \ - obj = ToObject(cx, (vp_)); \ + HandleValue val = HandleValue::fromMarkedLocation(®s.sp[n]); \ + obj = ToObject(cx, (val)); \ if (!obj) \ goto error; \ JS_END_MACRO @@ -1675,9 +1683,9 @@ END_CASE(JSOP_AND) BEGIN_CASE(JSOP_IN) { - const Value &rref = regs.sp[-1]; + HandleValue rref = HandleValue::fromMarkedLocation(®s.sp[-1]); if (!rref.isObject()) { - js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL); + js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NullPtr()); goto error; } RootedObject &obj = rootObject0; @@ -2204,8 +2212,9 @@ BEGIN_CASE(JSOP_TOID) * There must be an object value below the id, which will not be popped * but is necessary in interning the id for XML. */ - Value objval = regs.sp[-2]; - Value idval = regs.sp[-1]; + RootedValue &objval = rootValue0, &idval = rootValue1; + objval = regs.sp[-2]; + idval = regs.sp[-1]; MutableHandleValue res = MutableHandleValue::fromMarkedLocation(®s.sp[-1]); if (!ToIdOperation(cx, objval, idval, res)) @@ -2300,8 +2309,11 @@ BEGIN_CASE(JSOP_GETXPROP) BEGIN_CASE(JSOP_LENGTH) BEGIN_CASE(JSOP_CALLPROP) { + RootedValue &lval = rootValue0; + lval = regs.sp[-1]; + RootedValue rval(cx); - if (!GetPropertyOperation(cx, script, regs.pc, regs.sp[-1], rval.address())) + if (!GetPropertyOperation(cx, regs.pc, &lval, &rval)) goto error; TypeScript::Monitor(cx, script, regs.pc, rval); @@ -2315,8 +2327,8 @@ BEGIN_CASE(JSOP_SETGNAME) BEGIN_CASE(JSOP_SETNAME) BEGIN_CASE(JSOP_SETPROP) { - const Value &rval = regs.sp[-1]; - const Value &lval = regs.sp[-2]; + HandleValue lval = HandleValue::fromMarkedLocation(®s.sp[-2]); + HandleValue rval = HandleValue::fromMarkedLocation(®s.sp[-1]); if (!SetPropertyOperation(cx, regs.pc, lval, rval)) goto error; @@ -2329,10 +2341,11 @@ END_CASE(JSOP_SETPROP) BEGIN_CASE(JSOP_GETELEM) BEGIN_CASE(JSOP_CALLELEM) { - Value &lref = regs.sp[-2]; - Value &rref = regs.sp[-1]; + MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(®s.sp[-2]); + HandleValue rval = HandleValue::fromMarkedLocation(®s.sp[-1]); + MutableHandleValue res = MutableHandleValue::fromMarkedLocation(®s.sp[-2]); - if (!GetElementOperation(cx, op, lref, rref, res)) + if (!GetElementOperation(cx, op, lval, rval, res)) goto error; TypeScript::Monitor(cx, script, regs.pc, res); regs.sp--; @@ -3263,9 +3276,10 @@ BEGIN_CASE(JSOP_THROW) BEGIN_CASE(JSOP_INSTANCEOF) { - const Value &rref = regs.sp[-1]; + RootedValue &rref = rootValue0; + rref = regs.sp[-1]; if (rref.isPrimitive()) { - js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NULL); + js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NullPtr()); goto error; } RootedObject &obj = rootObject0; @@ -3703,8 +3717,9 @@ BEGIN_CASE(JSOP_YIELD) JS_ASSERT(!cx->isExceptionPending()); JS_ASSERT(regs.fp()->isNonEvalFunctionFrame()); if (cx->innermostGenerator()->state == JSGEN_CLOSING) { - js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, - ObjectValue(regs.fp()->callee()), NULL); + RootedValue &val = rootValue0; + val.setObject(regs.fp()->callee()); + js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, val, NullPtr()); goto error; } regs.fp()->setReturnValue(regs.sp[-1]); diff --git a/js/src/jsinterpinlines.h b/js/src/jsinterpinlines.h index 0183145c8579..046cb9bb8fef 100644 --- a/js/src/jsinterpinlines.h +++ b/js/src/jsinterpinlines.h @@ -144,7 +144,7 @@ GuardFunApplyArgumentsOptimization(JSContext *cx) * problem to the value at |spindex| on the stack. */ JS_ALWAYS_INLINE JSObject * -ValuePropertyBearer(JSContext *cx, StackFrame *fp, const Value &v, int spindex) +ValuePropertyBearer(JSContext *cx, StackFrame *fp, HandleValue v, int spindex) { if (v.isObject()) return &v.toObject(); @@ -159,7 +159,7 @@ ValuePropertyBearer(JSContext *cx, StackFrame *fp, const Value &v, int spindex) return global.getOrCreateBooleanPrototype(cx); JS_ASSERT(v.isNull() || v.isUndefined()); - js_ReportIsNullOrUndefined(cx, spindex, v, NULL); + js_ReportIsNullOrUndefined(cx, spindex, v, NullPtr()); return NULL; } @@ -205,27 +205,27 @@ GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleI } inline bool -GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value &lval, Value *vp) +GetPropertyOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue lval, MutableHandleValue vp) { - JS_ASSERT(vp != &lval); + JS_ASSERT(vp.address() != lval.address()); JSOp op = JSOp(*pc); if (op == JSOP_LENGTH) { /* Optimize length accesses on strings, arrays, and arguments. */ if (lval.isString()) { - *vp = Int32Value(lval.toString()->length()); + vp.setInt32(lval.toString()->length()); return true; } - if (IsOptimizedArguments(cx->fp(), &lval)) { - *vp = Int32Value(cx->fp()->numActualArgs()); + if (IsOptimizedArguments(cx->fp(), lval.address())) { + vp.setInt32(cx->fp()->numActualArgs()); return true; } if (lval.isObject()) { JSObject *obj = &lval.toObject(); if (obj->isArray()) { uint32_t length = obj->getArrayLength(); - *vp = NumberValue(length); + vp.setNumber(length); return true; } @@ -234,19 +234,19 @@ GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value &lva if (!argsobj->hasOverriddenLength()) { uint32_t length = argsobj->initialLength(); JS_ASSERT(length < INT32_MAX); - *vp = Int32Value(int32_t(length)); + vp.setInt32(int32_t(length)); return true; } } if (obj->isTypedArray()) { - *vp = Int32Value(TypedArray::length(obj)); + vp.setInt32(TypedArray::length(obj)); return true; } } } - RootedObject obj(cx, ValueToObject(cx, lval)); + RootedObject obj(cx, ToObjectFromStack(cx, lval)); if (!obj) return false; @@ -256,40 +256,38 @@ GetPropertyOperation(JSContext *cx, JSScript *script, jsbytecode *pc, Value &lva JS_PROPERTY_CACHE(cx).test(cx, pc, obj.get(), obj2.get(), entry, name); if (!name) { AssertValidPropertyCacheHit(cx, obj, obj2, entry); - if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp)) + if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp.address())) return false; return true; } RootedId id(cx, NameToId(name)); - RootedValue value(cx); if (obj->getOps()->getProperty) { - if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, &value)) + if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp)) return false; } else { - if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, &value)) + if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp)) return false; } #if JS_HAS_NO_SUCH_METHOD if (op == JSOP_CALLPROP && - JS_UNLIKELY(value.isPrimitive()) && + JS_UNLIKELY(vp.isPrimitive()) && lval.isObject()) { - if (!OnUnknownMethod(cx, obj, IdToValue(id), &value)) + if (!OnUnknownMethod(cx, obj, IdToValue(id), vp)) return false; } #endif - *vp = value; return true; } inline bool -SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Value &rval) +SetPropertyOperation(JSContext *cx, jsbytecode *pc, HandleValue lval, HandleValue rval) { - RootedObject obj(cx, ValueToObject(cx, lval)); + RootedObject obj(cx, ToObjectFromStack(cx, lval)); if (!obj) return false; @@ -505,10 +503,8 @@ AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res) } else #endif { - RootedValue lval_(cx, lhs); - RootedValue rval_(cx, rhs); - Value &lval = lval_.get(); - Value &rval = rval_.get(); + RootedValue lval(cx, lhs); + RootedValue rval(cx, rhs); /* * If either operand is an object, any non-integer result must be @@ -516,9 +512,9 @@ AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res) */ bool lIsObject = lval.isObject(), rIsObject = rval.isObject(); - if (!ToPrimitive(cx, &lval)) + if (!ToPrimitive(cx, lval.address())) return false; - if (!ToPrimitive(cx, &rval)) + if (!ToPrimitive(cx, rval.address())) return false; bool lIsString, rIsString; if ((lIsString = lval.isString()) | (rIsString = rval.isString())) { @@ -629,14 +625,14 @@ FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp, Muta } static JS_ALWAYS_INLINE bool -ToIdOperation(JSContext *cx, const Value &objval, const Value &idval, MutableHandleValue res) +ToIdOperation(JSContext *cx, HandleValue objval, HandleValue idval, MutableHandleValue res) { if (idval.isInt32()) { res.set(idval); return true; } - JSObject *obj = ValueToObject(cx, objval); + JSObject *obj = ToObjectFromStack(cx, objval); if (!obj) return false; @@ -710,7 +706,8 @@ GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value } static JS_ALWAYS_INLINE bool -GetElementOperation(JSContext *cx, JSOp op, Value &lref, const Value &rref, MutableHandleValue res) +GetElementOperation(JSContext *cx, JSOp op, MutableHandleValue lref, HandleValue rref, + MutableHandleValue res) { JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM); @@ -727,7 +724,7 @@ GetElementOperation(JSContext *cx, JSOp op, Value &lref, const Value &rref, Muta } StackFrame *fp = cx->fp(); - if (IsOptimizedArguments(fp, &lref)) { + if (IsOptimizedArguments(fp, lref.address())) { if (rref.isInt32()) { int32_t i = rref.toInt32(); if (i >= 0 && uint32_t(i) < fp->numActualArgs()) { @@ -739,11 +736,11 @@ GetElementOperation(JSContext *cx, JSOp op, Value &lref, const Value &rref, Muta if (!JSScript::argumentsOptimizationFailed(cx, fp->script())) return false; - lref = ObjectValue(fp->argsObj()); + lref.set(ObjectValue(fp->argsObj())); } bool isObject = lref.isObject(); - RootedObject obj(cx, ValueToObject(cx, lref)); + RootedObject obj(cx, ToObjectFromStack(cx, lref)); if (!obj) return false; if (!GetObjectElementOperation(cx, op, obj, rref, res)) diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 323152769a3d..eec8c591a38d 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -343,7 +343,7 @@ GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandle JS_CHECK_RECURSION(cx, return false); /* Check whether we have a valid __iterator__ method. */ - PropertyName *name = cx->runtime->atomState.iteratorIntrinsicAtom; + RootedPropertyName name(cx, cx->runtime->atomState.iteratorIntrinsicAtom); if (!GetMethod(cx, obj, name, 0, vp)) return false; @@ -368,8 +368,9 @@ GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandle JSAutoByteString bytes; if (!js_AtomToPrintableString(cx, name, &bytes)) return false; + RootedValue val(cx, ObjectValue(*obj)); js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE, - -1, ObjectValue(*obj), NULL, bytes.ptr()); + -1, val, NullPtr(), bytes.ptr()); return false; } return true; @@ -578,7 +579,8 @@ GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue // for this kind of error anyway, but it would throw an inscrutable // error message about |method| rather than this nice one about |obj|. if (!method.isObject() || !method.toObject().isCallable()) { - char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, ObjectOrNullValue(obj), NULL); + RootedValue val(cx, ObjectOrNullValue(obj)); + char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, NullPtr()); if (!bytes) return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_ITERABLE, bytes); @@ -589,8 +591,10 @@ GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, NULL, vp.address())) return false; - if (!ToObject(cx, vp.address())) + JSObject *obj = ToObject(cx, vp); + if (!obj) return false; + vp.setObject(*obj); return true; } @@ -846,7 +850,7 @@ const uint32_t CLOSED_INDEX = UINT32_MAX; JSObject * ElementIteratorObject::create(JSContext *cx, Handle target) { - GlobalObject *global = GetCurrentGlobal(cx); + Rooted global(cx, GetCurrentGlobal(cx)); Rooted proto(cx, global->getOrCreateElementIteratorPrototype(cx)); if (!proto) return NULL; @@ -874,16 +878,16 @@ ElementIteratorObject::next(JSContext *cx, unsigned argc, Value *vp) bool ElementIteratorObject::next_impl(JSContext *cx, CallArgs args) { - JSObject *iterobj = &args.thisv().toObject(); + RootedObject iterobj(cx, &args.thisv().toObject()); uint32_t i, length; - Value target = iterobj->getReservedSlot(TargetSlot); + RootedValue target(cx, iterobj->getReservedSlot(TargetSlot)); Rooted obj(cx); // Get target.length. if (target.isString()) { length = uint32_t(target.toString()->length()); } else { - obj = ValueToObject(cx, target); + obj = ToObjectFromStack(cx, target); if (!obj) goto close; if (!js_GetLengthProperty(cx, obj, &length)) @@ -1605,8 +1609,9 @@ generator_send_impl(JSContext *cx, CallArgs args) } if (gen->state == JSGEN_NEWBORN && args.hasDefined(0)) { + RootedValue val(cx, args[0]); js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND, - JSDVG_SEARCH_STACK, args[0], NULL); + JSDVG_SEARCH_STACK, val, NullPtr()); return false; } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index a457f7eb4032..b4ec40659868 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -329,6 +329,8 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map) static JSBool obj_toSource(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + bool comma = false; const jschar *vchars; size_t vlength; @@ -345,7 +347,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) /* If outermost, we need parentheses to be an expression, not a block. */ bool outermost = (cx->sharpObjectMap.depth == 0); - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -364,7 +366,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) JSString *str = js_NewStringCopyZ(cx, "{}"); if (!str) return false; - vp->setString(str); + args.rval().setString(str); return true; } @@ -537,7 +539,7 @@ obj_toSource(JSContext *cx, unsigned argc, Value *vp) JSString *str = buf.finishString(); if (!str) return false; - vp->setString(str); + args.rval().setString(str); return true; } #endif /* JS_HAS_TOSOURCE */ @@ -594,22 +596,22 @@ InformalValueTypeName(const Value &v) static JSBool obj_toString(JSContext *cx, unsigned argc, Value *vp) { - Value &thisv = vp[1]; + CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - if (thisv.isUndefined()) { - vp->setString(cx->runtime->atomState.objectUndefinedAtom); + if (args.thisv().isUndefined()) { + args.rval().setString(cx->runtime->atomState.objectUndefinedAtom); return true; } /* Step 2. */ - if (thisv.isNull()) { - vp->setString(cx->runtime->atomState.objectNullAtom); + if (args.thisv().isNull()) { + args.rval().setString(cx->runtime->atomState.objectNullAtom); return true; } /* Step 3. */ - JSObject *obj = ToObject(cx, &thisv); + JSObject *obj = ToObject(cx, args.thisv()); if (!obj) return false; @@ -617,7 +619,7 @@ obj_toString(JSContext *cx, unsigned argc, Value *vp) JSString *str = js::obj_toStringHelper(cx, obj); if (!str) return false; - vp->setString(str); + args.rval().setString(str); return true; } @@ -630,7 +632,7 @@ obj_toLocaleString(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); /* Step 1. */ - JSObject *obj = ToObject(cx, &args.thisv()); + JSObject *obj = ToObject(cx, args.thisv()); if (!obj) return false; @@ -642,10 +644,11 @@ obj_toLocaleString(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_valueOf(JSContext *cx, unsigned argc, Value *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + JSObject *obj = ToObject(cx, args.thisv()); if (!obj) return false; - vp->setObject(*obj); + args.rval().setObject(*obj); return true; } @@ -684,20 +687,22 @@ obj_watch_handler(JSContext *cx, JSObject *obj_, jsid id_, jsval old, static JSBool obj_watch(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + if (argc <= 1) { - js_ReportMissingArg(cx, *vp, 1); + js_ReportMissingArg(cx, args.calleev(), 1); return false; } - RootedObject callable(cx, ValueToCallable(cx, &vp[3])); + RootedObject callable(cx, ValueToCallable(cx, &args[1])); if (!callable) return false; RootedId propid(cx); - if (!ValueToId(cx, vp[2], propid.address())) + if (!ValueToId(cx, args[0], propid.address())) return false; - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; @@ -706,7 +711,7 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp) if (!CheckAccess(cx, obj, propid, JSACC_WATCH, &tmp, &attrs)) return false; - vp->setUndefined(); + args.rval().setUndefined(); if (obj->isDenseArray() && !JSObject::makeDenseArraySlow(cx, obj)) return false; @@ -716,13 +721,15 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_unwatch(JSContext *cx, unsigned argc, Value *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; - vp->setUndefined(); + args.rval().setUndefined(); jsid id; if (argc != 0) { - if (!ValueToId(cx, vp[2], &id)) + if (!ValueToId(cx, args[0], &id)) return false; } else { id = JSID_VOID; @@ -741,21 +748,25 @@ obj_unwatch(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + CallArgs args = CallArgsFromVp(argc, vp); + + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; - return js_HasOwnPropertyHelper(cx, obj->getOps()->lookupGeneric, argc, vp); + return js_HasOwnPropertyHelper(cx, obj->getOps()->lookupGeneric, argc, args.rval().address()); } JSBool js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + RootedId id(cx); - if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address())) + if (!ValueToId(cx, args.length() ? args[0] : UndefinedValue(), id.address())) return JS_FALSE; - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; RootedObject obj2(cx); @@ -764,12 +775,12 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc, bool has; if (!Proxy::hasOwn(cx, obj, id, &has)) return false; - vp->setBoolean(has); + args.rval().setBoolean(has); return true; } if (!js_HasOwnProperty(cx, lookup, obj, id, &obj2, &prop)) return JS_FALSE; - vp->setBoolean(!!prop); + args.rval().setBoolean(!!prop); return JS_TRUE; } @@ -808,19 +819,21 @@ js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, Handl static JSBool obj_isPrototypeOf(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Step 1. */ - if (argc < 1 || !vp[2].isObject()) { - vp->setBoolean(false); + if (args.length() < 1 || !args[0].isObject()) { + args.rval().setBoolean(false); return true; } /* Step 2. */ - JSObject *obj = ToObject(cx, &vp[1]); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; /* Step 3. */ - vp->setBoolean(js_IsDelegate(cx, obj, vp[2])); + args.rval().setBoolean(js_IsDelegate(cx, obj, args[0])); return true; } @@ -828,18 +841,20 @@ obj_isPrototypeOf(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_propertyIsEnumerable(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Step 1. */ RootedId id(cx); - if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address())) + if (!ValueToId(cx, args.length() ? args[0] : UndefinedValue(), id.address())) return false; /* Step 2. */ - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; /* Steps 3-5. */ - return js_PropertyIsEnumerable(cx, obj, id, vp); + return js_PropertyIsEnumerable(cx, obj, id, args.rval().address()); } JSBool @@ -941,32 +956,34 @@ js::obj_defineSetter(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + RootedId id(cx); - if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address())) + if (!ValueToId(cx, args.length() ? args[0] : UndefinedValue(), id.address())) return JS_FALSE; - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return JS_FALSE; if (obj->isProxy()) { // The vanilla getter lookup code below requires that the object is // native. Handle proxies separately. - vp->setUndefined(); + args.rval().setUndefined(); AutoPropertyDescriptorRooter desc(cx); if (!Proxy::getPropertyDescriptor(cx, obj, id, false, &desc)) return JS_FALSE; if (desc.obj && (desc.attrs & JSPROP_GETTER) && desc.getter) - *vp = CastAsObjectJsval(desc.getter); + args.rval().set(CastAsObjectJsval(desc.getter)); return JS_TRUE; } RootedObject pobj(cx); RootedShape shape(cx); if (!obj->lookupGeneric(cx, id, &pobj, &shape)) return JS_FALSE; - vp->setUndefined(); + args.rval().setUndefined(); if (shape) { if (pobj->isNative()) { if (shape->hasGetterValue()) - *vp = shape->getterValue(); + args.rval().set(shape->getterValue()); } } return JS_TRUE; @@ -975,32 +992,34 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp) static JSBool obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + RootedId id(cx); - if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address())) + if (!ValueToId(cx, args.length() ? args[0] : UndefinedValue(), id.address())) return JS_FALSE; - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return JS_FALSE; if (obj->isProxy()) { // The vanilla setter lookup code below requires that the object is // native. Handle proxies separately. - vp->setUndefined(); + args.rval().setUndefined(); AutoPropertyDescriptorRooter desc(cx); if (!Proxy::getPropertyDescriptor(cx, obj, id, false, &desc)) return JS_FALSE; if (desc.obj && (desc.attrs & JSPROP_SETTER) && desc.setter) - *vp = CastAsObjectJsval(desc.setter); + args.rval().set(CastAsObjectJsval(desc.setter)); return JS_TRUE; } RootedObject pobj(cx); RootedShape shape(cx); if (!obj->lookupGeneric(cx, id, &pobj, &shape)) return JS_FALSE; - vp->setUndefined(); + args.rval().setUndefined(); if (shape) { if (pobj->isNative()) { if (shape->hasSetterValue()) - *vp = shape->setterValue(); + args.rval().set(shape->setterValue()); } } return JS_TRUE; @@ -1020,7 +1039,8 @@ obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp) } if (args[0].isPrimitive()) { - char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, vp[2], NULL); + RootedValue val(cx, args[0]); + char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, NullPtr()); if (!bytes) return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -1038,8 +1058,8 @@ obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp) InvokeArgsGuard nested; if (!cx->stack.pushInvokeArgs(cx, 0, &nested)) return false; - nested.calleev() = cx->global()->protoGetter(); - nested.thisv() = args[0]; + nested.setCallee(cx->global()->protoGetter()); + nested.setThis(args[0]); if (!Invoke(cx, nested)) return false; args.rval().set(nested.rval()); @@ -1189,9 +1209,9 @@ GetFirstArgumentAsObject(JSContext *cx, unsigned argc, Value *vp, const char *me return false; } - const Value &v = vp[2]; + RootedValue v(cx, vp[2]); if (!v.isObject()) { - char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); + char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NullPtr()); if (!bytes) return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE, @@ -1397,9 +1417,10 @@ bool Throw(JSContext *cx, JSObject *obj, unsigned errorNumber) { if (js_ErrorFormatString[errorNumber].argCount == 1) { + RootedValue val(cx, ObjectValue(*obj)); js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, - JSDVG_IGNORE_STACK, ObjectValue(*obj), - NULL, NULL, NULL); + JSDVG_IGNORE_STACK, val, NullPtr(), + NULL, NULL); } else { JS_ASSERT(js_ErrorFormatString[errorNumber].argCount == 0); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber); @@ -1924,19 +1945,22 @@ js_PopulateObject(JSContext *cx, HandleObject newborn, HandleObject props) static JSBool obj_defineProperties(JSContext *cx, unsigned argc, Value *vp) { + CallArgs args = CallArgsFromVp(argc, vp); + /* Steps 1 and 7. */ RootedObject obj(cx); - if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperties", &obj)) + if (!GetFirstArgumentAsObject(cx, args.length(), vp, "Object.defineProperties", &obj)) return false; - vp->setObject(*obj); + args.rval().setObject(*obj); /* Step 2. */ - if (argc < 2) { + if (args.length() < 2) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED, "Object.defineProperties", "0", "s"); return false; } - RootedObject props(cx, ToObject(cx, &vp[3])); + RootedValue val(cx, args[1]); + RootedObject props(cx, ToObject(cx, val)); if (!props) return false; @@ -1955,9 +1979,9 @@ obj_create(JSContext *cx, unsigned argc, Value *vp) } CallArgs args = CallArgsFromVp(argc, vp); - const Value &v = args[0]; + RootedValue v(cx, args[0]); if (!v.isObjectOrNull()) { - char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NULL); + char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, NullPtr()); if (!bytes) return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE, @@ -4697,9 +4721,10 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive cx->stack.currentScript()->warnedAboutUndefinedProp = true; /* Ok, bad undefined property reference: whine about it. */ + RootedValue val(cx, IdToValue(id)); if (!js_ReportValueErrorFlags(cx, flags, JSMSG_UNDEFINED_PROP, - JSDVG_IGNORE_STACK, IdToValue(id), - NULL, NULL, NULL)) + JSDVG_IGNORE_STACK, val, NullPtr(), + NULL, NULL)) { return false; } @@ -4809,25 +4834,28 @@ js::CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname) bool JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report) { + RootedValue val(cx, IdToValue(id)); return js_ReportValueErrorFlags(cx, report, JSMSG_READ_ONLY, - JSDVG_IGNORE_STACK, IdToValue(id), NULL, + JSDVG_IGNORE_STACK, val, NullPtr(), NULL, NULL); } bool JSObject::reportNotConfigurable(JSContext *cx, jsid id, unsigned report) { + RootedValue val(cx, IdToValue(id)); return js_ReportValueErrorFlags(cx, report, JSMSG_CANT_DELETE, - JSDVG_IGNORE_STACK, IdToValue(id), NULL, + JSDVG_IGNORE_STACK, val, NullPtr(), NULL, NULL); } bool JSObject::reportNotExtensible(JSContext *cx, unsigned report) { + RootedValue val(cx, ObjectValue(*this)); return js_ReportValueErrorFlags(cx, report, JSMSG_OBJECT_NOT_EXTENSIBLE, - JSDVG_IGNORE_STACK, ObjectValue(*this), - NULL, NULL, NULL); + JSDVG_IGNORE_STACK, val, NullPtr(), + NULL, NULL); } bool @@ -5265,7 +5293,7 @@ DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp } /* Avoid recursive death when decompiling in js_ReportValueError. */ - JSString *str; + RootedString str(cx); if (hint == JSTYPE_STRING) { str = JS_InternString(cx, clasp->name); if (!str) @@ -5274,7 +5302,8 @@ DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp str = NULL; } - js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO, JSDVG_SEARCH_STACK, ObjectValue(*obj), str, + RootedValue val(cx, ObjectValue(*obj)); + js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO, JSDVG_SEARCH_STACK, val, str, (hint == JSTYPE_VOID) ? "primitive type" : JS_TYPE_STR(hint)); return false; } @@ -5489,21 +5518,22 @@ namespace js { /* Callers must handle the already-object case . */ JSObject * -ToObjectSlow(JSContext *cx, Value *vp) +ToObjectSlow(JSContext *cx, HandleValue val, bool reportScanStack) { - JS_ASSERT(!vp->isMagic()); - JS_ASSERT(!vp->isObject()); + JS_ASSERT(!val.isMagic()); + JS_ASSERT(!val.isObject()); - if (vp->isNullOrUndefined()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO, - vp->isNull() ? "null" : "undefined", "object"); + if (val.isNullOrUndefined()) { + if (reportScanStack) { + js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, val, NullPtr()); + } else { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO, + val.isNull() ? "null" : "undefined", "object"); + } return NULL; } - JSObject *obj = PrimitiveToObject(cx, *vp); - if (obj) - vp->setObject(*obj); - return obj; + return PrimitiveToObject(cx, val); } } @@ -5515,8 +5545,10 @@ js_ValueToNonNullObject(JSContext *cx, const Value &v) if (!js_ValueToObjectOrNull(cx, v, &obj)) return NULL; - if (!obj) - js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL); + if (!obj) { + RootedValue val(cx, v); + js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, val, NullPtr()); + } return obj; } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 47d9c9762f5d..5d96a58d48c1 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1334,27 +1334,29 @@ js_ValueToNonNullObject(JSContext *cx, const js::Value &v); namespace js { /* - * Invokes the ES5 ToObject algorithm on *vp, writing back the object to vp. - * If *vp might already be an object, use ToObject. + * Invokes the ES5 ToObject algorithm on vp, returning the result. If vp might + * already be an object, use ToObject. reportCantConvert controls how null and + * undefined errors are reported. */ extern JSObject * -ToObjectSlow(JSContext *cx, Value *vp); +ToObjectSlow(JSContext *cx, HandleValue vp, bool reportScanStack); +/* For object conversion in e.g. native functions. */ JS_ALWAYS_INLINE JSObject * -ToObject(JSContext *cx, Value *vp) +ToObject(JSContext *cx, HandleValue vp) { - if (vp->isObject()) - return &vp->toObject(); - return ToObjectSlow(cx, vp); + if (vp.isObject()) + return &vp.toObject(); + return ToObjectSlow(cx, vp, false); } -/* As for ToObject, but preserves the original value. */ -inline JSObject * -ValueToObject(JSContext *cx, const Value &v) +/* For converting stack values to objects. */ +JS_ALWAYS_INLINE JSObject * +ToObjectFromStack(JSContext *cx, HandleValue vp) { - if (v.isObject()) - return &v.toObject(); - return js_ValueToNonNullObject(cx, v); + if (vp.isObject()) + return &vp.toObject(); + return ToObjectSlow(cx, vp, true); } } /* namespace js */ diff --git a/js/src/json.cpp b/js/src/json.cpp index 7231a428f1ca..d3532509fc64 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -295,8 +295,8 @@ PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleVa if (!cx->stack.pushInvokeArgs(cx, 1, &args)) return false; - args.calleev() = toJSON; - args.thisv() = vp; + args.setCallee(toJSON); + args.setThis(vp); args[0] = StringValue(keyStr); if (!Invoke(cx, args)) @@ -317,8 +317,8 @@ PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleVa if (!cx->stack.pushInvokeArgs(cx, 2, &args)) return false; - args.calleev() = ObjectValue(*scx->replacer); - args.thisv() = ObjectValue(*holder); + args.setCallee(ObjectValue(*scx->replacer)); + args.setThis(ObjectValue(*holder)); args[0] = StringValue(keyStr); args[1] = vp; @@ -838,8 +838,8 @@ Walk(JSContext *cx, HandleObject holder, HandleId name, HandleValue reviver, Mut if (!cx->stack.pushInvokeArgs(cx, 2, &args)) return false; - args.calleev() = reviver; - args.thisv() = ObjectValue(*holder); + args.setCallee(reviver); + args.setThis(ObjectValue(*holder)); args[0] = StringValue(key); args[1] = val; diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 4bcf48e51f78..59a4f7f95b1b 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -6200,9 +6200,10 @@ DecompileExpressionFromStack(JSContext *cx, int spindex, Value v, char **res) } char * -js_DecompileValueGenerator(JSContext *cx, int spindex, jsval v, - JSString *fallback) +js::DecompileValueGenerator(JSContext *cx, int spindex, HandleValue v, + HandleString fallbackArg) { + RootedString fallback(cx, fallbackArg); { char *result; if (!DecompileExpressionFromStack(cx, spindex, v, &result)) diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 3491fe260d6b..a057d5a12ed1 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -321,22 +321,6 @@ js_DecompileToString(JSContext *cx, const char *name, JSFunction *fun, unsigned indent, JSBool pretty, JSBool grouped, JSBool strict, JSDecompilerPtr decompiler); -/* - * Find the source expression that resulted in v, and return a newly allocated - * C-string containing it. Fall back on v's string conversion (fallback) if we - * can't find the bytecode that generated and pushed v on the operand stack. - * - * Search the current stack frame if spindex is JSDVG_SEARCH_STACK. Don't - * look for v on the stack if spindex is JSDVG_IGNORE_STACK. Otherwise, - * spindex is the negative index of v, measured from cx->fp->sp, or from a - * lower frame's sp if cx->fp is native. - * - * The caller must call JS_free on the result after a succsesful call. - */ -extern char * -js_DecompileValueGenerator(JSContext *cx, int spindex, jsval v, - JSString *fallback); - /* * Given bytecode address pc in script's main program code, return the operand * stack depth just before (JSOp) *pc executes. @@ -361,12 +345,20 @@ js_GetVariableBytecodeLength(jsbytecode *pc); namespace js { -static inline char * -DecompileValueGenerator(JSContext *cx, int spindex, const Value &v, - JSString *fallback) -{ - return js_DecompileValueGenerator(cx, spindex, v, fallback); -} +/* + * Find the source expression that resulted in v, and return a newly allocated + * C-string containing it. Fall back on v's string conversion (fallback) if we + * can't find the bytecode that generated and pushed v on the operand stack. + * + * Search the current stack frame if spindex is JSDVG_SEARCH_STACK. Don't + * look for v on the stack if spindex is JSDVG_IGNORE_STACK. Otherwise, + * spindex is the negative index of v, measured from cx->fp->sp, or from a + * lower frame's sp if cx->fp is native. + * + * The caller must call JS_free on the result after a succsesful call. + */ +char * +DecompileValueGenerator(JSContext *cx, int spindex, HandleValue v, HandleString fallback); /* * Sprintf, but with unlimited and automatically allocated buffering. diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 25c0121f9c56..dbc77105478f 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -352,8 +352,10 @@ bool BaseProxyHandler::hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp) { JS_ASSERT(OperationInProgress(cx, proxy)); + + RootedValue val(cx, ObjectValue(*proxy)); js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, - JSDVG_SEARCH_STACK, ObjectValue(*proxy), NULL); + JSDVG_SEARCH_STACK, val, NullPtr()); return false; } @@ -493,7 +495,7 @@ bool IndirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args) { - args.thisv() = ObjectValue(*GetProxyTargetObject(&args.thisv().toObject())); + args.setThis(ObjectValue(*GetProxyTargetObject(&args.thisv().toObject()))); if (!test(args.thisv())) { ReportIncompatible(cx, args); return false; @@ -825,8 +827,9 @@ ReturnedValueMustNotBePrimitive(JSContext *cx, JSObject *proxy, JSAtom *atom, co if (v.isPrimitive()) { JSAutoByteString bytes; if (js_AtomToPrintableString(cx, atom, &bytes)) { + RootedValue val(cx, ObjectOrNullValue(proxy)); js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE, - JSDVG_SEARCH_STACK, ObjectOrNullValue(proxy), NULL, bytes.ptr()); + JSDVG_SEARCH_STACK, val, NullPtr(), bytes.ptr()); } return false; } @@ -1074,10 +1077,12 @@ class AutoPendingProxyOperation { bool -Proxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, +Proxy::getPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, bool set, PropertyDescriptor *desc) { JS_CHECK_RECURSION(cx, return false); + RootedObject proxy(cx, proxy_); + RootedId id(cx, id_); AutoPendingProxyOperation pending(cx, proxy); BaseProxyHandler *handler = GetProxyHandler(proxy); if (!handler->hasPrototype()) @@ -1193,9 +1198,11 @@ Proxy::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) } bool -Proxy::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp) +Proxy::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp) { JS_CHECK_RECURSION(cx, return false); + RootedObject proxy(cx, proxy_); + RootedId id(cx, id_); AutoPendingProxyOperation pending(cx, proxy); BaseProxyHandler *handler = GetProxyHandler(proxy); if (!handler->hasPrototype()) @@ -1258,14 +1265,14 @@ Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id JS_CHECK_RECURSION(cx, return false); AutoPendingProxyOperation pending(cx, proxy); BaseProxyHandler *handler = GetProxyHandler(proxy); - JSObject *proto; + RootedObject proto(cx); if (handler->hasPrototype()) { // If we're using a prototype, we still want to use the proxy trap unless // we have a non-own property with a setter. bool hasOwn; AutoPropertyDescriptorRooter desc(cx); if (handler->hasOwn(cx, proxy, id, &hasOwn) && !hasOwn && - handler->getPrototypeOf(cx, proxy, &proto) && proto && + handler->getPrototypeOf(cx, proxy, proto.address()) && proto && JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, &desc) && desc.obj && desc.setter) { diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index 44f898e3144a..525b0e59c9e1 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -186,7 +186,7 @@ class NodeBuilder if (!funv.isObject() || !funv.toObject().isFunction()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NOT_FUNCTION, - JSDVG_SEARCH_STACK, funv, NULL, NULL, NULL); + JSDVG_SEARCH_STACK, funv, NullPtr(), NULL, NULL); return false; } @@ -3183,12 +3183,12 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp) JSObject *builder = NULL; - Value arg = argc > 1 ? JS_ARGV(cx, vp)[1] : UndefinedValue(); + RootedValue arg(cx, argc > 1 ? JS_ARGV(cx, vp)[1] : UndefinedValue()); if (!arg.isNullOrUndefined()) { if (!arg.isObject()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, - JSDVG_SEARCH_STACK, arg, NULL, "not an object", NULL); + JSDVG_SEARCH_STACK, arg, NullPtr(), "not an object", NULL); return JS_FALSE; } @@ -3245,7 +3245,7 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp) if (!prop.isNullOrUndefined()) { if (!prop.isObject()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, - JSDVG_SEARCH_STACK, prop, NULL, "not an object", NULL); + JSDVG_SEARCH_STACK, prop, NullPtr(), "not an object", NULL); return JS_FALSE; } builder = &prop.toObject(); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index f398a1379dd3..d76b2bb1821e 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -440,7 +440,7 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call) Rooted id(cx, NameToId(cx->runtime->atomState.toStringAtom)); if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) { JSString *str = obj->asString().unbox(); - call.thisv().setString(str); + call.setThis(StringValue(str)); return str; } } @@ -454,7 +454,7 @@ ThisToStringForStringProto(JSContext *cx, CallReceiver call) if (!str) return NULL; - call.thisv().setString(str); + call.setThis(StringValue(str)); return str; } @@ -1022,7 +1022,7 @@ StringMatch(const jschar *text, uint32_t textlen, static const size_t sRopeMatchThresholdRatioLog2 = 5; /* - * RopeMatch takes the text to search, the patern to search for in the text. + * RopeMatch takes the text to search and the pattern to search for in the text. * RopeMatch returns false on OOM and otherwise returns the match index through * the 'match' outparam (-1 for not found). */ @@ -1148,6 +1148,9 @@ str_contains(JSContext *cx, unsigned argc, Value *vp) if (!text) return false; + // XXX fix for moving GC. + SkipRoot skip(cx, &text); + if (args.hasDefined(1)) { // Step 4 double posDouble; @@ -1325,6 +1328,9 @@ str_startsWith(JSContext *cx, unsigned argc, Value *vp) if (!text) return false; + // XXX fix for moving GC. + SkipRoot skip(cx, &text); + if (args.hasDefined(1)) { // Step 4 double posDouble; @@ -1368,6 +1374,9 @@ str_endsWith(JSContext *cx, unsigned argc, Value *vp) if (!text) return false; + // XXX fix for moving GC. + SkipRoot skip(cx, &text); + if (args.hasDefined(1)) { // Step 5 double endPosDouble; @@ -1978,7 +1987,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t return false; args.setCallee(ObjectValue(*lambda)); - args.thisv() = UndefinedValue(); + args.setThis(UndefinedValue()); /* Push $&, $1, $2, ... */ unsigned argi = 0; @@ -2296,8 +2305,8 @@ str_replace_flat_lambda(JSContext *cx, CallArgs outerArgs, ReplaceData &rdata, c return false; CallArgs &args = rdata.args; - args.calleev().setObject(*rdata.lambda); - args.thisv().setUndefined(); + args.setCallee(ObjectValue(*rdata.lambda)); + args.setThis(UndefinedValue()); Value *sp = args.array(); sp[0].setString(matchStr); @@ -2769,7 +2778,7 @@ static JSBool str_substr(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); - JSString *str = ThisToStringForStringProto(cx, args); + RootedString str(cx, ThisToStringForStringProto(cx, args)); if (!str) return false; diff --git a/js/src/jsstrinlines.h b/js/src/jsstrinlines.h index 415ed9ca0df5..3cf050966f38 100644 --- a/js/src/jsstrinlines.h +++ b/js/src/jsstrinlines.h @@ -46,8 +46,8 @@ class StringSegmentRange * If malloc() shows up in any profiles from this vector, we can add a new * StackAllocPolicy which stashes a reusable freed-at-gc buffer in the cx. */ - Vector stack; - JSLinearString *cur; + AutoStringVector stack; + Rooted cur; bool settle(JSString *str) { while (str->isRope()) { @@ -62,7 +62,7 @@ class StringSegmentRange public: StringSegmentRange(JSContext *cx) - : stack(cx), cur(NULL) + : stack(cx), cur(cx) {} JS_WARN_UNUSED_RESULT bool init(JSString *str) { diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index c387f9ab85c8..05efe98cf5f7 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -143,10 +143,9 @@ ArrayBufferObject::fun_slice_impl(JSContext *cx, CallArgs args) JS_ASSERT(IsArrayBuffer(args.thisv())); Rooted thisObj(cx, &args.thisv().toObject()); - ArrayBufferObject &arrayBuffer = thisObj->asArrayBuffer(); // these are the default values - uint32_t length = arrayBuffer.byteLength(); + uint32_t length = thisObj->asArrayBuffer().byteLength(); uint32_t begin = 0, end = length; if (args.length() > 0) { @@ -162,7 +161,7 @@ ArrayBufferObject::fun_slice_impl(JSContext *cx, CallArgs args) if (begin > end) begin = end; - JSObject *nobj = createSlice(cx, arrayBuffer, begin, end); + JSObject *nobj = createSlice(cx, thisObj->asArrayBuffer(), begin, end); if (!nobj) return false; args.rval().setObject(*nobj); @@ -1678,8 +1677,8 @@ class TypedArrayTemplate if (!cx->stack.pushInvokeArgs(cx, 3, &ag)) return NULL; - ag.calleev() = cx->compartment->maybeGlobal()->createArrayFromBuffer(); - ag.thisv() = ObjectValue(*bufobj); + ag.setCallee(cx->compartment->maybeGlobal()->createArrayFromBuffer()); + ag.setThis(ObjectValue(*bufobj)); ag[0] = Int32Value(byteOffsetInt); ag[1] = Int32Value(lengthInt); ag[2] = ObjectValue(*proto); @@ -2262,8 +2261,8 @@ DataViewObject::class_constructor(JSContext *cx, unsigned argc, Value *vp) InvokeArgsGuard ag; if (!cx->stack.pushInvokeArgs(cx, argc + 1, &ag)) return false; - ag.calleev() = global->createDataViewForThis(); - ag.thisv() = ObjectValue(*bufobj); + ag.setCallee(global->createDataViewForThis()); + ag.setThis(ObjectValue(*bufobj)); PodCopy(ag.array(), args.array(), args.length()); ag[argc] = ObjectValue(*proto); if (!Invoke(cx, ag)) diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 0d91d1cfd8fe..42ad44e075ee 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -205,7 +205,7 @@ static JSPropertySpec namespace_props[] = { static JSBool namespace_toString(JSContext *cx, unsigned argc, Value *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return JS_FALSE; if (!obj->isNamespace()) { @@ -395,7 +395,7 @@ ConvertQNameToString(JSContext *cx, JSObject *obj) static JSBool qname_toString(JSContext *cx, unsigned argc, Value *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return false; @@ -1897,8 +1897,9 @@ ToXML(JSContext *cx, jsval v) return obj; bad: + RootedValue val(cx, v); js_ReportValueError(cx, JSMSG_BAD_XML_CONVERSION, - JSDVG_IGNORE_STACK, v, NULL); + JSDVG_IGNORE_STACK, val, NullPtr()); return NULL; } @@ -1973,8 +1974,9 @@ ToXMLList(JSContext *cx, jsval v) return listobj; bad: + RootedValue val(cx, v); js_ReportValueError(cx, JSMSG_BAD_XMLLIST_CONVERSION, - JSDVG_IGNORE_STACK, v, NULL); + JSDVG_IGNORE_STACK, val, NullPtr()); return NULL; } @@ -2789,8 +2791,9 @@ ToAttributeName(JSContext *cx, jsval v) uri = prefix = cx->runtime->emptyString; } else { if (JSVAL_IS_PRIMITIVE(v)) { + RootedValue val(cx, v); js_ReportValueError(cx, JSMSG_BAD_XML_ATTR_NAME, - JSDVG_IGNORE_STACK, v, NULL); + JSDVG_IGNORE_STACK, val, NullPtr()); return NULL; } @@ -2825,7 +2828,8 @@ ToAttributeName(JSContext *cx, jsval v) static void ReportBadXMLName(JSContext *cx, const Value &idval) { - js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, idval, NULL); + RootedValue val(cx, idval); + js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, val, NullPtr()); } namespace js { @@ -5372,7 +5376,7 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, MutableHandleObject objp) JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp)); JS_ASSERT(JSVAL_TO_OBJECT(*vp)->isFunction()); - objp.set(ToObject(cx, &vp[1])); + objp.set(ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!objp) return NULL; if (!objp->isXML()) { @@ -5406,7 +5410,7 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, MutableHandleObject objp) /* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */ #define XML_METHOD_PROLOG \ - JSObject *obj = ToObject(cx, &vp[1]); \ + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); \ if (!obj) \ return JS_FALSE; \ if (!obj->isXML()) { \ @@ -5490,7 +5494,8 @@ xml_attribute(JSContext *cx, unsigned argc, jsval *vp) JSObject *qn; if (argc == 0) { - js_ReportMissingArg(cx, *vp, 0); + RootedValue val(cx, *vp); + js_ReportMissingArg(cx, val, 0); return JS_FALSE; } @@ -5500,7 +5505,7 @@ xml_attribute(JSContext *cx, unsigned argc, jsval *vp) vp[2] = OBJECT_TO_JSVAL(qn); /* local root */ RootedId id(cx, OBJECT_TO_JSID(qn)); - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!obj) return JS_FALSE; return GetProperty(cx, obj, id, MutableHandleValue::fromMarkedLocation(vp)); @@ -5516,7 +5521,7 @@ xml_attributes(JSContext *cx, unsigned argc, jsval *vp) return JS_FALSE; RootedId id(cx, OBJECT_TO_JSID(qn)); - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!obj) return JS_FALSE; return GetProperty(cx, obj, id, MutableHandleValue::fromMarkedLocation(vp)); @@ -5676,7 +5681,7 @@ xml_childIndex(JSContext *cx, unsigned argc, jsval *vp) static JSBool xml_children(JSContext *cx, unsigned argc, jsval *vp) { - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!obj) return false; RootedId name(cx, NameToId(cx->runtime->atomState.starAtom)); @@ -5883,7 +5888,7 @@ xml_hasOwnProperty(JSContext *cx, unsigned argc, jsval *vp) jsval name; JSBool found; - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return JS_FALSE; if (!obj->isXML()) { @@ -6925,7 +6930,7 @@ xml_toString_helper(JSContext *cx, JSXML *xml) static JSBool xml_toSource(JSContext *cx, unsigned argc, jsval *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return JS_FALSE; JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), TO_SOURCE_FLAG); @@ -6952,7 +6957,7 @@ xml_toString(JSContext *cx, unsigned argc, jsval *vp) static JSBool xml_toXMLString(JSContext *cx, unsigned argc, jsval *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return JS_FALSE; JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), 0); @@ -6966,7 +6971,7 @@ xml_toXMLString(JSContext *cx, unsigned argc, jsval *vp) static JSBool xml_valueOf(JSContext *cx, unsigned argc, jsval *vp) { - JSObject *obj = ToObject(cx, &vp[1]); + JSObject *obj = ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])); if (!obj) return false; *vp = OBJECT_TO_JSVAL(obj); @@ -7066,7 +7071,7 @@ xml_settings(JSContext *cx, unsigned argc, jsval *vp) if (!settings) return false; *vp = OBJECT_TO_JSVAL(settings); - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!obj) return false; return CopyXMLSettings(cx, obj, settings); @@ -7078,7 +7083,7 @@ xml_setSettings(JSContext *cx, unsigned argc, jsval *vp) jsval v; JSBool ok; - RootedObject obj(cx, ToObject(cx, &vp[1])); + RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1]))); if (!obj) return JS_FALSE; v = (argc == 0) ? JSVAL_VOID : vp[2]; @@ -7882,7 +7887,8 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized) * value stored in sp[-2]. */ if (!VALUE_IS_XML(sp[-2])) { - js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, sp[-2], NULL); + RootedValue val(cx, sp[-2]); + js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, val, NullPtr()); return JS_FALSE; } obj = JSVAL_TO_OBJECT(sp[-2]); diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index f81e091b4d63..88c822fff342 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -1005,7 +1005,8 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM * portion of fun_hasInstance. */ if (f.regs.sp[0].isPrimitive()) { - js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, f.regs.sp[-1], NULL); + RootedValue val(cx, f.regs.sp[-1]); + js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, val, NullPtr()); return js_InternalThrow(f); } nextsp[-1].setBoolean(js_IsDelegate(cx, &f.regs.sp[0].toObject(), f.regs.sp[-2])); diff --git a/js/src/methodjit/MonoIC.cpp b/js/src/methodjit/MonoIC.cpp index e599c54d858d..82669b8bd2a9 100644 --- a/js/src/methodjit/MonoIC.cpp +++ b/js/src/methodjit/MonoIC.cpp @@ -771,7 +771,7 @@ class CallCompiler : public BaseCompiler return false; if (callingNew) - args.thisv().setMagic(JS_IS_CONSTRUCTING); + args.setThis(MagicValue(JS_IS_CONSTRUCTING)); RecompilationMonitor monitor(cx); diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index 6d46c114ad50..123fa938e713 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -1948,6 +1948,8 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) } } + RootedValue objval(f.cx, f.regs.sp[-1]); + if (f.regs.sp[-1].isString()) { GetPropCompiler cc(f, NULL, *pic, name, stub); if (name == f.cx->runtime->atomState.lengthAtom) { @@ -1960,7 +1962,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) LookupStatus status = cc.generateStringPropertyStub(); if (status == Lookup_Error) THROW(); - JSObject *obj = ValueToObject(f.cx, f.regs.sp[-1]); + JSObject *obj = ToObjectFromStack(f.cx, objval); if (!obj) THROW(); if (!obj->getProperty(f.cx, name, MutableHandleValue::fromMarkedLocation(&f.regs.sp[-1]))) @@ -1971,7 +1973,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) RecompilationMonitor monitor(f.cx); - RootedObject obj(f.cx, ValueToObject(f.cx, f.regs.sp[-1])); + RootedObject obj(f.cx, ToObjectFromStack(f.cx, objval)); if (!obj) THROW(); @@ -1983,7 +1985,7 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic) RootedValue v(f.cx); if (cached) { - if (!GetPropertyOperation(f.cx, f.script(), f.pc(), f.regs.sp[-1], v.address())) + if (!GetPropertyOperation(f.cx, f.pc(), &objval, &v)) THROW(); } else { if (!obj->getProperty(f.cx, name, &v)) @@ -2013,7 +2015,8 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic) RecompilationMonitor monitor(f.cx); - JSObject *obj = ValueToObject(f.cx, f.regs.sp[-2]); + RootedValue objval(f.cx, f.regs.sp[-2]); + JSObject *obj = ToObjectFromStack(f.cx, objval); if (!obj) THROW(); @@ -2550,12 +2553,12 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic) return; } - RootedValue idval_(cx, f.regs.sp[-1]); - Value &idval = idval_.get(); + RootedValue idval(cx, f.regs.sp[-1]); RecompilationMonitor monitor(cx); - RootedObject obj(cx, ValueToObject(cx, f.regs.sp[-2])); + RootedValue objval(f.cx, f.regs.sp[-2]); + RootedObject obj(cx, ToObjectFromStack(cx, objval)); if (!obj) THROW(); @@ -2583,7 +2586,7 @@ ic::GetElement(VMFrame &f, ic::GetElementIC *ic) #ifdef DEBUG f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC); #endif - LookupStatus status = ic->update(f, obj, idval_, id, res); + LookupStatus status = ic->update(f, obj, idval, id, res); if (status != Lookup_Uncacheable && status != Lookup_NoProperty) { if (status == Lookup_Error) THROW(); diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index baab202fa0e7..3f65e4c05460 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -72,8 +72,8 @@ void JS_FASTCALL stubs::SetName(VMFrame &f, PropertyName *name) { JSContext *cx = f.cx; - const Value &rval = f.regs.sp[-1]; - const Value &lval = f.regs.sp[-2]; + HandleValue rval = HandleValue::fromMarkedLocation(&f.regs.sp[-1]); + HandleValue lval = HandleValue::fromMarkedLocation(&f.regs.sp[-2]); if (!SetPropertyOperation(cx, f.pc(), lval, rval)) THROW(); @@ -106,11 +106,11 @@ stubs::Name(VMFrame &f) void JS_FASTCALL stubs::GetElem(VMFrame &f) { - Value &lref = f.regs.sp[-2]; - Value &rref = f.regs.sp[-1]; + MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(&f.regs.sp[-2]); + HandleValue rval = HandleValue::fromMarkedLocation(&f.regs.sp[-1]); MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&f.regs.sp[-2]); - if (!GetElementOperation(f.cx, JSOp(*f.pc()), lref, rref, res)) + if (!GetElementOperation(f.cx, JSOp(*f.pc()), lval, rval, res)) THROW(); } @@ -121,13 +121,13 @@ stubs::SetElem(VMFrame &f) JSContext *cx = f.cx; FrameRegs ®s = f.regs; - Value &objval = regs.sp[-3]; + HandleValue objval = HandleValue::fromMarkedLocation(®s.sp[-3]); Value &idval = regs.sp[-2]; RootedValue rval(cx, regs.sp[-1]); RootedId id(cx); - Rooted obj(cx, ValueToObject(cx, objval)); + Rooted obj(cx, ToObjectFromStack(cx, objval)); if (!obj) THROW(); @@ -174,10 +174,10 @@ template void JS_FASTCALL stubs::SetElem(VMFrame &f); void JS_FASTCALL stubs::ToId(VMFrame &f) { - Value &objval = f.regs.sp[-2]; + HandleValue objval = HandleValue::fromMarkedLocation(&f.regs.sp[-2]); MutableHandleValue idval = MutableHandleValue::fromMarkedLocation(&f.regs.sp[-1]); - JSObject *obj = ValueToObject(f.cx, objval); + JSObject *obj = ToObjectFromStack(f.cx, objval); if (!obj) THROW(); @@ -983,8 +983,10 @@ stubs::GetProp(VMFrame &f, PropertyName *name) JSContext *cx = f.cx; FrameRegs ®s = f.regs; + MutableHandleValue objval = MutableHandleValue::fromMarkedLocation(&f.regs.sp[-1]); + RootedValue rval(cx); - if (!GetPropertyOperation(cx, f.script(), f.pc(), f.regs.sp[-1], rval.address())) + if (!GetPropertyOperation(cx, f.pc(), objval, &rval)) THROW(); regs.sp[-1] = rval; @@ -1142,10 +1144,10 @@ stubs::InstanceOf(VMFrame &f) JSContext *cx = f.cx; FrameRegs ®s = f.regs; - const Value &rref = regs.sp[-1]; + RootedValue rref(cx, regs.sp[-1]); if (rref.isPrimitive()) { js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, - -1, rref, NULL); + -1, rref, NullPtr()); THROWV(JS_FALSE); } RootedObject obj(cx, &rref.toObject()); @@ -1167,7 +1169,8 @@ stubs::FastInstanceOf(VMFrame &f) * Throw a runtime error if instanceof is called on a function that * has a non-object as its .prototype value. */ - js_ReportValueError(f.cx, JSMSG_BAD_PROTOTYPE, -1, f.regs.sp[-2], NULL); + RootedValue val(f.cx, f.regs.sp[-2]); + js_ReportValueError(f.cx, JSMSG_BAD_PROTOTYPE, -1, val, NullPtr()); THROW(); } @@ -1365,7 +1368,8 @@ stubs::DelProp(VMFrame &f, PropertyName *name_) JSContext *cx = f.cx; RootedPropertyName name(cx, name_); - JSObject *obj = ValueToObject(cx, f.regs.sp[-1]); + RootedValue objval(cx, f.regs.sp[-1]); + JSObject *obj = ToObjectFromStack(cx, objval); if (!obj) THROW(); @@ -1385,7 +1389,8 @@ stubs::DelElem(VMFrame &f) { JSContext *cx = f.cx; - JSObject *obj = ValueToObject(cx, f.regs.sp[-2]); + RootedValue objval(cx, f.regs.sp[-2]); + JSObject *obj = ToObjectFromStack(cx, objval); if (!obj) THROW(); @@ -1434,7 +1439,8 @@ stubs::In(VMFrame &f) const Value &rref = f.regs.sp[-1]; if (!rref.isObject()) { - js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL); + RootedValue val(cx, rref); + js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, val, NullPtr()); THROWV(JS_FALSE); } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 1c63613a09f5..d5ecc35816e8 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2534,9 +2534,9 @@ NewSandbox(JSContext *cx, bool lazy) static JSBool EvalInContext(JSContext *cx, unsigned argc, jsval *vp) { - JSString *str; + RootedString str(cx); RootedObject sobj(cx); - if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S / o", &str, sobj.address())) + if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S / o", str.address(), sobj.address())) return false; size_t srclen; diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 5e4a62fadb9b..3251bd6ac301 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -105,8 +105,9 @@ ValueToIdentifier(JSContext *cx, const Value &v, jsid *idp) if (!ValueToId(cx, v, &id)) return false; if (!JSID_IS_ATOM(id) || !IsIdentifier(JSID_TO_ATOM(id))) { + RootedValue val(cx, v); js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, - JSDVG_SEARCH_STACK, v, NULL, "not an identifier", NULL); + JSDVG_SEARCH_STACK, val, NullPtr(), "not an identifier", NULL); return false; } *idp = id; @@ -1472,7 +1473,6 @@ Debugger::sweepAll(FreeOp *fop) for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) dbg->removeDebuggeeGlobal(fop, e.front(), NULL, &e); } - } for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++) { @@ -1971,12 +1971,18 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global, * for sure, and possibly the compartment's debuggee set. */ v->erase(p); - if (v->empty()) - global->compartment()->removeDebuggee(fop, global, compartmentEnum); if (debugEnum) debugEnum->removeFront(); else debuggees.remove(global); + + /* + * The debuggee needs to be removed from the compartment last, as this can + * trigger GCs if the compartment's debug mode is being changed, and the + * global cannot be rooted on the stack without a cx. + */ + if (v->empty()) + global->compartment()->removeDebuggee(fop, global, compartmentEnum); } /* @@ -3171,7 +3177,7 @@ DebuggerArguments_getArg(JSContext *cx, unsigned argc, Value *vp) * Put the Debugger.Frame into the this-value slot, then use THIS_FRAME * to check that it is still live and get the fp. */ - args.thisv() = argsobj->getReservedSlot(JSSLOT_DEBUGARGUMENTS_FRAME); + args.setThis(argsobj->getReservedSlot(JSSLOT_DEBUGARGUMENTS_FRAME)); THIS_FRAME(cx, argc, vp, "get argument", ca2, thisobj, fp); /* @@ -3907,7 +3913,9 @@ DebuggerObject_defineProperties(JSContext *cx, unsigned argc, Value *vp) { THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "defineProperties", args, dbg, obj); REQUIRE_ARGC("Debugger.Object.defineProperties", 1); - RootedObject props(cx, ToObject(cx, &args[0])); + + RootedValue arg(cx, args[0]); + RootedObject props(cx, ToObject(cx, arg)); if (!props) return false; diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 08e77bd2145a..402d4bae549b 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -418,10 +418,11 @@ DenseElementsHeader::defineElement(JSContext *cx, Handle obj, uint3 *succeeded = false; if (!shouldThrow) return true; + RootedValue val(cx, ObjectValue(*obj)); MOZ_ALWAYS_FALSE(js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_OBJECT_NOT_EXTENSIBLE, JSDVG_IGNORE_STACK, - ObjectValue(*obj), - NULL, NULL, NULL)); + val, NullPtr(), + NULL, NULL)); return false; } @@ -466,10 +467,11 @@ TypedElementsHeader::defineElement(JSContext *cx, Handle obj, { /* XXX jwalden This probably isn't how typed arrays should behave... */ *succeeded = false; + + RootedValue val(cx, ObjectValue(*obj)); js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_OBJECT_NOT_EXTENSIBLE, JSDVG_IGNORE_STACK, - ObjectValue(*obj), - NULL, NULL, NULL); + val, NullPtr(), NULL, NULL); return false; } @@ -629,8 +631,8 @@ js::GetElement(JSContext *cx, Handle obj, Handle recei return false; /* Push get, receiver, and no args. */ - args.calleev() = get; - args.thisv() = ObjectValue(*current); + args.setCallee(get); + args.setThis(ObjectValue(*current)); bool ok = Invoke(cx, args); *vp = args.rval(); @@ -861,8 +863,8 @@ js::SetElement(JSContext *cx, Handle obj, Handle recei return false; /* Push set, receiver, and v as the sole argument. */ - args.calleev() = setter; - args.thisv() = ObjectValue(*current); + args.setCallee(setter); + args.setThis(ObjectValue(*current)); args[0] = v; *succeeded = true; diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index a16a173fdef9..65862e3bf086 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -1369,8 +1369,9 @@ class DebugScopeProxy : public BaseProxyHandler bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) MOZ_OVERRIDE { + RootedValue val(cx, IdToValue(id)); return js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_CANT_DELETE, - JSDVG_IGNORE_STACK, IdToValue(id), NULL, + JSDVG_IGNORE_STACK, val, NullPtr(), NULL, NULL); } diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 6db09c94ce4e..b78720e347c7 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -3109,7 +3109,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl // check to see if we can reuse a mask image const MaskLayerImageCache::MaskLayerImageKey* key = - new MaskLayerImageCache::MaskLayerImageKey(roundedRects); + new MaskLayerImageCache::MaskLayerImageKey(roundedRects, aLayer->Manager()->GetBackendType()); const MaskLayerImageCache::MaskLayerImageKey* lookupKey = key; nsRefPtr container = diff --git a/layout/base/MaskLayerImageCache.h b/layout/base/MaskLayerImageCache.h index 3dd54a530cfb..288aad2afa0e 100644 --- a/layout/base/MaskLayerImageCache.h +++ b/layout/base/MaskLayerImageCache.h @@ -113,8 +113,9 @@ public: class MaskLayerImageKey { public: - MaskLayerImageKey(const nsTArray& aRoundedClipRects) - : mLayerCount(0) + MaskLayerImageKey(const nsTArray& aRoundedClipRects, layers::LayersBackend aBackend) + : mBackend(aBackend) + , mLayerCount(0) , mRoundedClipRects(aRoundedClipRects) {} @@ -132,6 +133,7 @@ public: for (PRUint32 i = 0; i < mRoundedClipRects.Length(); ++i) { hash = AddToHash(hash, mRoundedClipRects[i].Hash()); } + hash = AddToHash(hash, mBackend); return hash; } @@ -141,6 +143,7 @@ public: return mRoundedClipRects == aOther.mRoundedClipRects; } + layers::LayersBackend mBackend; mutable PRUint32 mLayerCount; nsTArray mRoundedClipRects; }; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 750373a8c0a6..35218d0fb5d3 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7976,6 +7976,31 @@ nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent, NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr) +/** + * Return true if aFrame's subtree has placeholders for abs-pos or fixed-pos + * content. + */ +static bool +FrameHasAbsPosPlaceholderDescendants(nsIFrame* aFrame) +{ + const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList | + nsIFrame::kFixedList); + for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) { + if (!skip.Contains(lists.CurrentID())) { + for (nsFrameList::Enumerator childFrames(lists.CurrentList()); + !childFrames.AtEnd(); childFrames.Next()) { + nsIFrame* f = childFrames.get(); + if ((f->GetType() == nsGkAtoms::placeholderFrame && + nsPlaceholderFrame::GetRealFrameForPlaceholder(f)->IsAbsolutelyPositioned()) || + FrameHasAbsPosPlaceholderDescendants(f)) { + return true; + } + } + } + } + return false; +} + nsresult nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList) { @@ -8036,6 +8061,20 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList) continue; } + if ((hint & nsChangeHint_AddOrRemoveTransform) && frame && + !(hint & nsChangeHint_ReconstructFrame)) { + if (FrameHasAbsPosPlaceholderDescendants(frame)) { + NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); + } else { + // We can just add this state bit unconditionally, since it's + // conservative. Normally frame construction would set this if needed, + // but we're not going to reconstruct the frame so we need to set it. + // It's because we need to set this bit on each affected frame + // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up + // to ancestors (i.e. it can't be an inherited change hint). + frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED); + } + } if (hint & nsChangeHint_ReconstructFrame) { // If we ever start passing true here, be careful of restyles // that involve a reframe and animations. In particular, if the diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index f66cbb3c68d9..98687e90b8ce 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -101,6 +101,14 @@ enum nsChangeHint { */ nsChangeHint_RecomputePosition = 0x2000, + /** + * Behaves like ReconstructFrame, but only if the frame has descendants + * that are absolutely or fixed position. Use this hint when a style change + * has changed whether the frame is a container for fixed-pos or abs-pos + * elements, but reframing is otherwise not needed. + */ + nsChangeHint_AddOrRemoveTransform = 0x4000, + /** * We have an optimization when processing change hints which prevents * us from visiting the descendants of a node when a hint on that node @@ -116,7 +124,8 @@ enum nsChangeHint { nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateOverflow | nsChangeHint_ChildrenOnlyTransform | - nsChangeHint_RecomputePosition + nsChangeHint_RecomputePosition | + nsChangeHint_AddOrRemoveTransform }; // Redefine these operators to return nothing. This will catch any use diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 30a974ca11ce..97922daa2ce7 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1037,7 +1037,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, layerBuilder->WillEndTransaction(layerManager); bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap()); layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, - aBuilder); + aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT); aBuilder->SetIsCompositingCheap(temp); layerBuilder->DidEndTransaction(layerManager); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 750811e114c3..4331ed5a58ce 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -24,6 +24,7 @@ #include "FrameLayerBuilder.h" #include "nsThemeConstants.h" #include "ImageLayers.h" +#include "nsLayoutUtils.h" #include "mozilla/StandardInteger.h" @@ -1177,7 +1178,8 @@ public: PAINT_DEFAULT = 0, PAINT_USE_WIDGET_LAYERS = 0x01, PAINT_FLUSH_LAYERS = 0x02, - PAINT_EXISTING_TRANSACTION = 0x04 + PAINT_EXISTING_TRANSACTION = 0x04, + PAINT_NO_COMPOSITE = 0x08 }; void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, PRUint32 aFlags) const; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 79169524b073..d29fba528c1b 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1217,9 +1217,13 @@ public: */ virtual void SynthesizeMouseMove(bool aFromScroll) = 0; - virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget, - const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion, - bool aWillSendDidPaint) = 0; + enum PaintType { + PaintType_Composite, /* Just composite the layers, don't do ThebesLayer painting. */ + PaintType_NoComposite, /* Only paint ThebesLayers, don't composite. */ + PaintType_Full /* Do a full transaction. */ + }; + virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion, + PaintType aType, bool aWillSendDidPaint) = 0; virtual nsresult HandleEvent(nsIFrame* aFrame, nsGUIEvent* aEvent, bool aDontRetargetEvents, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index ff6ace446296..069a7c6be51e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1861,6 +1861,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram if (aFlags & PAINT_EXISTING_TRANSACTION) { flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION; } + if (aFlags & PAINT_NO_COMPOSITE) { + flags |= nsDisplayList::PAINT_NO_COMPOSITE; + } list.PaintRoot(&builder, aRenderingContext, flags); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 0d5a025df001..88bdc2e0c73c 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -598,7 +598,8 @@ public: PAINT_HIDE_CARET = 0x20, PAINT_ALL_CONTINUATIONS = 0x40, PAINT_TO_WINDOW = 0x80, - PAINT_EXISTING_TRANSACTION = 0x100 + PAINT_EXISTING_TRANSACTION = 0x100, + PAINT_NO_COMPOSITE = 0x200 }; /** diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index dd662d41245d..493148697aa1 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5249,9 +5249,8 @@ private: void PresShell::Paint(nsIView* aViewToPaint, - nsIWidget* aWidgetToPaint, const nsRegion& aDirtyRegion, - const nsIntRegion& aIntDirtyRegion, + PaintType aType, bool aWillSendDidPaint) { #ifdef NS_FUNCTION_TIMER @@ -5268,7 +5267,6 @@ PresShell::Paint(nsIView* aViewToPaint, SAMPLE_LABEL("Paint", "PresShell::Paint"); NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell"); NS_ASSERTION(aViewToPaint, "null view"); - NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget"); nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint); @@ -5279,14 +5277,13 @@ PresShell::Paint(nsIView* aViewToPaint, bool isRetainingManager; LayerManager* layerManager = - aWidgetToPaint->GetLayerManager(&isRetainingManager); + aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager); NS_ASSERTION(layerManager, "Must be in paint event"); if (mIsFirstPaint) { layerManager->SetIsFirstPaint(); mIsFirstPaint = false; } - layerManager->BeginTransaction(); if (frame && isRetainingManager) { // Try to do an empty transaction, if the frame tree does not @@ -5295,21 +5292,39 @@ PresShell::Paint(nsIView* aViewToPaint, // draws the window title bar on Mac), because a) it won't work // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE, // that will cause us to forget to update the real layer manager! - if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { + if (aType == PaintType_Composite) { + if (layerManager->HasShadowManager()) { + return; + } + layerManager->BeginTransaction(); if (layerManager->EndEmptyTransaction()) { + return; + } + NS_WARNING("Must complete empty transaction when compositing!"); + } else if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { + layerManager->BeginTransaction(); + if (layerManager->EndEmptyTransaction(LayerManager::END_NO_COMPOSITE)) { frame->UpdatePaintCountForPaintedPresShells(); presContext->NotifyDidPaintForSubtree(); return; } + } else { + layerManager->BeginTransaction(); } frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE); + } else { + layerManager->BeginTransaction(); } if (frame) { frame->ClearPresShellsFromLastPaint(); } nscolor bgcolor = ComputeBackstopColor(aViewToPaint); + PRUint32 flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION; + if (aType == PaintType_NoComposite) { + flags |= nsLayoutUtils::PAINT_NO_COMPOSITE; + } if (frame) { // Defer invalidates that are triggered during painting, and discard @@ -5319,12 +5334,12 @@ PresShell::Paint(nsIView* aViewToPaint, frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion); // We can paint directly into the widget using its layer manager. - nsLayoutUtils::PaintFrame(nullptr, frame, aDirtyRegion, bgcolor, - nsLayoutUtils::PAINT_WIDGET_LAYERS | - nsLayoutUtils::PAINT_EXISTING_TRANSACTION); + nsLayoutUtils::PaintFrame(nullptr, frame, aDirtyRegion, bgcolor, flags); frame->EndDeferringInvalidatesForDisplayRoot(); - presContext->NotifyDidPaintForSubtree(); + if (aType != PaintType_Composite) { + presContext->NotifyDidPaintForSubtree(); + } return; } @@ -5338,9 +5353,13 @@ PresShell::Paint(nsIView* aViewToPaint, root->SetVisibleRegion(bounds); layerManager->SetRoot(root); } - layerManager->EndTransaction(NULL, NULL); + layerManager->EndTransaction(NULL, NULL, aType == PaintType_NoComposite ? + LayerManager::END_NO_COMPOSITE : + LayerManager::END_DEFAULT); - presContext->NotifyDidPaintForSubtree(); + if (aType != PaintType_Composite) { + presContext->NotifyDidPaintForSubtree(); + } } // static diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index d93007c74581..96c986495544 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -184,9 +184,8 @@ public: //nsIViewObserver interface - virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget, - const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion, - bool aWillSendDidPaint); + virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion, + PaintType aType, bool aWillSendDidPaint); virtual nsresult HandleEvent(nsIFrame* aFrame, nsGUIEvent* aEvent, bool aDontRetargetEvents, diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 738f05df126b..d4e043751069 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -414,8 +414,14 @@ nsRefreshDriver::Notify(nsITimer *aTimer) } if (mViewManagerFlushIsPending) { +#ifdef DEBUG_INVALIDATIONS + printf("Starting ProcessPendingUpdates\n"); +#endif mViewManagerFlushIsPending = false; mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates(); +#ifdef DEBUG_INVALIDATIONS + printf("Ending ProcessPendingUpdates\n"); +#endif } if (mThrottled || diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index fa4b7e148d10..166864141dce 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1683,18 +1683,19 @@ void nsGfxScrollFrameInner::ScrollToCSSPixels(nsIntPoint aScrollPosition) { nsPoint current = GetScrollPosition(); + nsIntPoint currentCSSPixels = GetScrollPositionCSSPixels(); nsPoint pt(nsPresContext::CSSPixelsToAppUnits(aScrollPosition.x), nsPresContext::CSSPixelsToAppUnits(aScrollPosition.y)); nscoord halfPixel = nsPresContext::CSSPixelsToAppUnits(0.5f); nsRect range(pt.x - halfPixel, pt.y - halfPixel, 2*halfPixel - 1, 2*halfPixel - 1); - if (nsPresContext::AppUnitsToIntCSSPixels(current.x) == aScrollPosition.x) { + if (currentCSSPixels.x == aScrollPosition.x) { pt.x = current.x; range.x = pt.x; range.width = 0; } else { // current.x must be outside 'range', so we must move in the correct direction. } - if (nsPresContext::AppUnitsToIntCSSPixels(current.y) == aScrollPosition.y) { + if (currentCSSPixels.y == aScrollPosition.y) { pt.y = current.y; range.y = pt.y; range.height = 0; @@ -1704,6 +1705,14 @@ nsGfxScrollFrameInner::ScrollToCSSPixels(nsIntPoint aScrollPosition) ScrollTo(pt, nsIScrollableFrame::INSTANT, &range); } +nsIntPoint +nsGfxScrollFrameInner::GetScrollPositionCSSPixels() +{ + nsPoint pt = GetScrollPosition(); + return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x), + nsPresContext::AppUnitsToIntCSSPixels(pt.y)); +} + /* * this method wraps calls to ScrollToImpl(), either in one shot or incrementally, * based on the setting of the smoothness scroll pref @@ -2547,15 +2556,62 @@ nsGfxScrollFrameInner::GetLineScrollAmount() const return nsSize(fontHeight, fontHeight); } +/** + * Compute the scrollport size excluding any fixed-pos headers and + * footers. A header or footer is an box that spans that entire width + * of the viewport and touches the top (or bottom, respectively) of the + * viewport. Headers and footers that cover more than a quarter of the + * the viewport are ignored since they probably aren't true headers and + * footers and we don't want to restrict scrolling too much in such cases. + * This is a bit conservative --- some pages use elements as headers or + * footers that don't span the entire width of the viewport --- but it + * should be a good start. + */ +static nsSize +GetScrollPortSizeExcludingHeadersAndFooters(nsIFrame* aViewportFrame, + const nsRect& aScrollPort) +{ + nsFrameList fixedFrames = aViewportFrame->GetChildList(nsIFrame::kFixedList); + nscoord headerBottom = 0; + nscoord footerTop = aScrollPort.height; + for (nsFrameList::Enumerator iterator(fixedFrames); !iterator.AtEnd(); + iterator.Next()) { + nsIFrame* f = iterator.get(); + nsRect r = f->GetRect().Intersect(aScrollPort); + if (r.x == 0 && r.width == aScrollPort.width && + r.height <= aScrollPort.height/3) { + if (r.y == 0) { + headerBottom = NS_MAX(headerBottom, r.height); + } + if (r.YMost() == aScrollPort.height) { + footerTop = NS_MIN(footerTop, r.y); + } + } + } + return nsSize(aScrollPort.width, footerTop - headerBottom); +} + nsSize nsGfxScrollFrameInner::GetPageScrollAmount() const { nsSize lineScrollAmount = GetLineScrollAmount(); + nsSize effectiveScrollPortSize; + if (mIsRoot) { + // Reduce effective scrollport height by the height of any fixed-pos + // headers or footers + nsIFrame* root = mOuter->PresContext()->PresShell()->GetRootFrame(); + effectiveScrollPortSize = + GetScrollPortSizeExcludingHeadersAndFooters(root, mScrollPort); + } else { + effectiveScrollPortSize = mScrollPort.Size(); + } // The page increment is the size of the page, minus the smaller of // 10% of the size or 2 lines. return nsSize( - mScrollPort.width - NS_MIN(mScrollPort.width/10, 2*lineScrollAmount.width), - mScrollPort.height - NS_MIN(mScrollPort.height/10, 2*lineScrollAmount.height)); + effectiveScrollPortSize.width - + NS_MIN(effectiveScrollPortSize.width/10, 2*lineScrollAmount.width), + effectiveScrollPortSize.height - + NS_MIN(effectiveScrollPortSize.height/10, 2*lineScrollAmount.height)); } /** diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 8552c90a4766..3c0ff345d1ec 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -166,6 +166,7 @@ public: ScrollToWithOrigin(aScrollPosition, aMode, nsGkAtoms::other, aRange); } void ScrollToCSSPixels(nsIntPoint aScrollPosition); + nsIntPoint GetScrollPositionCSSPixels(); void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange); void ScrollVisual(nsPoint aOldScrolledFramePosition); void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit, @@ -480,6 +481,9 @@ public: virtual void ScrollToCSSPixels(nsIntPoint aScrollPosition) { mInner.ScrollToCSSPixels(aScrollPosition); } + virtual nsIntPoint GetScrollPositionCSSPixels() { + return mInner.GetScrollPositionCSSPixels(); + } virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) { mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin); @@ -725,6 +729,9 @@ public: virtual void ScrollToCSSPixels(nsIntPoint aScrollPosition) { mInner.ScrollToCSSPixels(aScrollPosition); } + virtual nsIntPoint GetScrollPositionCSSPixels() { + return mInner.GetScrollPositionCSSPixels(); + } virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode, nsIntPoint* aOverflow, nsIAtom *aOrigin = nullptr) { mInner.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin); diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 51a564ca8b8f..5fd73a52f5df 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -138,6 +138,11 @@ public: * The scroll mode is INSTANT. */ virtual void ScrollToCSSPixels(nsIntPoint aScrollPosition) = 0; + /** + * Returns the scroll position in integer CSS pixels, rounded to the nearest + * pixel. + */ + virtual nsIntPoint GetScrollPositionCSSPixels() = 0; /** * When scrolling by a relative amount, we can choose various units. */ diff --git a/layout/generic/test/Makefile.in b/layout/generic/test/Makefile.in index f17a52efb395..fb820609fbe4 100644 --- a/layout/generic/test/Makefile.in +++ b/layout/generic/test/Makefile.in @@ -65,6 +65,8 @@ MOCHITEST_FILES = \ test_invalidate_during_plugin_paint.html \ test_movement_by_characters.html \ test_movement_by_words.html \ + test_page_scroll_with_fixed_pos.html \ + page_scroll_with_fixed_pos_window.html \ test_plugin_clipping.xhtml \ test_plugin_clipping2.xhtml \ test_plugin_clipping_transformed.xhtml \ diff --git a/layout/generic/test/page_scroll_with_fixed_pos_window.html b/layout/generic/test/page_scroll_with_fixed_pos_window.html new file mode 100644 index 000000000000..93d84fa8b7d2 --- /dev/null +++ b/layout/generic/test/page_scroll_with_fixed_pos_window.html @@ -0,0 +1,81 @@ + + + + Scrolling by pages with fixed-pos headers and footers + + + +
+
+
+

Something to click on to get focus +

+
+
+
+ + diff --git a/layout/generic/test/test_page_scroll_with_fixed_pos.html b/layout/generic/test/test_page_scroll_with_fixed_pos.html new file mode 100644 index 000000000000..309ae7f4e1e8 --- /dev/null +++ b/layout/generic/test/test_page_scroll_with_fixed_pos.html @@ -0,0 +1,16 @@ + + + + Scrolling by pages with fixed-pos headers and footers + + + + +

+ + + + diff --git a/layout/reftests/svg/smil/container/deferred-anim-1.xhtml b/layout/reftests/svg/smil/container/deferred-anim-1.xhtml index 362a99039d03..0df307526fe6 100644 --- a/layout/reftests/svg/smil/container/deferred-anim-1.xhtml +++ b/layout/reftests/svg/smil/container/deferred-anim-1.xhtml @@ -51,6 +51,7 @@ const svgns="http://www.w3.org/2000/svg"; var anim = document.createElementNS(svgns,'animate'); anim.setAttribute('attributeName','fill'); + anim.setAttribute('from', 'red'); anim.setAttribute('to','green'); anim.setAttribute('begin','0s'); anim.setAttribute('dur','0.001s'); diff --git a/layout/reftests/svg/smil/container/deferred-tree-1.xhtml b/layout/reftests/svg/smil/container/deferred-tree-1.xhtml index 6d671331ecaa..1b700f180a93 100644 --- a/layout/reftests/svg/smil/container/deferred-tree-1.xhtml +++ b/layout/reftests/svg/smil/container/deferred-tree-1.xhtml @@ -69,6 +69,7 @@ var anim = document.createElementNS(svgns, 'animate'); anim.setAttribute('attributeName', 'fill'); anim.setAttribute('begin', '0s'); + anim.setAttribute('from', 'red'); anim.setAttribute('to', 'green'); anim.setAttribute('dur', '0.001s'); anim.setAttribute('fill', 'freeze'); diff --git a/layout/reftests/svg/smil/motion/animateMotion-by-1.svg b/layout/reftests/svg/smil/motion/animateMotion-by-1.svg index 755cf4c1e5c2..fdb31efef607 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-by-1.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-by-1.svg @@ -4,7 +4,7 @@ @@ -17,25 +17,25 @@ - + - - + + - - + + - - + + diff --git a/layout/reftests/svg/smil/motion/animateMotion-from-to-1.svg b/layout/reftests/svg/smil/motion/animateMotion-from-to-1.svg index e8aeed8ee264..065ee36b126c 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-from-to-1.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-from-to-1.svg @@ -4,7 +4,7 @@ @@ -17,28 +17,28 @@ - + - + - + - + - + diff --git a/layout/reftests/svg/smil/motion/animateMotion-rotate-1a.svg b/layout/reftests/svg/smil/motion/animateMotion-rotate-1a.svg index 368ffbc50f92..414a6c718be4 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-rotate-1a.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-rotate-1a.svg @@ -11,7 +11,7 @@ @@ -25,7 +25,7 @@ + begin="101" dur="1"/> @@ -33,7 +33,7 @@ - @@ -44,7 +44,7 @@ + begin="101" dur="1"/> @@ -53,9 +53,9 @@ + begin="100.5" dur="1"/> + begin="100.5" dur="1"/> diff --git a/layout/reftests/svg/smil/motion/animateMotion-rotate-1b.svg b/layout/reftests/svg/smil/motion/animateMotion-rotate-1b.svg index 84e740491d36..8c4287d33ed3 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-rotate-1b.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-rotate-1b.svg @@ -11,7 +11,7 @@ @@ -25,7 +25,7 @@ + begin="101" dur="1"/> @@ -33,7 +33,7 @@ - @@ -44,7 +44,7 @@ + begin="101" dur="1"/> @@ -53,9 +53,9 @@ + begin="100.5" dur="1"/> + begin="100.5" dur="1"/> diff --git a/layout/reftests/svg/smil/motion/animateMotion-rotate-2.svg b/layout/reftests/svg/smil/motion/animateMotion-rotate-2.svg index 930493e2678a..7f6fcc7cf590 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-rotate-2.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-rotate-2.svg @@ -25,7 +25,7 @@ @@ -40,13 +40,13 @@ - + - + - + diff --git a/layout/reftests/svg/smil/motion/animateMotion-to-overridden-1.svg b/layout/reftests/svg/smil/motion/animateMotion-to-overridden-1.svg index cca246567c35..2c6179640ae7 100644 --- a/layout/reftests/svg/smil/motion/animateMotion-to-overridden-1.svg +++ b/layout/reftests/svg/smil/motion/animateMotion-to-overridden-1.svg @@ -4,7 +4,7 @@ @@ -21,30 +21,30 @@ - + - + - + - + - + - + @@ -52,10 +52,10 @@ - + - + diff --git a/layout/reftests/svg/smil/sort/sort-additive-1.svg b/layout/reftests/svg/smil/sort/sort-additive-1.svg index 53f452f00418..e60ff0a15f4b 100644 --- a/layout/reftests/svg/smil/sort/sort-additive-1.svg +++ b/layout/reftests/svg/smil/sort/sort-additive-1.svg @@ -10,7 +10,7 @@ var low = document.getElementById("low"); low.parentNode.insertBefore(low, low.parentNode.firstChild); - setTimeAndSnapshot(3.1, true); + setTimeAndSnapshot(103.1, true); } window.addEventListener("MozReftestInvalidate", swapAnimations, false); ]]> @@ -29,8 +29,8 @@ - - + + @@ -39,8 +39,8 @@ - - + @@ -51,9 +51,9 @@ - - + @@ -63,9 +63,9 @@ - - + + @@ -74,9 +74,8 @@ - - + @@ -85,8 +84,8 @@ - - + @@ -97,8 +96,8 @@ - - + @@ -109,9 +108,9 @@ - - + diff --git a/layout/reftests/text-overflow/single-value-ref.html b/layout/reftests/text-overflow/single-value-ref.html index 85a751741121..bb0954f252a3 100644 --- a/layout/reftests/text-overflow/single-value-ref.html +++ b/layout/reftests/text-overflow/single-value-ref.html @@ -58,9 +58,10 @@ function scrolldivs() { } document.documentElement.removeAttribute('class'); } +window.addEventListener("MozReftestInvalidate", scrolldivs, false); - +
A long line that does not break (overflow:auto)
diff --git a/layout/reftests/text-overflow/single-value.html b/layout/reftests/text-overflow/single-value.html index d2e35baccb52..d6f765303a01 100644 --- a/layout/reftests/text-overflow/single-value.html +++ b/layout/reftests/text-overflow/single-value.html @@ -51,9 +51,10 @@ function scrolldivs() { } document.documentElement.removeAttribute('class'); } +window.addEventListener("MozReftestInvalidate", scrolldivs, false); - +
A long line that does not break (overflow:auto)
diff --git a/layout/reftests/transform/dynamic-addremove-1-ref.html b/layout/reftests/transform/dynamic-addremove-1-ref.html new file mode 100644 index 000000000000..271b1a64700e --- /dev/null +++ b/layout/reftests/transform/dynamic-addremove-1-ref.html @@ -0,0 +1,8 @@ + + + +
+
+
+ + diff --git a/layout/reftests/transform/dynamic-addremove-1a.html b/layout/reftests/transform/dynamic-addremove-1a.html new file mode 100644 index 000000000000..358cd938be7e --- /dev/null +++ b/layout/reftests/transform/dynamic-addremove-1a.html @@ -0,0 +1,15 @@ + + + +
+
+
+ + + diff --git a/layout/reftests/transform/dynamic-addremove-1b.html b/layout/reftests/transform/dynamic-addremove-1b.html new file mode 100644 index 000000000000..0ce3547c1b88 --- /dev/null +++ b/layout/reftests/transform/dynamic-addremove-1b.html @@ -0,0 +1,15 @@ + + + +
+
+
+ + + diff --git a/layout/reftests/transform/dynamic-addremove-1c.html b/layout/reftests/transform/dynamic-addremove-1c.html new file mode 100644 index 000000000000..c535969142eb --- /dev/null +++ b/layout/reftests/transform/dynamic-addremove-1c.html @@ -0,0 +1,17 @@ + + + +
+
+
+
+
+ + + diff --git a/layout/reftests/transform/reftest.list b/layout/reftests/transform/reftest.list index fa4e7882e2c1..f18842fcdd4e 100644 --- a/layout/reftests/transform/reftest.list +++ b/layout/reftests/transform/reftest.list @@ -6,6 +6,9 @@ == compound-1a.html compound-1-ref.html != compound-1a.html compound-1-fail.html == dynamic-inherit-1.html dynamic-inherit-1-ref.html +== dynamic-addremove-1a.html dynamic-addremove-1-ref.html +== dynamic-addremove-1b.html dynamic-addremove-1-ref.html +== dynamic-addremove-1c.html dynamic-addremove-1-ref.html # translatex should act like position: relative == translatex-1a.html translatex-1-ref.html == translatex-1b.html translatex-1-ref.html diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 0256499ab391..d2a835befe5d 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -415,7 +415,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther) // Visibility, Outline, TableBorder, Table, Text, UIReset, Quotes nsChangeHint maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE | nsChangeHint_UpdateTransformLayer | nsChangeHint_UpdateOpacityLayer | - nsChangeHint_UpdateOverflow); + nsChangeHint_UpdateOverflow | nsChangeHint_AddOrRemoveTransform); DO_STRUCT_DIFFERENCE(Display); maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE | diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 4eb05b2bd773..fb95803e9876 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2276,7 +2276,12 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const * or remove the view object, and also to handle abs-pos and fixed-pos containers. */ if (HasTransform() != aOther.HasTransform()) { - NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); + // We do not need to apply nsChangeHint_UpdateTransformLayer since + // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and + // ensure layers are rebuilt (or removed). + NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AddOrRemoveTransform, + NS_CombineHint(nsChangeHint_UpdateOverflow, + nsChangeHint_RepaintFrame))); } else if (HasTransform()) { /* Otherwise, if we've kept the property lying around and we already had a @@ -2339,7 +2344,8 @@ nsChangeHint nsStyleDisplay::MaxDifference() return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE | nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer | - nsChangeHint_UpdateOverflow); + nsChangeHint_UpdateOverflow | + nsChangeHint_AddOrRemoveTransform); } #endif diff --git a/layout/xul/base/src/nsScrollBoxObject.cpp b/layout/xul/base/src/nsScrollBoxObject.cpp index ad503afbee2e..620b0ab26abf 100644 --- a/layout/xul/base/src/nsScrollBoxObject.cpp +++ b/layout/xul/base/src/nsScrollBoxObject.cpp @@ -263,9 +263,9 @@ NS_IMETHODIMP nsScrollBoxObject::GetPosition(PRInt32 *x, PRInt32 *y) if (!sf) return NS_ERROR_FAILURE; - nsPoint pt = sf->GetScrollPosition(); - *x = nsPresContext::AppUnitsToIntCSSPixels(pt.x); - *y = nsPresContext::AppUnitsToIntCSSPixels(pt.y); + nsIntPoint pt = sf->GetScrollPositionCSSPixels(); + *x = pt.x; + *y = pt.y; return NS_OK; } diff --git a/security/build/Makefile.in b/security/build/Makefile.in new file mode 100644 index 000000000000..dcb84007bf70 --- /dev/null +++ b/security/build/Makefile.in @@ -0,0 +1,343 @@ +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DEPTH = @DEPTH@ +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk +CC_WRAPPER = +CXX_WRAPPER = +include $(topsrcdir)/config/config.mk + +ifndef MOZ_NATIVE_NSS +LOADABLE_ROOT_MODULE = $(DLL_PREFIX)nssckbi$(DLL_SUFFIX) +endif + +NSS3_LIB = $(DLL_PREFIX)nss3$(DLL_SUFFIX) +NSSUTIL3_LIB = $(DLL_PREFIX)nssutil3$(DLL_SUFFIX) +SMIME3_LIB = $(DLL_PREFIX)smime3$(DLL_SUFFIX) +SSL3_LIB = $(DLL_PREFIX)ssl3$(DLL_SUFFIX) +SOFTOKEN3_LIB = $(DLL_PREFIX)softokn3$(DLL_SUFFIX) + +ifndef NSS_DISABLE_DBM +NSSDBM3_LIB = $(DLL_PREFIX)nssdbm3$(DLL_SUFFIX) +else +NSSDBM3_LIB = +endif + +ifndef MOZ_NATIVE_NSS +ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) +SDK_LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)smime3.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)ssl3.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nss3.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \ + $(NULL) +else +SDK_LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \ + $(NULL) +endif +endif + +# Default +HAVE_FREEBL_LIBS = 1 + +# 32-bit HP-UX PA-RISC +ifeq ($(OS_ARCH), HP-UX) +ifneq ($(OS_TEST), ia64) +ifndef HAVE_64BIT_OS +HAVE_FREEBL_LIBS = +HAVE_FREEBL_LIBS_32 = 1 +endif +endif +endif + +# SunOS SPARC +ifeq ($(OS_ARCH), SunOS) +ifneq (86,$(findstring 86,$(OS_TEST))) +ifdef HAVE_64BIT_OS +HAVE_FREEBL_LIBS = +HAVE_FREEBL_LIBS_64 = 1 +else +HAVE_FREEBL_LIBS = +HAVE_FREEBL_LIBS_32 = 1 +HAVE_FREEBL_LIBS_32INT64 = 1 +endif +endif +endif + +ifdef HAVE_FREEBL_LIBS +FREEBL_LIB = $(DLL_PREFIX)freebl3$(DLL_SUFFIX) +endif +ifdef HAVE_FREEBL_LIBS_32 +FREEBL_32INT_LIB = libfreebl_32int_3$(DLL_SUFFIX) +FREEBL_32FPU_LIB = libfreebl_32fpu_3$(DLL_SUFFIX) +endif +ifdef HAVE_FREEBL_LIBS_32INT64 +FREEBL_32INT64_LIB = libfreebl_32int64_3$(DLL_SUFFIX) +endif +ifdef HAVE_FREEBL_LIBS_64 +FREEBL_64INT_LIB = libfreebl_64int_3$(DLL_SUFFIX) +FREEBL_64FPU_LIB = libfreebl_64fpu_3$(DLL_SUFFIX) +endif + +ABS_DIST := $(call core_abspath,$(DIST)) +ifeq ($(HOST_OS_ARCH),WINNT) +ifdef CYGDRIVE_MOUNT +ABS_DIST := $(shell cygpath -w $(ABS_DIST) | sed -e 's|\\|/|g') +endif +ifneq (,$(filter mingw%,$(host_os))) +ABS_DIST := $(shell cd $(DIST) && pwd -W) +endif +endif +# For all variables such as DLLFLAGS, that may contain $(DIST) +DIST := $(ABS_DIST) +NSPR_INCLUDE_DIR = $(firstword $(filter -I%,$(NSPR_CFLAGS))) +ifneq (,$(strip $(NSPR_INCLUDE_DIR))) +NSPR_INCLUDE_DIR := $(subst -I,,$(subst -I$(DIST),-I$(ABS_DIST),$(NSPR_INCLUDE_DIR))) +else +NSPR_INCLUDE_DIR = $(ABS_DIST)/include/nspr +endif +NSPR_LIB_DIR = $(firstword $(filter -L%,$(NSPR_LIBS))) +ifneq (,$(strip $(NSPR_LIB_DIR))) +NSPR_LIB_DIR := $(subst -L,,$(subst -L$(DIST),-L$(ABS_DIST),$(NSPR_LIB_DIR))) +else +NSPR_LIB_DIR = $(ABS_DIST)/lib +endif +# Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides +# definitions in NSS, so just export it into the sub-make's environment. +ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY)) +export DLLFLAGS +endif + +# To get debug symbols from NSS +export MOZ_DEBUG_SYMBOLS + +ifdef .PYMAKE +NSSMAKE = $(GMAKE) +else +NSSMAKE = $(MAKE) +endif + +# NSS makefiles are not safe for parallel execution. +DEFAULT_GMAKE_FLAGS = MAKE="$(NSSMAKE) -j1" -j1 +DEFAULT_GMAKE_FLAGS += CC="$(CC)" +DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST) +DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR) +DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST) +DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR) +DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR) +DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1 +DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1 +DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1 +DEFAULT_GMAKE_FLAGS += NSINSTALL="$(NSINSTALL)" +ifndef MOZ_NATIVE_SQLITE +DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3 +DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include +endif +ifdef NSS_DISABLE_DBM +DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1 +endif +ABS_topsrcdir := $(call core_abspath,$(topsrcdir)) +# Hack to force NSS build system to use "normal" object directories +DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $(shell cd $(topsrcdir); pwd)/security/,,$$(CURDIR))' +DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)' +DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST) +ifndef MOZ_DEBUG +DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1 +endif +ifdef GNU_CC +DEFAULT_GMAKE_FLAGS += NS_USE_GCC=1 +else +DEFAULT_GMAKE_FLAGS += NS_USE_GCC= +endif +ifdef USE_N32 +# It is not really necessary to specify USE_PTHREADS=1. USE_PTHREADS +# merely adds _PTH to coreconf's OBJDIR name. +DEFAULT_GMAKE_FLAGS += USE_N32=1 USE_PTHREADS=1 +endif +ifdef HAVE_64BIT_OS +DEFAULT_GMAKE_FLAGS += USE_64=1 +endif +ifeq ($(OS_ARCH),WINNT) +DEFAULT_GMAKE_FLAGS += OS_TARGET=WIN95 +ifdef MOZ_DEBUG +ifndef MOZ_NO_DEBUG_RTL +DEFAULT_GMAKE_FLAGS += USE_DEBUG_RTL=1 +endif +endif +endif # WINNT +ifeq ($(OS_ARCH),OS2) +ifdef MOZ_OS2_HIGH_MEMORY +DEFAULT_GMAKE_FLAGS += MOZ_OS2_HIGH_MEMORY=1 +endif +endif # OS2 +ifeq ($(OS_ARCH),Darwin) +# Make nsinstall use absolute symlinks by default when building NSS +# for Mozilla on Mac OS X. (Bugzilla bug 193164) +ifndef NSDISTMODE +DEFAULT_GMAKE_FLAGS += NSDISTMODE=absolute_symlink +endif +ifdef MACOS_SDK_DIR +DEFAULT_GMAKE_FLAGS += MACOS_SDK_DIR=$(MACOS_SDK_DIR) +endif +endif + +# Turn off TLS compression support because it requires system zlib. +# See bug 580679 comment 18. +DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ZLIB= + +# Disable building of the test programs in security/nss/lib/zlib +DEFAULT_GMAKE_FLAGS += PROGRAMS= + +# Disable creating .chk files. They will be generated from packager.mk +# When bug 681624 lands, we can replace CHECKLOC= with SKIP_SHLIBSIGN=1 +DEFAULT_GMAKE_FLAGS += CHECKLOC= + +ifdef CROSS_COMPILE + +DEFAULT_GMAKE_FLAGS += \ + NATIVE_CC="$(HOST_CC)" \ + CC="$(CC)" \ + CCC="$(CXX)" \ + LINK="$(LD)" \ + AS="$(AS)" \ + AR='$(AR) $(AR_FLAGS:$@=$$@)' \ + RANLIB="$(RANLIB)" \ + RC="$(RC) $(RCFLAGS)" \ + OS_ARCH="$(OS_ARCH)" \ + OS_TEST="$(OS_TEST)" \ + CPU_ARCH="$(TARGET_CPU)" \ + $(NULL) + +# Android has pthreads integrated into -lc, so OS_PTHREAD is set to nothing +ifeq ($(OS_TARGET), Android) +DEFAULT_GMAKE_FLAGS += \ + OS_RELEASE="2.6" \ + OS_PTHREAD= \ + STANDARDS_CFLAGS="-std=gnu89" \ + $(NULL) + +DEFAULT_GMAKE_FLAGS += ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -include $(ABS_topsrcdir)/security/manager/android_stub.h" +endif +endif + +ifdef WRAP_LDFLAGS +DEFAULT_GMAKE_FLAGS += \ + LDFLAGS="$(LDFLAGS) $(WRAP_LDFLAGS)" \ + DSO_LDOPTS="$(DSO_LDOPTS) $(LDFLAGS) $(WRAP_LDFLAGS)" \ + $(NULL) +endif + +DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 +ifeq ($(OS_TARGET),Linux) +DEFAULT_GMAKE_FLAGS += FREEBL_LOWHASH=1 +endif + +ifdef MOZ_NO_WLZDEFS +DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG= +endif +ifdef MOZ_CFLAGS_NSS +DEFAULT_GMAKE_FLAGS += XCFLAGS="$(CFLAGS)" +DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS="-compatibility_version 1 -current_version 1 $(LDFLAGS)" +endif + +ifdef MOZ_NSS_PATCH +# If we're applying a patch, we'll copy the NSS source to the objdir +# and build it from there. +NSS_SRCDIR = $(CURDIR)/nss + +# This will copy and patch the NSS source for every build. +# Since we "cp -p", it won't force rebuilds for most files, just +# for patched files, but that's easier than trying to track +# dependencies for patched files. +export:: + rm -rf $(NSS_SRCDIR) + $(NSINSTALL) -D $(NSS_SRCDIR)/security + cp -Rp $(topsrcdir)/security/nss $(NSS_SRCDIR)/security + cp -Rp $(topsrcdir)/security/coreconf $(NSS_SRCDIR)/security + cp -Rp $(topsrcdir)/security/dbm $(NSS_SRCDIR)/security + cp -Rp $(topsrcdir)/dbm $(NSS_SRCDIR) + (cd $(NSS_SRCDIR) && patch -p1 < $(call core_abspath,$(MOZ_NSS_PATCH))) +else +NSS_SRCDIR = $(topsrcdir) +endif + +NSS_DIRS = +ifndef NSS_DISABLE_DBM +NSS_DIRS += dbm +endif +NSS_DIRS += \ + nss/lib \ + nss/cmd/lib \ + nss/cmd/shlibsign \ + $(NULL) + +ifdef ENABLE_TESTS +NSS_DIRS += \ + nss/cmd/certutil \ + nss/cmd/pk12util \ + nss/cmd/modutil \ + $(NULL) +endif + +ifndef MOZ_NATIVE_NSS +define build_rules +libs:: + $$(NSSMAKE) -C $$(NSS_SRCDIR)/security/$(1) $$(DEFAULT_GMAKE_FLAGS) + +clean clobber clobber_all realclean distclean depend:: + $$(NSSMAKE) -C $$(NSS_SRCDIR)/security/$(1) $$(DEFAULT_GMAKE_FLAGS) clean +endef +$(foreach dir,$(NSS_DIRS),$(eval $(call build_rules,$(dir)))) + +NSS_LIBS = \ + $(LOADABLE_ROOT_MODULE) \ + $(SOFTOKEN3_LIB) \ + $(NSSDBM3_LIB) \ + $(NSS3_LIB) \ + $(NSSUTIL3_LIB) \ + $(SSL3_LIB) \ + $(SMIME3_LIB) \ + $(FREEBL_LIB) \ + $(FREEBL_32INT_LIB) \ + $(FREEBL_32FPU_LIB) \ + $(FREEBL_32INT64_LIB) \ + $(FREEBL_64INT_LIB) \ + $(FREEBL_64FPU_LIB) \ + $(NULL) + +define install_rules +libs:: +ifeq ($(OS_ARCH)_$(1), SunOS_$(SOFTOKEN3_LIB)) +# has to use copy mode on Solaris, see #665509 + $$(NSINSTALL) -t -m 755 $$(DIST)/lib/$(1) $$(DIST)/bin +else + $$(INSTALL) -m 755 $$(DIST)/lib/$(1) $$(DIST)/bin +endif + +install:: + $$(SYSINSTALL) -m 755 $$(DIST)/lib/$(1) $$(DESTDIR)$$(mozappdir) +endef +$(foreach lib,$(NSS_LIBS),$(eval $(call install_rules,$(lib)))) + +libs:: + $(INSTALL) -m 755 $(SDK_LIBS) $(DIST)/sdk/lib +# NSS installs headers to dist/public and we want them in dist/include + $(NSINSTALL) -D $(DIST)/include/nss + (cd $(DIST)/public/nss && tar $(TAR_CREATE_FLAGS) - .) | \ + (cd $(DIST)/include && tar -xf -) + +endif # MOZ_NATIVE_NSS + +include $(topsrcdir)/config/rules.mk diff --git a/security/manager/Makefile.in b/security/manager/Makefile.in index c3ceb187926c..cbd85bfc4d50 100644 --- a/security/manager/Makefile.in +++ b/security/manager/Makefile.in @@ -9,338 +9,6 @@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -CC_WRAPPER = -CXX_WRAPPER = -include $(topsrcdir)/config/config.mk - -MODULE = psm - -ifndef MOZ_NATIVE_NSS -LOADABLE_ROOT_MODULE = $(DLL_PREFIX)nssckbi$(DLL_SUFFIX) -endif - -NSS3_LIB = $(DLL_PREFIX)nss3$(DLL_SUFFIX) -NSSUTIL3_LIB = $(DLL_PREFIX)nssutil3$(DLL_SUFFIX) -SMIME3_LIB = $(DLL_PREFIX)smime3$(DLL_SUFFIX) -SSL3_LIB = $(DLL_PREFIX)ssl3$(DLL_SUFFIX) -SOFTOKEN3_LIB = $(DLL_PREFIX)softokn3$(DLL_SUFFIX) - -ifndef NSS_DISABLE_DBM -NSSDBM3_LIB = $(DLL_PREFIX)nssdbm3$(DLL_SUFFIX) -else -NSSDBM3_LIB = -endif - -ifndef MOZ_NATIVE_NSS -ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) -SDK_LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)smime3.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)ssl3.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nss3.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \ - $(NULL) -else -SDK_LIBS = \ - $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)smime.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)ssl.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nss.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)nssutil.$(LIB_SUFFIX) \ - $(NULL) -endif -endif - -# Default -HAVE_FREEBL_LIBS = 1 - -# 32-bit HP-UX PA-RISC -ifeq ($(OS_ARCH), HP-UX) -ifneq ($(OS_TEST), ia64) -ifndef HAVE_64BIT_OS -HAVE_FREEBL_LIBS = -HAVE_FREEBL_LIBS_32 = 1 -endif -endif -endif - -# SunOS SPARC -ifeq ($(OS_ARCH), SunOS) -ifneq (86,$(findstring 86,$(OS_TEST))) -ifdef HAVE_64BIT_OS -HAVE_FREEBL_LIBS = -HAVE_FREEBL_LIBS_64 = 1 -else -HAVE_FREEBL_LIBS = -HAVE_FREEBL_LIBS_32 = 1 -HAVE_FREEBL_LIBS_32INT64 = 1 -endif -endif -endif - -ifdef HAVE_FREEBL_LIBS -FREEBL_LIB = $(DLL_PREFIX)freebl3$(DLL_SUFFIX) -endif -ifdef HAVE_FREEBL_LIBS_32 -FREEBL_32INT_LIB = libfreebl_32int_3$(DLL_SUFFIX) -FREEBL_32FPU_LIB = libfreebl_32fpu_3$(DLL_SUFFIX) -endif -ifdef HAVE_FREEBL_LIBS_32INT64 -FREEBL_32INT64_LIB = libfreebl_32int64_3$(DLL_SUFFIX) -endif -ifdef HAVE_FREEBL_LIBS_64 -FREEBL_64INT_LIB = libfreebl_64int_3$(DLL_SUFFIX) -FREEBL_64FPU_LIB = libfreebl_64fpu_3$(DLL_SUFFIX) -endif - -ABS_DIST := $(call core_abspath,$(DIST)) -ifeq ($(HOST_OS_ARCH),WINNT) -ifdef CYGDRIVE_MOUNT -ABS_DIST := $(shell cygpath -w $(ABS_DIST) | sed -e 's|\\|/|g') -endif -ifneq (,$(filter mingw%,$(host_os))) -ABS_DIST := $(shell cd $(DIST) && pwd -W) -endif -endif -# For all variables such as DLLFLAGS, that may contain $(DIST) -DIST := $(ABS_DIST) -NSPR_INCLUDE_DIR = $(firstword $(filter -I%,$(NSPR_CFLAGS))) -ifneq (,$(strip $(NSPR_INCLUDE_DIR))) -NSPR_INCLUDE_DIR := $(subst -I,,$(subst -I$(DIST),-I$(ABS_DIST),$(NSPR_INCLUDE_DIR))) -else -NSPR_INCLUDE_DIR = $(ABS_DIST)/include/nspr -endif -NSPR_LIB_DIR = $(firstword $(filter -L%,$(NSPR_LIBS))) -ifneq (,$(strip $(NSPR_LIB_DIR))) -NSPR_LIB_DIR := $(subst -L,,$(subst -L$(DIST),-L$(ABS_DIST),$(NSPR_LIB_DIR))) -else -NSPR_LIB_DIR = $(ABS_DIST)/lib -endif -# Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides -# definitions in NSS, so just export it into the sub-make's environment. -ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY)) -export DLLFLAGS -endif - -# To get debug symbols from NSS -export MOZ_DEBUG_SYMBOLS - -ifdef .PYMAKE -NSSMAKE = $(GMAKE) -else -NSSMAKE = $(MAKE) -endif - -# NSS makefiles are not safe for parallel execution. -DEFAULT_GMAKE_FLAGS = MAKE="$(NSSMAKE) -j1" -j1 -DEFAULT_GMAKE_FLAGS += CC="$(CC)" -DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST) -DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR) -DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST) -DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR) -DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR) -DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1 -DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1 -DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1 -DEFAULT_GMAKE_FLAGS += NSINSTALL="$(NSINSTALL)" -ifndef MOZ_NATIVE_SQLITE -DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3 -DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include -endif -ifdef NSS_DISABLE_DBM -DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1 -endif -ABS_topsrcdir := $(call core_abspath,$(topsrcdir)) -# Hack to force NSS build system to use "normal" object directories -DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $(shell cd $(topsrcdir); pwd)/security/,,$$(CURDIR))' -DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)' -DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST) -ifndef MOZ_DEBUG -DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1 -endif -ifdef GNU_CC -DEFAULT_GMAKE_FLAGS += NS_USE_GCC=1 -else -DEFAULT_GMAKE_FLAGS += NS_USE_GCC= -endif -ifdef USE_N32 -# It is not really necessary to specify USE_PTHREADS=1. USE_PTHREADS -# merely adds _PTH to coreconf's OBJDIR name. -DEFAULT_GMAKE_FLAGS += USE_N32=1 USE_PTHREADS=1 -endif -ifdef HAVE_64BIT_OS -DEFAULT_GMAKE_FLAGS += USE_64=1 -endif -ifeq ($(OS_ARCH),WINNT) -DEFAULT_GMAKE_FLAGS += OS_TARGET=WIN95 -ifdef MOZ_DEBUG -ifndef MOZ_NO_DEBUG_RTL -DEFAULT_GMAKE_FLAGS += USE_DEBUG_RTL=1 -endif -endif -endif # WINNT -ifeq ($(OS_ARCH),OS2) -ifdef MOZ_OS2_HIGH_MEMORY -DEFAULT_GMAKE_FLAGS += MOZ_OS2_HIGH_MEMORY=1 -endif -endif # OS2 -ifeq ($(OS_ARCH),Darwin) -# Make nsinstall use absolute symlinks by default when building NSS -# for Mozilla on Mac OS X. (Bugzilla bug 193164) -ifndef NSDISTMODE -DEFAULT_GMAKE_FLAGS += NSDISTMODE=absolute_symlink -endif -ifdef MACOS_SDK_DIR -DEFAULT_GMAKE_FLAGS += MACOS_SDK_DIR=$(MACOS_SDK_DIR) -endif -endif - -# Turn off TLS compression support because it requires system zlib. -# See bug 580679 comment 18. -DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ZLIB= - -# Disable building of the test programs in security/nss/lib/zlib -DEFAULT_GMAKE_FLAGS += PROGRAMS= - -# Disable creating .chk files. They will be generated from packager.mk -# When bug 681624 lands, we can replace CHECKLOC= with SKIP_SHLIBSIGN=1 -DEFAULT_GMAKE_FLAGS += CHECKLOC= - -ifdef CROSS_COMPILE - -DEFAULT_GMAKE_FLAGS += \ - NATIVE_CC="$(HOST_CC)" \ - CC="$(CC)" \ - CCC="$(CXX)" \ - LINK="$(LD)" \ - AS="$(AS)" \ - AR='$(AR) $(AR_FLAGS:$@=$$@)' \ - RANLIB="$(RANLIB)" \ - RC="$(RC) $(RCFLAGS)" \ - OS_ARCH="$(OS_ARCH)" \ - OS_TEST="$(OS_TEST)" \ - CPU_ARCH="$(TARGET_CPU)" \ - $(NULL) - -# Android has pthreads integrated into -lc, so OS_PTHREAD is set to nothing -ifeq ($(OS_TARGET), Android) -DEFAULT_GMAKE_FLAGS += \ - OS_RELEASE="2.6" \ - OS_PTHREAD= \ - STANDARDS_CFLAGS="-std=gnu89" \ - $(NULL) - -DEFAULT_GMAKE_FLAGS += ARCHFLAG="$(CFLAGS) -DCHECK_FORK_GETPID -DRTLD_NOLOAD=0 -include $(ABS_topsrcdir)/security/manager/android_stub.h" -endif -endif - -ifdef WRAP_LDFLAGS -DEFAULT_GMAKE_FLAGS += \ - LDFLAGS="$(LDFLAGS) $(WRAP_LDFLAGS)" \ - DSO_LDOPTS="$(DSO_LDOPTS) $(LDFLAGS) $(WRAP_LDFLAGS)" \ - $(NULL) -endif - -DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 -ifeq ($(OS_TARGET),Linux) -DEFAULT_GMAKE_FLAGS += FREEBL_LOWHASH=1 -endif - -ifdef MOZ_NO_WLZDEFS -DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG= -endif -ifdef MOZ_CFLAGS_NSS -DEFAULT_GMAKE_FLAGS += XCFLAGS="$(CFLAGS)" -DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS="-compatibility_version 1 -current_version 1 $(LDFLAGS)" -endif - -ifdef MOZ_NSS_PATCH -# If we're applying a patch, we'll copy the NSS source to the objdir -# and build it from there. -NSS_SRCDIR = $(CURDIR)/nss - -# This will copy and patch the NSS source for every build. -# Since we "cp -p", it won't force rebuilds for most files, just -# for patched files, but that's easier than trying to track -# dependencies for patched files. -export:: - rm -rf $(NSS_SRCDIR) - $(NSINSTALL) -D $(NSS_SRCDIR)/security - cp -Rp $(topsrcdir)/security/nss $(NSS_SRCDIR)/security - cp -Rp $(topsrcdir)/security/coreconf $(NSS_SRCDIR)/security - cp -Rp $(topsrcdir)/security/dbm $(NSS_SRCDIR)/security - cp -Rp $(topsrcdir)/dbm $(NSS_SRCDIR) - (cd $(NSS_SRCDIR) && patch -p1 < $(call core_abspath,$(MOZ_NSS_PATCH))) -else -NSS_SRCDIR = $(topsrcdir) -endif - -NSS_DIRS = -ifndef NSS_DISABLE_DBM -NSS_DIRS += dbm -endif -NSS_DIRS += \ - nss/lib \ - nss/cmd/lib \ - nss/cmd/shlibsign \ - $(NULL) - -ifdef ENABLE_TESTS -NSS_DIRS += \ - nss/cmd/certutil \ - nss/cmd/pk12util \ - nss/cmd/modutil \ - $(NULL) -endif - -ifndef MOZ_NATIVE_NSS -define build_rules -libs:: - $$(NSSMAKE) -C $$(NSS_SRCDIR)/security/$(1) $$(DEFAULT_GMAKE_FLAGS) - -clean clobber clobber_all realclean distclean depend:: - $$(NSSMAKE) -C $$(NSS_SRCDIR)/security/$(1) $$(DEFAULT_GMAKE_FLAGS) clean -endef -$(foreach dir,$(NSS_DIRS),$(eval $(call build_rules,$(dir)))) - -NSS_LIBS = \ - $(LOADABLE_ROOT_MODULE) \ - $(SOFTOKEN3_LIB) \ - $(NSSDBM3_LIB) \ - $(NSS3_LIB) \ - $(NSSUTIL3_LIB) \ - $(SSL3_LIB) \ - $(SMIME3_LIB) \ - $(FREEBL_LIB) \ - $(FREEBL_32INT_LIB) \ - $(FREEBL_32FPU_LIB) \ - $(FREEBL_32INT64_LIB) \ - $(FREEBL_64INT_LIB) \ - $(FREEBL_64FPU_LIB) \ - $(NULL) - -define install_rules -libs:: -ifeq ($(OS_ARCH)_$(1), SunOS_$(SOFTOKEN3_LIB)) -# has to use copy mode on Solaris, see #665509 - $$(NSINSTALL) -t -m 755 $$(DIST)/lib/$(1) $$(DIST)/bin -else - $$(INSTALL) -m 755 $$(DIST)/lib/$(1) $$(DIST)/bin -endif - -install:: - $$(SYSINSTALL) -m 755 $$(DIST)/lib/$(1) $$(DESTDIR)$$(mozappdir) -endef -$(foreach lib,$(NSS_LIBS),$(eval $(call install_rules,$(lib)))) - -libs:: - $(INSTALL) -m 755 $(SDK_LIBS) $(DIST)/sdk/lib -# NSS installs headers to dist/public and we want them in dist/include - $(NSINSTALL) -D $(DIST)/include/nss - (cd $(DIST)/public/nss && tar $(TAR_CREATE_FLAGS) - .) | \ - (cd $(DIST)/include && tar -xf -) - -endif # MOZ_NATIVE_NSS DIRS = \ boot \ diff --git a/testing/mochitest/android.json b/testing/mochitest/android.json index e7fc02b9bdb7..757cc54b6556 100644 --- a/testing/mochitest/android.json +++ b/testing/mochitest/android.json @@ -141,6 +141,7 @@ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html": "bug 775227", "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227", "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227", + "dom/imptests/webapps/DOMCore/tests/submissions": "bug 782254", "dom/imptests/webapps/WebStorage/tests/submissions": "bug 781837 & bug 775227", "dom/indexedDB/test/test_third_party.html": "TIMED_OUT", "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855", diff --git a/toolkit/content/tests/chrome/test_bug624329.xul b/toolkit/content/tests/chrome/test_bug624329.xul index 03e33002331f..db2428712885 100644 --- a/toolkit/content/tests/chrome/test_bug624329.xul +++ b/toolkit/content/tests/chrome/test_bug624329.xul @@ -55,16 +55,15 @@ function childFocused() { function childResized() { const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1; - if (isOSXLion) { - todo_is(win.windowState, win.STATE_MAXIMIZED, - "A resize before being maximized breaks this test on 10.7"); - finish(); - return; - } is(win.windowState, win.STATE_MAXIMIZED, "window should be maximized"); + if (isOSXLion) { + finish(); + return; + } + isnot(win.innerWidth, 300, "window inner width should have changed"); diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh index 08733882fe80..95695f9ce337 100644 --- a/toolkit/toolkit-makefiles.sh +++ b/toolkit/toolkit-makefiles.sh @@ -1531,6 +1531,7 @@ fi if [ "$MOZ_PSM" ]; then add_makefiles " + security/build/Makefile security/manager/Makefile security/manager/boot/Makefile security/manager/boot/src/Makefile diff --git a/toolkit/toolkit-tiers.mk b/toolkit/toolkit-tiers.mk index f21b9e571d33..c252b601f0ff 100644 --- a/toolkit/toolkit-tiers.mk +++ b/toolkit/toolkit-tiers.mk @@ -125,6 +125,12 @@ tier_platform_dirs += \ $(NULL) endif +ifdef MOZ_PSM +tier_platform_dirs += \ + security/build \ + $(NULL) +endif + ifdef MOZ_WEBRTC tier_platform_dirs += \ media/webrtc \ diff --git a/view/src/Makefile.in b/view/src/Makefile.in index 98bc3e87d164..078766fe883f 100644 --- a/view/src/Makefile.in +++ b/view/src/Makefile.in @@ -17,6 +17,8 @@ MODULE_NAME = nsViewModule GRE_MODULE = 1 LIBXUL_LIBRARY = 1 +DEFINES += -D_IMPL_NS_LAYOUT + CPPSRCS = \ nsView.cpp \ nsViewManager.cpp \ diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index a3de1b6b71df..8858e9a14d90 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -23,6 +23,8 @@ #include "nsEventStateManager.h" #include "mozilla/StartupTimeline.h" #include "sampler.h" +#include "nsRefreshDriver.h" +#include "mozilla/Preferences.h" /** XXX TODO XXX @@ -44,6 +46,22 @@ #undef DEBUG_MOUSE_LOCATION +static bool +IsRefreshDriverPaintingEnabled() +{ + static bool sRefreshDriverPaintingEnabled; + static bool sRefreshDriverPaintingPrefCached = false; + + if (!sRefreshDriverPaintingPrefCached) { + sRefreshDriverPaintingPrefCached = true; + mozilla::Preferences::AddBoolVarCache(&sRefreshDriverPaintingEnabled, + "viewmanager.refresh-driver-painting.enabled", + true); + } + + return sRefreshDriverPaintingEnabled; +} + PRInt32 nsViewManager::mVMCount = 0; // Weakly held references to all of the view managers @@ -298,11 +316,9 @@ nsIView* nsIViewManager::GetDisplayRootFor(nsIView* aView) aContext may be null, in which case layers should be used for rendering. */ -void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, - const nsIntRegion& aRegion, +void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint) { - NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch"); NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); // damageRegion is the damaged area, in twips, relative to the view origin @@ -335,8 +351,19 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, "Widgets that we paint must all be display roots"); if (mPresShell) { - mPresShell->Paint(aView, aWidget, damageRegion, aRegion, - aWillSendDidPaint); +#ifdef DEBUG_INVALIDATIONS + printf("--COMPOSITE-- %p\n", mPresShell); +#endif + if (IsRefreshDriverPaintingEnabled()) { + mPresShell->Paint(aView, damageRegion, nsIPresShell::PaintType_Composite, + false); + } else { + mPresShell->Paint(aView, damageRegion, nsIPresShell::PaintType_Full, + aWillSendDidPaint); + } +#ifdef DEBUG_INVALIDATIONS + printf("--ENDCOMPOSITE--\n"); +#endif mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT); } @@ -372,7 +399,41 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, // Push out updates after we've processed the children; ensures that // damage is applied based on the final widget geometry if (aFlushDirtyRegion) { - FlushDirtyRegionToWidget(aView); + if (IsRefreshDriverPaintingEnabled()) { + nsIWidget *widget = aView->GetWidget(); + if (widget && widget->NeedsPaint() && aView->HasNonEmptyDirtyRegion()) { + FlushDirtyRegionToWidget(aView); + // If an ancestor widget was hidden and then shown, we could + // have a delayed resize to handle. + for (nsViewManager *vm = this; vm; + vm = vm->mRootView->GetParent() + ? vm->mRootView->GetParent()->GetViewManager() + : nullptr) { + if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && + vm->mRootView->IsEffectivelyVisible() && + mPresShell && mPresShell->IsVisible()) { + vm->FlushDelayedResize(true); + vm->InvalidateView(vm->mRootView); + } + } + + NS_ASSERTION(aView->HasWidget(), "Must have a widget!"); + + SetPainting(true); +#ifdef DEBUG_INVALIDATIONS + printf("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", mPresShell, aView, widget); +#endif + nsAutoScriptBlocker scriptBlocker; + NS_ASSERTION(aView->HasWidget(), "Must have a widget!"); + mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, true); +#ifdef DEBUG_INVALIDATIONS + printf("---- PAINT END ----\n"); +#endif + SetPainting(false); + } + } else { + FlushDirtyRegionToWidget(aView); + } } } @@ -699,35 +760,38 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, break; *aStatus = nsEventStatus_eConsumeNoDefault; + + if (!IsRefreshDriverPaintingEnabled()) { - nsPaintEvent *event = static_cast(aEvent); + nsPaintEvent *event = static_cast(aEvent); - NS_ASSERTION(static_cast(aView) == - nsView::GetViewFor(event->widget), - "view/widget mismatch"); + NS_ASSERTION(static_cast(aView) == + nsView::GetViewFor(event->widget), + "view/widget mismatch"); - // If an ancestor widget was hidden and then shown, we could - // have a delayed resize to handle. - for (nsViewManager *vm = this; vm; - vm = vm->mRootView->GetParent() - ? vm->mRootView->GetParent()->GetViewManager() - : nullptr) { - if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && - vm->mRootView->IsEffectivelyVisible() && - mPresShell && mPresShell->IsVisible()) { - vm->FlushDelayedResize(true); - vm->InvalidateView(vm->mRootView); + // If an ancestor widget was hidden and then shown, we could + // have a delayed resize to handle. + for (nsViewManager *vm = this; vm; + vm = vm->mRootView->GetParent() + ? vm->mRootView->GetParent()->GetViewManager() + : nullptr) { + if (vm->mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && + vm->mRootView->IsEffectivelyVisible() && + mPresShell && mPresShell->IsVisible()) { + vm->FlushDelayedResize(true); + vm->InvalidateView(vm->mRootView); + } } - } - // Flush things like reflows and plugin widget geometry updates by - // calling WillPaint on observer presShells. - nsRefPtr rootVM = RootViewManager(); - if (mPresShell) { - rootVM->CallWillPaintOnObservers(event->willSendDidPaint); + // Flush things like reflows and plugin widget geometry updates by + // calling WillPaint on observer presShells. + nsRefPtr rootVM = RootViewManager(); + if (mPresShell) { + rootVM->CallWillPaintOnObservers(event->willSendDidPaint); + } + // Flush view widget geometry updates and invalidations. + rootVM->ProcessPendingUpdates(); } - // Flush view widget geometry updates and invalidations. - rootVM->ProcessPendingUpdates(); } break; @@ -745,7 +809,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, "shouldn't be receiving paint events while painting is " "disallowed!"); - if (!event->didSendWillPaint) { + if (!event->didSendWillPaint && !IsRefreshDriverPaintingEnabled()) { // Send NS_WILL_PAINT event ourselves. nsPaintEvent willPaintEvent(true, NS_WILL_PAINT, event->widget); willPaintEvent.willSendDidPaint = event->willSendDidPaint; @@ -760,14 +824,16 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, break; // Paint. - Refresh(view, event->widget, event->region, event->willSendDidPaint); + Refresh(view, event->region, event->willSendDidPaint); break; } case NS_DID_PAINT: { - nsRefPtr rootVM = RootViewManager(); - rootVM->CallDidPaintOnObserver(); + if (!IsRefreshDriverPaintingEnabled()) { + nsRefPtr rootVM = RootViewManager(); + rootVM->CallDidPaintOnObserver(); + } break; } @@ -1292,7 +1358,20 @@ nsViewManager::ProcessPendingUpdates() return; } - if (mHasPendingUpdates) { + if (IsRefreshDriverPaintingEnabled()) { + mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush(); + if (mHasPendingUpdates) { + mHasPendingUpdates = false; + + // Flush things like reflows and plugin widget geometry updates by + // calling WillPaint on observer presShells. + if (mPresShell) { + CallWillPaintOnObservers(true); + } + ProcessPendingUpdatesForView(mRootView, true); + CallDidPaintOnObserver(); + } + } else if (mHasPendingUpdates) { ProcessPendingUpdatesForView(mRootView, true); mHasPendingUpdates = false; } @@ -1307,8 +1386,8 @@ nsViewManager::UpdateWidgetGeometry() } if (mHasPendingWidgetGeometryChanges) { - ProcessPendingUpdatesForView(mRootView, false); mHasPendingWidgetGeometryChanges = false; + ProcessPendingUpdatesForView(mRootView, false); } } diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index 70ad2abd4678..cc9230b4a22d 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -129,8 +129,7 @@ private: void InvalidateViews(nsView *aView); // aView is the view for aWidget and aRegion is relative to aWidget. - void Refresh(nsView *aView, nsIWidget *aWidget, const nsIntRegion& aRegion, - bool aWillSendDidPaint); + void Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint); void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut); void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index c7d01eef8c81..00ff3a647d99 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2312,5 +2312,14 @@ nsWindow::ScheduleResumeComposition(int width, int height) } } +bool +nsWindow::NeedsPaint() +{ + if (sCompositorPaused || FindTopLevel() != nsWindow::TopWindow()) { + return false; + } + return nsIWidget::NeedsPaint(); +} + #endif diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 45ac8ec037df..4cbeb27bf141 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -148,6 +148,7 @@ public: NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent); #ifdef MOZ_JAVA_COMPOSITOR + virtual bool NeedsPaint(); virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect); virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect); diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 2ee0d13c5bf0..999aad98b250 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2556,6 +2556,9 @@ NSEvent* gLastDragMouseDownEvent = nil; [self setGLContext:glContext]; } + [glContext setView:self]; + [glContext update]; + mGeckoChild->DispatchWindowEvent(paintEvent); // Force OpenGL to refresh the very first time we draw. This works around a diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index e03aaca87462..50b192d54692 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1593,6 +1593,15 @@ class nsIWidget : public nsISupports { */ virtual bool WidgetPaintsBackground() { return false; } + virtual bool NeedsPaint() { + if (!IsVisible()) { + return false; + } + nsIntRect bounds; + nsresult rv = GetBounds(bounds); + NS_ENSURE_SUCCESS(rv, false); + return !bounds.IsEmpty(); + } /** * Get the natural bounds of this widget. This method is only * meaningful for widgets for which Gecko implements screen