From 6d78fb9dc66e485f29bf11285acf8d15a317ae6c Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 17 Jun 2013 14:46:53 +1200 Subject: [PATCH 001/615] Bug 877949 - Restrict maximum texture size on nvidia cards on OSX 10.6 and 10.7 to 4096. r=bjacob --- gfx/gl/GLContext.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index c811e0049332..596430334b8a 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -23,6 +23,10 @@ #include "mozilla/DebugOnly.h" #include "mozilla/Preferences.h" +#ifdef XP_MACOSX +#include +#endif + using namespace mozilla::gfx; namespace mozilla { @@ -568,14 +572,25 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize); #ifdef XP_MACOSX - if (mWorkAroundDriverBugs && - mVendor == VendorIntel) { - // see bug 737182 for 2D textures, bug 684882 for cube map textures. - mMaxTextureSize = std::min(mMaxTextureSize, 4096); - mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512); - // for good measure, we align renderbuffers on what we do for 2D textures - mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096); - mNeedsTextureSizeChecks = true; + if (mWorkAroundDriverBugs) { + if (mVendor == VendorIntel) { + // see bug 737182 for 2D textures, bug 684882 for cube map textures. + mMaxTextureSize = std::min(mMaxTextureSize, 4096); + mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512); + // for good measure, we align renderbuffers on what we do for 2D textures + mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096); + mNeedsTextureSizeChecks = true; + } else if (mVendor == VendorNVIDIA) { + SInt32 major, minor; + OSErr err1 = ::Gestalt(gestaltSystemVersionMajor, &major); + OSErr err2 = ::Gestalt(gestaltSystemVersionMinor, &minor); + + if (err1 != noErr || err2 != noErr || + major < 10 || (major == 10 && minor < 8)) { + mMaxTextureSize = std::min(mMaxTextureSize, 4096); + mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096); + } + } } #endif #ifdef MOZ_X11 From a7ebadcc0ef2f4a22b9ba5076e63588c02c5dbc9 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 17 Jun 2013 14:48:41 +1200 Subject: [PATCH 002/615] Bug 882590 - Fix invalid assertion when creating a SharedSurface_GLTexture without a consumer GLContext. r=jgilbert --- gfx/gl/SharedSurfaceGL.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp index b3e3d33a5e6a..f1c27e349671 100644 --- a/gfx/gl/SharedSurfaceGL.cpp +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -314,8 +314,8 @@ SharedSurface_GLTexture::Create(GLContext* prodGL, const gfxIntSize& size, bool hasAlpha) { - MOZ_ASSERT(prodGL && consGL); - MOZ_ASSERT(prodGL->SharesWith(consGL)); + MOZ_ASSERT(prodGL); + MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL)); prodGL->MakeCurrent(); GLuint tex = prodGL->CreateTextureForOffscreen(formats, size); @@ -386,6 +386,7 @@ SharedSurface_GLTexture::SetConsumerGL(GLContext* consGL) { MutexAutoLock lock(mMutex); MOZ_ASSERT(consGL); + MOZ_ASSERT(mGL->SharesWith(consGL)); mConsGL = consGL; } From 2f54796673c894a064ba32ea873964e4c710fce3 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 17 Jun 2013 14:50:32 +1200 Subject: [PATCH 003/615] Bug 877534 - Use a shutdown listener to destroy the compositor from nsBaseWidget. r=roc This prevents a case where the nsBaseWidget isn't destroyed until the cycle collector is shutdown, and we are too late in the shutdown sequence to process the events that get queued during Compositor teardown. --- widget/xpwidgets/nsBaseWidget.cpp | 33 +++++++++++++++++++++++++++++++ widget/xpwidgets/nsBaseWidget.h | 20 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index ad8b62752b5e..22f50b3d0624 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -118,8 +118,31 @@ nsBaseWidget::nsBaseWidget() #ifdef DEBUG debug_RegisterPrefCallbacks(); #endif + + mShutdownObserver = new WidgetShutdownObserver(this); + nsContentUtils::RegisterShutdownObserver(mShutdownObserver); } +NS_IMPL_ISUPPORTS1(WidgetShutdownObserver, nsIObserver) + +NS_IMETHODIMP +WidgetShutdownObserver::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + mWidget->Shutdown(); + nsContentUtils::UnregisterShutdownObserver(this); + } + return NS_OK; +} + +void +nsBaseWidget::Shutdown() +{ + DestroyCompositor(); + mShutdownObserver = nullptr; +} static void DeferredDestroyCompositor(CompositorParent* aCompositorParent, CompositorChild* aCompositorChild) @@ -171,6 +194,10 @@ nsBaseWidget::~nsBaseWidget() mLayerManager = nullptr; } + if (mShutdownObserver) { + nsContentUtils::UnregisterShutdownObserver(mShutdownObserver); + } + DestroyCompositor(); #ifdef NOISY_WIDGET_LEAKS @@ -893,6 +920,12 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) // Recreating this is tricky, as we may still have an old and we need // to make sure it's properly destroyed by calling DestroyCompositor! + // If we've already received a shutdown notification, don't try + // create a new compositor. + if (!mShutdownObserver) { + return; + } + mCompositorParent = NewCompositorParent(aWidth, aHeight); AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel(); LayerManager* lm = new ClientLayerManager(this); diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index 87ff5eedc752..d3efcb931b39 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -15,6 +15,7 @@ #include "nsGUIEvent.h" #include "nsAutoPtr.h" #include "nsIRollupListener.h" +#include "nsIObserver.h" #include class nsIContent; class nsAutoRollup; @@ -38,6 +39,22 @@ namespace base { class Thread; } +class nsBaseWidget; + +class WidgetShutdownObserver MOZ_FINAL : public nsIObserver +{ +public: + WidgetShutdownObserver(nsBaseWidget* aWidget) + : mWidget(aWidget) + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + +private: + nsBaseWidget *mWidget; +}; + /** * Common widget implementation used as base class for native * or crossplatform implementations of Widgets. @@ -254,6 +271,8 @@ public: static nsIRollupListener* GetActiveRollupListener(); + void Shutdown(); + protected: virtual void ResolveIconName(const nsAString &aIconName, @@ -356,6 +375,7 @@ protected: nsRefPtr mBasicLayerManager; nsRefPtr mCompositorChild; nsRefPtr mCompositorParent; + nsCOMPtr mShutdownObserver; nscolor mBackground; nscolor mForeground; nsCursor mCursor; From 7e37b3be70c685f627eb70a7c725cae6c195d471 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 2 Feb 2013 17:21:45 -0800 Subject: [PATCH 004/615] Bug 832848: Removed unused site identity block tooltip logic from PSM, r=dolske --HG-- extra : rebase_source : 1793e526272622d811e45d0f4b2f0460471f4501 --- dom/ipc/TabParent.cpp | 7 - netwerk/base/public/nsISecureBrowserUI.idl | 3 +- netwerk/socket/nsITransportSecurityInfo.idl | 3 +- .../boot/src/nsSecureBrowserUIImpl.cpp | 97 +---------- .../manager/boot/src/nsSecureBrowserUIImpl.h | 8 +- .../en-US/chrome/pipnss/pipnss.properties | 1 - .../en-US/chrome/pipnss/security.properties | 3 - .../en-US/chrome/pippki/pippki.properties | 1 - .../manager/ssl/src/TransportSecurityInfo.cpp | 24 +-- .../manager/ssl/src/TransportSecurityInfo.h | 1 - security/manager/ssl/src/nsNSSCallbacks.cpp | 162 +++++++----------- 11 files changed, 77 insertions(+), 233 deletions(-) diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index d9e6dc992bee..5f16db0e7e18 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -538,13 +538,6 @@ TabParent::SetDocShell(nsIDocShell *aDocShell) return NS_OK; } -NS_IMETHODIMP -TabParent::GetTooltipText(nsAString & aTooltipText) -{ - aTooltipText.Truncate(); - return NS_OK; -} - PDocumentRendererParent* TabParent::AllocPDocumentRenderer(const nsRect& documentRect, const gfxMatrix& transform, diff --git a/netwerk/base/public/nsISecureBrowserUI.idl b/netwerk/base/public/nsISecureBrowserUI.idl index fb8c00663dee..a017d830acd6 100644 --- a/netwerk/base/public/nsISecureBrowserUI.idl +++ b/netwerk/base/public/nsISecureBrowserUI.idl @@ -10,14 +10,13 @@ interface nsIDOMWindow; interface nsIDOMElement; interface nsIDocShell; -[scriptable, uuid(e97e5688-add2-4a1d-acae-396d7702e382)] +[scriptable, uuid(62f6c5be-ea8c-4fab-8e5c-d1580b50ec3f)] interface nsISecureBrowserUI : nsISupports { void init(in nsIDOMWindow window); void setDocShell(in nsIDocShell docShell); readonly attribute unsigned long state; - readonly attribute AString tooltipText; }; %{C++ diff --git a/netwerk/socket/nsITransportSecurityInfo.idl b/netwerk/socket/nsITransportSecurityInfo.idl index f237d01dc8b6..96a16233b7f8 100644 --- a/netwerk/socket/nsITransportSecurityInfo.idl +++ b/netwerk/socket/nsITransportSecurityInfo.idl @@ -6,10 +6,9 @@ #include "nsISupports.idl" -[scriptable, uuid(0d0a6b62-d4a9-402e-a197-6bc6e358fec9)] +[scriptable, uuid(8813d03b-e76c-4240-9691-d327d9b91e88)] interface nsITransportSecurityInfo : nsISupports { readonly attribute unsigned long securityState; - readonly attribute wstring shortSecurityDescription; readonly attribute wstring errorMessage; }; diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp index 7b9e5d2061c7..584ffd5cebf6 100644 --- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp +++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp @@ -48,8 +48,6 @@ using namespace mozilla; -#define SECURITY_STRING_BUNDLE_URL "chrome://pipnss/locale/security.properties" - #define IS_SECURE(state) ((state & 0xFFFF) == STATE_IS_SECURE) #if defined(PR_LOGGING) @@ -191,17 +189,6 @@ nsSecureBrowserUIImpl::Init(nsIDOMWindow *aWindow) mWindow = do_GetWeakReference(pwin, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr service(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv)); - if (NS_FAILED(rv)) return rv; - - // We do not need to test for mStringBundle here... - // Anywhere we use it, we will test before using. Some - // embedded users of PSM may want to reuse our - // nsSecureBrowserUIImpl implementation without the - // bundle. - service->CreateBundle(SECURITY_STRING_BUNDLE_URL, getter_AddRefs(mStringBundle)); - - // hook up to the form post notifications: nsCOMPtr svc(do_GetService("@mozilla.org/observer-service;1", &rv)); if (NS_SUCCEEDED(rv)) { @@ -337,36 +324,6 @@ nsSecureBrowserUIImpl::SetDocShell(nsIDocShell *aDocShell) return rv; } -NS_IMETHODIMP -nsSecureBrowserUIImpl::GetTooltipText(nsAString& aText) -{ - lockIconState state; - nsXPIDLString tooltip; - - { - ReentrantMonitorAutoEnter lock(mReentrantMonitor); - state = mNotifiedSecurityState; - tooltip = mInfoTooltip; - } - - if (state == lis_mixed_security) - { - GetBundleString(NS_LITERAL_STRING("SecurityButtonMixedContentTooltipText").get(), - aText); - } - else if (!tooltip.IsEmpty()) - { - aText = tooltip; - } - else - { - GetBundleString(NS_LITERAL_STRING("SecurityButtonTooltipText").get(), - aText); - } - - return NS_OK; -} - NS_IMETHODIMP nsSecureBrowserUIImpl::Observe(nsISupports*, const char*, const PRUnichar*) @@ -504,7 +461,6 @@ void nsSecureBrowserUIImpl::ResetStateTracking() { ReentrantMonitorAutoEnter lock(mReentrantMonitor); - mInfoTooltip.Truncate(); mDocumentRequestsInProgress = 0; if (mTransferringRequests.ops) { PL_DHashTableFinish(&mTransferringRequests); @@ -528,9 +484,6 @@ nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest, nsIS bool updateStatus = false; nsCOMPtr temp_SSLStatus; - bool updateTooltip = false; - nsXPIDLString temp_InfoTooltip; - temp_NewToplevelSecurityState = GetSecurityStateFromSecurityInfo(info); PR_LOG(gSecureDocLog, PR_LOG_DEBUG, @@ -550,14 +503,6 @@ nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest, nsIS } } - if (info) { - nsCOMPtr secInfo(do_QueryInterface(info)); - if (secInfo) { - updateTooltip = true; - secInfo->GetShortSecurityDescription(getter_Copies(temp_InfoTooltip)); - } - } - // assume temp_NewToplevelSecurityState was set in this scope! // see code that is directly above @@ -569,9 +514,6 @@ nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest, nsIS if (updateStatus) { mSSLStatus = temp_SSLStatus; } - if (updateTooltip) { - mInfoTooltip = temp_InfoTooltip; - } PR_LOG(gSecureDocLog, PR_LOG_DEBUG, ("SecureUI:%p: remember securityInfo %p\n", this, info)); @@ -588,8 +530,7 @@ nsSecureBrowserUIImpl::EvaluateAndUpdateSecurityState(nsIRequest* aRequest, nsIS mRestoreSubrequests = false; } - return UpdateSecurityState(aRequest, withNewLocation, - updateStatus, updateTooltip); + return UpdateSecurityState(aRequest, withNewLocation, updateStatus); } void @@ -1311,7 +1252,7 @@ nsSecureBrowserUIImpl::OnStateChange(nsIWebProgress* aWebProgress, } if (temp_NewToplevelSecurityStateKnown) - return UpdateSecurityState(aRequest, false, false, false); + return UpdateSecurityState(aRequest, false, false); } return NS_OK; @@ -1331,8 +1272,7 @@ void nsSecureBrowserUIImpl::ObtainEventSink(nsIChannel *channel, nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest, bool withNewLocation, - bool withUpdateStatus, - bool withUpdateTooltip) + bool withUpdateStatus) { lockIconState warnSecurityState = lis_no_security; nsresult rv = NS_OK; @@ -1340,7 +1280,7 @@ nsresult nsSecureBrowserUIImpl::UpdateSecurityState(nsIRequest* aRequest, // both parameters are both input and outout bool flagsChanged = UpdateMyFlags(warnSecurityState); - if (flagsChanged || withNewLocation || withUpdateStatus || withUpdateTooltip) + if (flagsChanged || withNewLocation || withUpdateStatus) rv = TellTheWorld(warnSecurityState, aRequest); return rv; @@ -1407,7 +1347,6 @@ bool nsSecureBrowserUIImpl::UpdateMyFlags(lockIconState &warnSecurityState) if (lis_no_security == newSecurityState) { mSSLStatus = nullptr; - mInfoTooltip.Truncate(); } } @@ -1547,7 +1486,7 @@ nsSecureBrowserUIImpl::OnLocationChange(nsIWebProgress* aWebProgress, } if (temp_NewToplevelSecurityStateKnown) - return UpdateSecurityState(aRequest, true, false, false); + return UpdateSecurityState(aRequest, true, false); return NS_OK; } @@ -1637,32 +1576,6 @@ nsSecureBrowserUIImpl::IsURLJavaScript(nsIURI* aURL, bool* value) return aURL->SchemeIs("javascript", value); } -void -nsSecureBrowserUIImpl::GetBundleString(const PRUnichar* name, - nsAString &outString) -{ - nsCOMPtr temp_StringBundle; - - { - ReentrantMonitorAutoEnter lock(mReentrantMonitor); - temp_StringBundle = mStringBundle; - } - - if (temp_StringBundle && name) { - PRUnichar *ptrv = nullptr; - if (NS_SUCCEEDED(temp_StringBundle->GetStringFromName(name, - &ptrv))) - outString = ptrv; - else - outString.SetLength(0); - - nsMemory::Free(ptrv); - - } else { - outString.SetLength(0); - } -} - nsresult nsSecureBrowserUIImpl::CheckPost(nsIURI *formURL, nsIURI *actionURL, bool *okayToPost) { diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.h b/security/manager/boot/src/nsSecureBrowserUIImpl.h index fc614663208f..174bffe82c03 100644 --- a/security/manager/boot/src/nsSecureBrowserUIImpl.h +++ b/security/manager/boot/src/nsSecureBrowserUIImpl.h @@ -8,13 +8,11 @@ #include "mozilla/ReentrantMonitor.h" #include "nsCOMPtr.h" -#include "nsXPIDLString.h" #include "nsString.h" #include "nsIObserver.h" #include "nsIDOMElement.h" #include "nsIDOMWindow.h" #include "nsIDOMHTMLFormElement.h" -#include "nsIStringBundle.h" #include "nsISecureBrowserUI.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" @@ -69,7 +67,6 @@ protected: nsWeakPtr mWindow; nsWeakPtr mDocShell; nsCOMPtr mIOService; - nsCOMPtr mStringBundle; nsCOMPtr mCurrentURI; nsCOMPtr mToplevelEventSink; @@ -89,7 +86,6 @@ protected: bool mNewToplevelSecurityStateKnown; bool mIsViewSource; - nsXPIDLString mInfoTooltip; int32_t mDocumentRequestsInProgress; int32_t mSubRequestsBrokenSecurity; int32_t mSubRequestsNoSecurity; @@ -103,7 +99,7 @@ protected: static already_AddRefed ExtractSecurityInfo(nsIRequest* aRequest); nsresult MapInternalToExternalState(uint32_t* aState, lockIconState lock, bool ev); nsresult UpdateSecurityState(nsIRequest* aRequest, bool withNewLocation, - bool withUpdateStatus, bool withUpdateTooltip); + bool withUpdateStatus); bool UpdateMyFlags(lockIconState &warnSecurityState); nsresult TellTheWorld(lockIconState warnSecurityState, nsIRequest* aRequest); @@ -118,8 +114,6 @@ protected: nsCOMPtr mSSLStatus; nsCOMPtr mCurrentToplevelSecurityInfo; - void GetBundleString(const PRUnichar* name, nsAString &outString); - nsresult CheckPost(nsIURI *formURI, nsIURI *actionURL, bool *okayToPost); nsresult IsURLHTTPS(nsIURI* aURL, bool *value); nsresult IsURLJavaScript(nsIURI* aURL, bool *value); diff --git a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties index 5f36bf1a9b4c..d8834955adc2 100755 --- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties +++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties @@ -3,7 +3,6 @@ # 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/. -SignedBy=Authenticated by %S CertPassPrompt=Please enter the master password for the %S. # the following strings have special requirements: # they must fit in a 32 or 64 byte buffer after being translated diff --git a/security/manager/locales/en-US/chrome/pipnss/security.properties b/security/manager/locales/en-US/chrome/pipnss/security.properties index 764ca812aa66..50af92694e0e 100644 --- a/security/manager/locales/en-US/chrome/pipnss/security.properties +++ b/security/manager/locales/en-US/chrome/pipnss/security.properties @@ -1,10 +1,7 @@ -# # 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/. Title=Security Warning PostToInsecureFromSecureMessage=Although this page is encrypted, the information you have entered is to be sent over an unencrypted connection and could easily be read by a third party.##Are you sure you want to continue sending this information?## -SecurityButtonTooltipText=Displays security information about the current page -SecurityButtonMixedContentTooltipText=Warning: Contains unauthenticated content Continue=Continue diff --git a/security/manager/locales/en-US/chrome/pippki/pippki.properties b/security/manager/locales/en-US/chrome/pippki/pippki.properties index 4d8445d2e660..5e98f19afe68 100644 --- a/security/manager/locales/en-US/chrome/pippki/pippki.properties +++ b/security/manager/locales/en-US/chrome/pippki/pippki.properties @@ -3,7 +3,6 @@ # 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/. -SignedBy=Authenticated by %S CertPassPrompt=Please enter the Personal Security Password for the PSM Private Keys security device. #These are for dialogs diff --git a/security/manager/ssl/src/TransportSecurityInfo.cpp b/security/manager/ssl/src/TransportSecurityInfo.cpp index 94535fe7fbbd..fbf492b91f74 100644 --- a/security/manager/ssl/src/TransportSecurityInfo.cpp +++ b/security/manager/ssl/src/TransportSecurityInfo.cpp @@ -175,25 +175,6 @@ TransportSecurityInfo::Flush() return NS_OK; } -NS_IMETHODIMP -TransportSecurityInfo::GetShortSecurityDescription(PRUnichar** aText) -{ - if (mShortDesc.IsEmpty()) - *aText = nullptr; - else { - *aText = ToNewUnicode(mShortDesc); - NS_ENSURE_TRUE(*aText, NS_ERROR_OUT_OF_MEMORY); - } - return NS_OK; -} - -nsresult -TransportSecurityInfo::SetShortSecurityDescription(const PRUnichar* aText) -{ - mShortDesc.Assign(aText); - return NS_OK; -} - NS_IMETHODIMP TransportSecurityInfo::GetErrorMessage(PRUnichar** aText) { @@ -358,7 +339,7 @@ TransportSecurityInfo::Write(nsIObjectOutputStream* stream) uint32_t version = 3; stream->Write32(version | 0xFFFF0000); stream->Write32(mSecurityState); - stream->WriteWStringZ(mShortDesc.get()); + stream->WriteWStringZ(EmptyString().get()); // XXX: uses nsNSSComponent string bundles off the main thread nsresult rv = formatErrorMessage(lock, @@ -459,7 +440,8 @@ TransportSecurityInfo::Read(nsIObjectInputStream* stream) mSecurityState = version; version = 1; } - stream->ReadString(mShortDesc); + nsAutoString dummyShortDesc; + stream->ReadString(dummyShortDesc); stream->ReadString(mErrorMessageCached); mErrorCode = 0; diff --git a/security/manager/ssl/src/TransportSecurityInfo.h b/security/manager/ssl/src/TransportSecurityInfo.h index c4132f13f5c9..c13d89d27f02 100644 --- a/security/manager/ssl/src/TransportSecurityInfo.h +++ b/security/manager/ssl/src/TransportSecurityInfo.h @@ -90,7 +90,6 @@ private: uint32_t mSecurityState; int32_t mSubRequestsBrokenSecurity; int32_t mSubRequestsNoSecurity; - nsString mShortDesc; PRErrorCode mErrorCode; ::mozilla::psm::SSLErrorMessageType mErrorMessageType; diff --git a/security/manager/ssl/src/nsNSSCallbacks.cpp b/security/manager/ssl/src/nsNSSCallbacks.cpp index 4f77a86f0192..a8d7f6d30b4b 100644 --- a/security/manager/ssl/src/nsNSSCallbacks.cpp +++ b/security/manager/ssl/src/nsNSSCallbacks.cpp @@ -826,10 +826,8 @@ PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg) void HandshakeCallback(PRFileDesc* fd, void* client_data) { nsNSSShutDownPreventionLock locker; int32_t sslStatus; - char* signer = nullptr; char* cipherName = nullptr; int32_t keyLength; - nsresult rv; int32_t encryptBits; nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret; @@ -847,7 +845,7 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { ioLayerHelpers.rememberTolerantSite(infoObject); if (SECSuccess != SSL_SecurityStatus(fd, &sslStatus, &cipherName, &keyLength, - &encryptBits, &signer, nullptr)) { + &encryptBits, nullptr, nullptr)) { return; } @@ -883,116 +881,88 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) { } } - ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd)); - const char* caName = nullptr; // caName is a pointer only, no ownership - char* certOrgName = CERT_GetOrgName(&serverCert->issuer); - caName = certOrgName ? certOrgName : signer; - const char* verisignName = "Verisign, Inc."; - // If the CA name is RSA Data Security, then change the name to the real - // name of the company i.e. VeriSign, Inc. - if (nsCRT::strcmp((const char*)caName, "RSA Data Security, Inc.") == 0) { - caName = verisignName; + infoObject->SetSecurityState(secStatus); + + /* Set the SSL Status information */ + RefPtr status(infoObject->SSLStatus()); + if (!status) { + status = new nsSSLStatus(); + infoObject->SetSSLStatus(status); } - nsAutoString shortDesc; - const PRUnichar* formatStrings[1] = { ToNewUnicode(NS_ConvertUTF8toUTF16(caName)) }; - nsCOMPtr nssComponent(do_GetService(kNSSComponentCID, &rv)); - if (NS_SUCCEEDED(rv)) { - rv = nssComponent->PIPBundleFormatStringFromName("SignedBy", - formatStrings, 1, - shortDesc); + RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject, + status); - nsMemory::Free(const_cast(formatStrings[0])); + RefPtr nssc(nsNSSCertificate::Create(serverCert)); + nsCOMPtr prevcert; + infoObject->GetPreviousCert(getter_AddRefs(prevcert)); - nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret; - infoObject->SetSecurityState(secStatus); - infoObject->SetShortSecurityDescription(shortDesc.get()); - - /* Set the SSL Status information */ - RefPtr status(infoObject->SSLStatus()); - if (!status) { - status = new nsSSLStatus(); - infoObject->SetSSLStatus(status); + bool equals_previous = false; + if (prevcert && nssc) { + nsresult rv = nssc->Equals(prevcert, &equals_previous); + if (NS_FAILED(rv)) { + equals_previous = false; } + } - RememberCertErrorsTable::GetInstance().LookupCertErrorBits(infoObject, - status); - - if (serverCert) { - RefPtr nssc(nsNSSCertificate::Create(serverCert)); - nsCOMPtr prevcert; - infoObject->GetPreviousCert(getter_AddRefs(prevcert)); - - bool equals_previous = false; - if (prevcert && nssc) { - nsresult rv = nssc->Equals(prevcert, &equals_previous); - if (NS_FAILED(rv)) { - equals_previous = false; - } - } - - if (equals_previous) { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, - ("HandshakeCallback using PREV cert %p\n", prevcert.get())); - status->mServerCert = prevcert; - } - else { - if (status->mServerCert) { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, - ("HandshakeCallback KEEPING cert %p\n", status->mServerCert.get())); - } - else { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, - ("HandshakeCallback using NEW cert %p\n", nssc.get())); - status->mServerCert = nssc; - } - } + if (equals_previous) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("HandshakeCallback using PREV cert %p\n", prevcert.get())); + status->mServerCert = prevcert; + } + else { + if (status->mServerCert) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("HandshakeCallback KEEPING cert %p\n", status->mServerCert.get())); } + else { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("HandshakeCallback using NEW cert %p\n", nssc.get())); + status->mServerCert = nssc; + } + } - status->mHaveKeyLengthAndCipher = true; - status->mKeyLength = keyLength; - status->mSecretKeyLength = encryptBits; - status->mCipherName.Assign(cipherName); + status->mHaveKeyLengthAndCipher = true; + status->mKeyLength = keyLength; + status->mSecretKeyLength = encryptBits; + status->mCipherName.Assign(cipherName); - // Get the NPN value. - SSLNextProtoState state; - unsigned char npnbuf[256]; - unsigned int npnlen; + // Get the NPN value. + SSLNextProtoState state; + unsigned char npnbuf[256]; + unsigned int npnlen; - if (SSL_GetNextProto(fd, &state, npnbuf, &npnlen, 256) == SECSuccess) { - if (state == SSL_NEXT_PROTO_NEGOTIATED) - infoObject->SetNegotiatedNPN(reinterpret_cast(npnbuf), npnlen); - else - infoObject->SetNegotiatedNPN(nullptr, 0); - mozilla::Telemetry::Accumulate(Telemetry::SSL_NPN_TYPE, state); - } + if (SSL_GetNextProto(fd, &state, npnbuf, &npnlen, 256) == SECSuccess) { + if (state == SSL_NEXT_PROTO_NEGOTIATED) + infoObject->SetNegotiatedNPN(reinterpret_cast(npnbuf), npnlen); else infoObject->SetNegotiatedNPN(nullptr, 0); - - SSLChannelInfo channelInfo; - if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) { - // Get the protocol version for telemetry - // 0=ssl3, 1=tls1, 2=tls1.1, 3=tls1.2 - unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; - Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); - - SSLCipherSuiteInfo cipherInfo; - if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, - sizeof (cipherInfo)) == SECSuccess) { - // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 - Telemetry::Accumulate(Telemetry::SSL_KEY_EXCHANGE_ALGORITHM, - cipherInfo.keaType); - } - - } - infoObject->SetHandshakeCompleted(isResumedSession); + mozilla::Telemetry::Accumulate(Telemetry::SSL_NPN_TYPE, state); } + else + infoObject->SetNegotiatedNPN(nullptr, 0); + + SSLChannelInfo channelInfo; + if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) { + // Get the protocol version for telemetry + // 0=ssl3, 1=tls1, 2=tls1.1, 3=tls1.2 + unsigned int versionEnum = channelInfo.protocolVersion & 0xFF; + Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_VERSION, versionEnum); + + SSLCipherSuiteInfo cipherInfo; + if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, + sizeof (cipherInfo)) == SECSuccess) { + // keyExchange null=0, rsa=1, dh=2, fortezza=3, ecdh=4 + Telemetry::Accumulate(Telemetry::SSL_KEY_EXCHANGE_ALGORITHM, + cipherInfo.keaType); + } + + } + infoObject->SetHandshakeCompleted(isResumedSession); PORT_Free(cipherName); - PR_FREEIF(certOrgName); - PR_Free(signer); } struct OCSPDefaultResponders { From 75ab2ff4732efa81f75b2776b4bf1e8b77f1e03d Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 14 Jun 2013 15:19:30 -0700 Subject: [PATCH 005/615] Bug 874764 - Add CheckedInt support for operator%. - r=bjacob,waldo --- mfbt/CheckedInt.h | 55 +++++++++++++++++++++++++++++++++-- mfbt/tests/TestCheckedInt.cpp | 32 ++++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/mfbt/CheckedInt.h b/mfbt/CheckedInt.h index 1dc80b032bb3..5b5b86d03f89 100644 --- a/mfbt/CheckedInt.h +++ b/mfbt/CheckedInt.h @@ -450,6 +450,44 @@ IsDivValid(T x, T y) !(IsSigned::value && x == MinValue::value && y == T(-1)); } +template::value> +struct IsModValidImpl; + +template +inline bool +IsModValid(T x, T y) +{ + return IsModValidImpl::run(x, y); +} + +/* + * Mod is pretty simple. + * For now, let's just use the ANSI C definition: + * If x or y are negative, the results are implementation defined. + * Consider these invalid. + * Undefined for y=0. + * The result will never exceed either x or y. + * + * Checking that x>=0 is a warning when T is unsigned. + */ + +template +struct IsModValidImpl { + static inline bool run(T x, T y) { + return y >= 1; + } +}; + +template +struct IsModValidImpl { + static inline bool run(T x, T y) { + if (x < 0) + return false; + + return y >= 1; + } +}; + template::value> struct NegateImpl; @@ -619,22 +657,31 @@ class CheckedInt const CheckedInt& rhs); template CheckedInt& operator +=(U rhs); + template friend CheckedInt operator -(const CheckedInt& lhs, - const CheckedInt &rhs); + const CheckedInt& rhs); template CheckedInt& operator -=(U rhs); + template friend CheckedInt operator *(const CheckedInt& lhs, - const CheckedInt &rhs); + const CheckedInt& rhs); template CheckedInt& operator *=(U rhs); + template friend CheckedInt operator /(const CheckedInt& lhs, - const CheckedInt &rhs); + const CheckedInt& rhs); template CheckedInt& operator /=(U rhs); + template + friend CheckedInt operator %(const CheckedInt& lhs, + const CheckedInt& rhs); + template + CheckedInt& operator %=(U rhs); + CheckedInt operator -() const { return detail::NegateImpl::negate(*this); @@ -726,6 +773,7 @@ MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +) MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -) MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *) MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /) +MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mod, %) #undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR @@ -786,6 +834,7 @@ MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=) MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=) MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=) MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=) +MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(%, %=) #undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS diff --git a/mfbt/tests/TestCheckedInt.cpp b/mfbt/tests/TestCheckedInt.cpp index f6e0c2830d2a..8e9aa42d8a50 100644 --- a/mfbt/tests/TestCheckedInt.cpp +++ b/mfbt/tests/TestCheckedInt.cpp @@ -190,6 +190,26 @@ void test() VERIFY_IS_INVALID(one - min + min); } + /* Modulo checks */ + VERIFY_IS_INVALID(zero % zero); + VERIFY_IS_INVALID(one % zero); + VERIFY_IS_VALID(zero % one); + VERIFY_IS_VALID(zero % max); + VERIFY_IS_VALID(one % max); + VERIFY_IS_VALID(max % one); + VERIFY_IS_VALID(max % max); + if (isTSigned) { + const CheckedInt minusOne = zero - one; + VERIFY_IS_INVALID(minusOne % minusOne); + VERIFY_IS_INVALID(zero % minusOne); + VERIFY_IS_INVALID(one % minusOne); + VERIFY_IS_INVALID(minusOne % one); + + VERIFY_IS_INVALID(min % min); + VERIFY_IS_INVALID(zero % min); + VERIFY_IS_INVALID(min % one); + } + /* Unary operator- checks */ const CheckedInt negOne = -one; @@ -347,10 +367,15 @@ void test() VERIFY_IS_INVALID(someInvalid / one); VERIFY_IS_INVALID(zero / someInvalid); VERIFY_IS_INVALID(one / someInvalid); + VERIFY_IS_INVALID(someInvalid % zero); + VERIFY_IS_INVALID(someInvalid % one); + VERIFY_IS_INVALID(zero % someInvalid); + VERIFY_IS_INVALID(one % someInvalid); VERIFY_IS_INVALID(someInvalid + someInvalid); VERIFY_IS_INVALID(someInvalid - someInvalid); VERIFY_IS_INVALID(someInvalid * someInvalid); VERIFY_IS_INVALID(someInvalid / someInvalid); + VERIFY_IS_INVALID(someInvalid % someInvalid); /* Check that mixing checked integers with plain integers in expressions is allowed */ @@ -382,6 +407,13 @@ void test() x /= 2; VERIFY(x == two); } + VERIFY(three % 2 == one); + VERIFY(3 % two == one); + { + CheckedInt x = three; + x %= 2; + VERIFY(x == one); + } VERIFY(one == 1); VERIFY(1 == one); From 3049ca7c7646ba08a91e5ca898c2dfae616d20e4 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 14 Jun 2013 15:19:40 -0700 Subject: [PATCH 006/615] Bug 881980 - Allow casting CheckedInts to other CheckedInt types. - r=bjacob,waldo --- mfbt/CheckedInt.h | 13 +++++++++- mfbt/tests/TestCheckedInt.cpp | 45 +++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/mfbt/CheckedInt.h b/mfbt/CheckedInt.h index 5b5b86d03f89..e0c0ebe74963 100644 --- a/mfbt/CheckedInt.h +++ b/mfbt/CheckedInt.h @@ -566,7 +566,7 @@ struct NegateImpl CheckedInt x(-1); // 1000 is of type int16_t, is found not to be in range for int8_t, // x is invalid - CheckedInt x(int16_t(1000)); + CheckedInt x(int16_t(1000)); // 3123456789 is of type uint32_t, is found not to be in range for int32_t, // x is invalid CheckedInt x(uint32_t(3123456789)); @@ -628,6 +628,17 @@ class CheckedInt "This type is not supported by CheckedInt"); } + template + friend class CheckedInt; + + template + CheckedInt toChecked() const + { + CheckedInt ret(mValue); + ret.mIsValid = ret.mIsValid && mIsValid; + return ret; + } + /** Constructs a valid checked integer with initial value 0 */ CheckedInt() : mValue(0), mIsValid(true) { diff --git a/mfbt/tests/TestCheckedInt.cpp b/mfbt/tests/TestCheckedInt.cpp index 8e9aa42d8a50..5a9cba78c24d 100644 --- a/mfbt/tests/TestCheckedInt.cpp +++ b/mfbt/tests/TestCheckedInt.cpp @@ -422,25 +422,50 @@ void test() VERIFY_IS_FALSE(someInvalid == 1); VERIFY_IS_FALSE(1 == someInvalid); - /* Check that construction of CheckedInt from an integer value of a mismatched type is checked */ + // Check simple casting between different signedness and sizes. + { + CheckedInt foo = CheckedInt(2).toChecked(); + VERIFY_IS_VALID(foo); + VERIFY(foo == 2); + } + { + CheckedInt foo = CheckedInt(255).toChecked(); + VERIFY_IS_VALID(foo); + VERIFY(foo == 255); + } + { + CheckedInt foo = CheckedInt(256).toChecked(); + VERIFY_IS_INVALID(foo); + } + { + CheckedInt foo = CheckedInt(-2).toChecked(); + VERIFY_IS_INVALID(foo); + } - #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \ + // Check that construction of CheckedInt from an integer value of a mismatched type is checked + // Also check casting between all types. + + #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,V,PostVExpr) \ { \ bool isUSigned = detail::IsSigned::value; \ - VERIFY_IS_VALID(CheckedInt(U(0))); \ - VERIFY_IS_VALID(CheckedInt(U(1))); \ - VERIFY_IS_VALID(CheckedInt(U(100))); \ + VERIFY_IS_VALID(CheckedInt(V( 0)PostVExpr)); \ + VERIFY_IS_VALID(CheckedInt(V( 1)PostVExpr)); \ + VERIFY_IS_VALID(CheckedInt(V(100)PostVExpr)); \ if (isUSigned) \ - VERIFY_IS_VALID_IF(CheckedInt(U(-1)), isTSigned); \ + VERIFY_IS_VALID_IF(CheckedInt(V(-1)PostVExpr), isTSigned); \ if (sizeof(U) > sizeof(T)) \ - VERIFY_IS_INVALID(CheckedInt(U(detail::MaxValue::value) + one.value())); \ + VERIFY_IS_INVALID(CheckedInt(V(detail::MaxValue::value)PostVExpr + one.value())); \ VERIFY_IS_VALID_IF(CheckedInt(detail::MaxValue::value), \ (sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \ VERIFY_IS_VALID_IF(CheckedInt(detail::MinValue::value), \ - isUSigned == false ? 1 : \ - bool(isTSigned) == false ? 0 : \ - sizeof(T) >= sizeof(U)); \ + isUSigned == false ? 1 \ + : bool(isTSigned) == false ? 0 \ + : sizeof(T) >= sizeof(U)); \ } + #define VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(U) \ + VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,U,+0) \ + VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE2(U,CheckedInt,.toChecked()) + VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int8_t) VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(uint8_t) VERIFY_CONSTRUCTION_FROM_INTEGER_TYPE(int16_t) From 9b9a765974ed658b0a5cb21713347aa45b1b5872 Mon Sep 17 00:00:00 2001 From: Jonathan Wilde Date: Fri, 14 Jun 2013 15:23:51 -0700 Subject: [PATCH 007/615] Bug 811413 - Story - Domain highlighting. r=fryn --- .../base/content/bindings/autocomplete.xml | 9 +++ browser/metro/base/content/browser-ui.js | 80 +++++++++++++++++++ browser/metro/profile/metro.js | 1 + 3 files changed, 90 insertions(+) diff --git a/browser/metro/base/content/bindings/autocomplete.xml b/browser/metro/base/content/bindings/autocomplete.xml index e25f8feae126..11b17c07a159 100644 --- a/browser/metro/base/content/bindings/autocomplete.xml +++ b/browser/metro/base/content/bindings/autocomplete.xml @@ -22,6 +22,7 @@ this.popup._input = this; ]]> + + + + + + + diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 9c890d452946..0d217cae7798 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -97,6 +97,7 @@ var BrowserUI = { window.addEventListener("MozImprecisePointer", this, true); Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false); + Services.prefs.addObserver("browser.urlbar.formatting.enabled", this, false); Services.obs.addObserver(this, "metro_viewstate_changed", false); // Init core UI modules @@ -560,6 +561,9 @@ var BrowserUI = { case "browser.cache.disk_cache_ssl": this._sslDiskCacheEnabled = Services.prefs.getBoolPref(aData); break; + case "browser.urlbar.formatting.enabled": + this._formattingEnabled = Services.prefs.getBookPref(aData); + break; } break; case "metro_viewstate_changed": @@ -662,6 +666,7 @@ var BrowserUI = { }, _editURI: function _editURI(aShouldDismiss) { + this._clearURIFormatting(); this._edit.focus(); this._edit.select(); @@ -671,11 +676,77 @@ var BrowserUI = { ContextUI.dismissTabs(); }, + formatURI: function formatURI() { + if (!this.formattingEnabled || + Elements.urlbarState.getAttribute("mode") == "edit") + return; + + let controller = this._edit.editor.selectionController; + let selection = controller.getSelection(controller.SELECTION_URLSECONDARY); + selection.removeAllRanges(); + + let textNode = this._edit.editor.rootElement.firstChild; + let value = textNode.textContent; + + let protocol = value.match(/^[a-z\d.+\-]+:(?=[^\d])/); + if (protocol && + ["http:", "https:", "ftp:"].indexOf(protocol[0]) == -1) + return; + let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/); + if (!matchedURL) + return; + + let [, preDomain, domain] = matchedURL; + let baseDomain = domain; + let subDomain = ""; + // getBaseDomainFromHost doesn't recognize IPv6 literals in brackets as IPs (bug 667159) + if (domain[0] != "[") { + try { + baseDomain = Services.eTLD.getBaseDomainFromHost(domain); + if (!domain.endsWith(baseDomain)) { + // getBaseDomainFromHost converts its resultant to ACE. + let IDNService = Cc["@mozilla.org/network/idn-service;1"] + .getService(Ci.nsIIDNService); + baseDomain = IDNService.convertACEtoUTF8(baseDomain); + } + } catch (e) {} + } + if (baseDomain != domain) { + subDomain = domain.slice(0, -baseDomain.length); + } + + let rangeLength = preDomain.length + subDomain.length; + if (rangeLength) { + let range = document.createRange(); + range.setStart(textNode, 0); + range.setEnd(textNode, rangeLength); + selection.addRange(range); + } + + let startRest = preDomain.length + domain.length; + if (startRest < value.length) { + let range = document.createRange(); + range.setStart(textNode, startRest); + range.setEnd(textNode, value.length); + selection.addRange(range); + } + }, + + _clearURIFormatting: function _clearURIFormatting() { + if (!this.formattingEnabled) + return; + + let controller = this._edit.editor.selectionController; + let selection = controller.getSelection(controller.SELECTION_URLSECONDARY); + selection.removeAllRanges(); + }, + _urlbarBlurred: function _urlbarBlurred() { let state = Elements.urlbarState; if (state.getAttribute("mode") == "edit") state.removeAttribute("mode"); this._updateToolbar(); + this.formatURI(); }, _closeOrQuit: function _closeOrQuit() { @@ -959,6 +1030,15 @@ var BrowserUI = { return this._sslDiskCacheEnabled; }, + _formattingEnabled: null, + + get formattingEnabled() { + if (this._formattingEnabled === null) { + this._formattingEnabled = Services.prefs.getBoolPref("browser.urlbar.formatting.enabled"); + } + return this._formattingEnabled; + }, + supportsCommand : function(cmd) { var isSupported = false; switch (cmd) { diff --git a/browser/metro/profile/metro.js b/browser/metro/profile/metro.js index b6a523ef8125..988538f01980 100644 --- a/browser/metro/profile/metro.js +++ b/browser/metro/profile/metro.js @@ -261,6 +261,7 @@ pref("places.favicons.optimizeToDimension", 25); // various and sundry awesomebar prefs (should remove/re-evaluate // these once bug 447900 is fixed) +pref("browser.urlbar.formatting.enabled", true); pref("browser.urlbar.clickSelectsAll", true); pref("browser.urlbar.doubleClickSelectsAll", true); pref("browser.urlbar.autoFill", false); From 65dc14f2813f32b45a9ab13b48ade27a3a586e60 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Fri, 14 Jun 2013 15:37:27 -0700 Subject: [PATCH 008/615] [Bug 882536] Remove nsIDOMSVGDocument r=Ms2ger --- content/base/test/test_bug450160.html | 16 +++++----- .../html/content/src/HTMLIFrameElement.cpp | 1 - .../content/src/HTMLSharedObjectElement.cpp | 1 - content/svg/document/src/SVGDocument.cpp | 32 ------------------- content/svg/document/src/SVGDocument.h | 22 +------------ dom/interfaces/svg/moz.build | 1 - dom/interfaces/svg/nsIDOMSVGDocument.idl | 15 --------- 7 files changed, 9 insertions(+), 79 deletions(-) delete mode 100644 dom/interfaces/svg/nsIDOMSVGDocument.idl diff --git a/content/base/test/test_bug450160.html b/content/base/test/test_bug450160.html index d5fb7f86929d..dd28623b1ab4 100644 --- a/content/base/test/test_bug450160.html +++ b/content/base/test/test_bug450160.html @@ -32,9 +32,9 @@ function testHTMLDocuments(ids, isXHTML) { is(docType1.ownerDocument, doc1, "docType should have ownerDocument!"); ok(!doc1.documentElement, "Document shouldn't have document element!"); is(doc1.body, null, "Shouldn't have .body!"); - ok(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument, + ok(doc1 instanceof HTMLDocument, "Document should be an HTML document!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument), + ok(!(doc1 instanceof SVGDocument), "Document shouldn't be an SVG document!"); var docType2 = @@ -68,9 +68,9 @@ function testSVGDocument() { var doc1 = document.implementation.createDocument(null, null, docType1); is(docType1.ownerDocument, doc1, "docType should have ownerDocument!"); ok(!doc1.documentElement, "Document shouldn't have document element!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument), + ok(!(doc1 instanceof HTMLDocument), "Document shouldn't be an HTML document!"); - ok(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument, + ok(doc1 instanceof SVGDocument, "Document should be an SVG document!"); // SVG documents have .rootElement. @@ -95,9 +95,9 @@ function testFooBarDocument() { var doc1 = document.implementation.createDocument(null, null, docType1); is(docType1.ownerDocument, doc1, "docType should have ownerDocument!"); ok(!doc1.documentElement, "Document shouldn't have document element!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument), + ok(!(doc1 instanceof HTMLDocument), "Document shouldn't be an HTML document!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument), + ok(!(doc1 instanceof SVGDocument), "Document shouldn't be an SVG document!"); var docType2 = @@ -112,9 +112,9 @@ function testFooBarDocument() { function testNullDocTypeDocument() { var doc1 = document.implementation.createDocument(null, null, null); ok(!doc1.documentElement, "Document shouldn't have document element!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument), + ok(!(doc1 instanceof HTMLDocument), "Document shouldn't be an HTML document!"); - ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument), + ok(!(doc1 instanceof SVGDocument), "Document shouldn't be an SVG document!"); var doc2 = document.implementation.createDocument("FooBarNS", diff --git a/content/html/content/src/HTMLIFrameElement.cpp b/content/html/content/src/HTMLIFrameElement.cpp index 4f679cde433a..346b19a8c2db 100644 --- a/content/html/content/src/HTMLIFrameElement.cpp +++ b/content/html/content/src/HTMLIFrameElement.cpp @@ -7,7 +7,6 @@ #include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/dom/HTMLIFrameElementBinding.h" -#include "nsIDOMSVGDocument.h" #include "nsMappedAttributes.h" #include "nsAttrValueInlines.h" #include "nsError.h" diff --git a/content/html/content/src/HTMLSharedObjectElement.cpp b/content/html/content/src/HTMLSharedObjectElement.cpp index dff85b6298fd..5a2c862f381c 100644 --- a/content/html/content/src/HTMLSharedObjectElement.cpp +++ b/content/html/content/src/HTMLSharedObjectElement.cpp @@ -13,7 +13,6 @@ #include "nsIPluginDocument.h" #include "nsIDOMDocument.h" #include "nsThreadUtils.h" -#include "nsIDOMSVGDocument.h" #include "nsIScriptError.h" #include "nsIWidget.h" #include "nsContentUtils.h" diff --git a/content/svg/document/src/SVGDocument.cpp b/content/svg/document/src/SVGDocument.cpp index d588a1577f5c..cc0e84d3fe48 100644 --- a/content/svg/document/src/SVGDocument.cpp +++ b/content/svg/document/src/SVGDocument.cpp @@ -19,31 +19,9 @@ namespace dom { //---------------------------------------------------------------------- // Implementation -SVGDocument::SVGDocument() -{ -} - -SVGDocument::~SVGDocument() -{ -} - //---------------------------------------------------------------------- // nsISupports methods: -NS_IMPL_ISUPPORTS_INHERITED1(SVGDocument, XMLDocument, nsIDOMSVGDocument) - -//---------------------------------------------------------------------- -// nsIDOMSVGDocument methods: - -/* readonly attribute DOMString domain; */ -NS_IMETHODIMP -SVGDocument::GetDomain(nsAString& aDomain) -{ - ErrorResult rv; - GetDomain(aDomain, rv); - return rv.ErrorCode(); -} - void SVGDocument::GetDomain(nsAString& aDomain, ErrorResult& aRv) { @@ -63,16 +41,6 @@ SVGDocument::GetDomain(nsAString& aDomain, ErrorResult& aRv) } } -/* readonly attribute SVGSVGElement rootElement; */ -NS_IMETHODIMP -SVGDocument::GetRootElement(nsIDOMSVGElement** aRootElement) -{ - ErrorResult rv; - nsCOMPtr retval = GetRootElement(rv); - retval.forget(aRootElement); - return rv.ErrorCode(); -} - nsSVGElement* SVGDocument::GetRootElement(ErrorResult& aRv) { diff --git a/content/svg/document/src/SVGDocument.h b/content/svg/document/src/SVGDocument.h index 6e02cbeb5772..72c8652be048 100644 --- a/content/svg/document/src/SVGDocument.h +++ b/content/svg/document/src/SVGDocument.h @@ -8,35 +8,15 @@ #include "mozilla/Attributes.h" #include "mozilla/dom/XMLDocument.h" -#include "nsIDOMSVGDocument.h" class nsSVGElement; namespace mozilla { namespace dom { -class SVGDocument : public XMLDocument, - public nsIDOMSVGDocument +class SVGDocument : public XMLDocument { public: - using nsDocument::GetElementById; - using nsDocument::SetDocumentURI; - SVGDocument(); - virtual ~SVGDocument(); - - NS_DECL_NSIDOMSVGDOCUMENT - NS_FORWARD_NSIDOMDOCUMENT(mozilla::dom::XMLDocument::) - // And explicitly import the things from nsDocument that we just shadowed - using nsDocument::GetImplementation; - using nsDocument::GetTitle; - using nsDocument::SetTitle; - using nsDocument::GetLastStyleSheetSet; - using nsDocument::MozSetImageElement; - using nsDocument::GetMozFullScreenElement; - using nsIDocument::GetLocation; - - NS_FORWARD_NSIDOMNODE_TO_NSINODE - NS_DECL_ISUPPORTS_INHERITED virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL API diff --git a/dom/interfaces/svg/moz.build b/dom/interfaces/svg/moz.build index 46a8e651f252..1b34a9d7167f 100644 --- a/dom/interfaces/svg/moz.build +++ b/dom/interfaces/svg/moz.build @@ -10,7 +10,6 @@ XPIDL_SOURCES += [ 'nsIDOMSVGAnimatedLength.idl', 'nsIDOMSVGAnimatedNumber.idl', 'nsIDOMSVGAnimatedString.idl', - 'nsIDOMSVGDocument.idl', 'nsIDOMSVGElement.idl', 'nsIDOMSVGLength.idl', 'nsIDOMSVGNumber.idl', diff --git a/dom/interfaces/svg/nsIDOMSVGDocument.idl b/dom/interfaces/svg/nsIDOMSVGDocument.idl deleted file mode 100644 index 26edcb527787..000000000000 --- a/dom/interfaces/svg/nsIDOMSVGDocument.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsIDOMDocument.idl" - -interface nsIDOMSVGElement; - -[scriptable, uuid(72d201c7-159c-4b64-886f-ed3920dd9462)] -interface nsIDOMSVGDocument : nsIDOMDocument -{ - readonly attribute DOMString domain; - readonly attribute nsIDOMSVGElement rootElement; -}; From 54d09e22420be4682790092a7d97fdd7fc2e2399 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Fri, 14 Jun 2013 15:37:27 -0700 Subject: [PATCH 009/615] Bug 882553 - Convert SVGAnimatedString to WebIDL r=Ms2ger --- content/svg/content/src/SVGAElement.cpp | 4 +- content/svg/content/src/SVGAElement.h | 4 +- .../svg/content/src/SVGAltGlyphElement.cpp | 2 +- content/svg/content/src/SVGAltGlyphElement.h | 2 +- content/svg/content/src/SVGAnimatedString.cpp | 20 +++++++ content/svg/content/src/SVGAnimatedString.h | 43 +++++++++++++++ content/svg/content/src/SVGFEBlendElement.cpp | 4 +- content/svg/content/src/SVGFEBlendElement.h | 4 +- .../content/src/SVGFEColorMatrixElement.cpp | 2 +- .../svg/content/src/SVGFEColorMatrixElement.h | 2 +- .../src/SVGFEComponentTransferElement.cpp | 2 +- .../src/SVGFEComponentTransferElement.h | 2 +- .../svg/content/src/SVGFECompositeElement.cpp | 4 +- .../svg/content/src/SVGFECompositeElement.h | 4 +- .../src/SVGFEConvolveMatrixElement.cpp | 2 +- .../content/src/SVGFEConvolveMatrixElement.h | 2 +- .../src/SVGFEDiffuseLightingElement.cpp | 2 +- .../content/src/SVGFEDiffuseLightingElement.h | 2 +- .../src/SVGFEDisplacementMapElement.cpp | 4 +- .../content/src/SVGFEDisplacementMapElement.h | 4 +- .../content/src/SVGFEGaussianBlurElement.cpp | 2 +- .../content/src/SVGFEGaussianBlurElement.h | 2 +- content/svg/content/src/SVGFEImageElement.cpp | 2 +- content/svg/content/src/SVGFEImageElement.h | 2 +- .../svg/content/src/SVGFEMergeNodeElement.cpp | 2 +- .../svg/content/src/SVGFEMergeNodeElement.h | 2 +- .../content/src/SVGFEMorphologyElement.cpp | 2 +- .../svg/content/src/SVGFEMorphologyElement.h | 2 +- .../svg/content/src/SVGFEOffsetElement.cpp | 2 +- content/svg/content/src/SVGFEOffsetElement.h | 2 +- .../src/SVGFESpecularLightingElement.cpp | 2 +- .../src/SVGFESpecularLightingElement.h | 2 +- content/svg/content/src/SVGFETileElement.cpp | 2 +- content/svg/content/src/SVGFETileElement.h | 2 +- content/svg/content/src/SVGFilterElement.cpp | 2 +- content/svg/content/src/SVGFilterElement.h | 2 +- .../svg/content/src/SVGGradientElement.cpp | 2 +- content/svg/content/src/SVGGradientElement.h | 2 +- content/svg/content/src/SVGImageElement.cpp | 2 +- content/svg/content/src/SVGImageElement.h | 2 +- content/svg/content/src/SVGMPathElement.cpp | 2 +- content/svg/content/src/SVGMPathElement.h | 2 +- content/svg/content/src/SVGPatternElement.cpp | 2 +- content/svg/content/src/SVGPatternElement.h | 2 +- content/svg/content/src/SVGScriptElement.cpp | 2 +- content/svg/content/src/SVGScriptElement.h | 2 +- .../svg/content/src/SVGTextPathElement.cpp | 2 +- content/svg/content/src/SVGTextPathElement.h | 2 +- content/svg/content/src/SVGUseElement.cpp | 6 +-- content/svg/content/src/SVGUseElement.h | 2 +- content/svg/content/src/moz.build | 2 + content/svg/content/src/nsSVGClass.cpp | 53 +++++++++++++++---- content/svg/content/src/nsSVGClass.h | 39 +++----------- content/svg/content/src/nsSVGElement.cpp | 6 +-- content/svg/content/src/nsSVGElement.h | 2 +- content/svg/content/src/nsSVGFilters.cpp | 2 +- content/svg/content/src/nsSVGFilters.h | 2 +- content/svg/content/src/nsSVGString.cpp | 18 ++----- content/svg/content/src/nsSVGString.h | 37 +++++++------ dom/base/nsDOMClassInfo.cpp | 7 --- dom/base/nsDOMClassInfoClasses.h | 1 - dom/bindings/Bindings.conf | 1 - dom/interfaces/svg/moz.build | 1 - .../svg/nsIDOMSVGAnimatedString.idl | 15 ------ dom/interfaces/svg/nsIDOMSVGElement.idl | 3 +- dom/webidl/SVGAElement.webidl | 2 - dom/webidl/SVGAnimatedString.webidl | 16 ++++++ dom/webidl/SVGElement.webidl | 2 - dom/webidl/SVGFEBlendElement.webidl | 1 - dom/webidl/SVGFEColorMatrixElement.webidl | 1 - .../SVGFEComponentTransferElement.webidl | 2 - dom/webidl/SVGFECompositeElement.webidl | 1 - dom/webidl/SVGFEConvolveMatrixElement.webidl | 1 - dom/webidl/SVGFEDiffuseLightingElement.webidl | 1 - dom/webidl/SVGFEDisplacementMapElement.webidl | 1 - dom/webidl/SVGFEGaussianBlurElement.webidl | 1 - dom/webidl/SVGFEMergeNodeElement.webidl | 2 - dom/webidl/SVGFEMorphologyElement.webidl | 1 - dom/webidl/SVGFEOffsetElement.webidl | 1 - .../SVGFESpecularLightingElement.webidl | 1 - dom/webidl/SVGFETileElement.webidl | 2 - dom/webidl/SVGFETurbulenceElement.webidl | 1 - ...VGFilterPrimitiveStandardAttributes.webidl | 2 - dom/webidl/SVGSVGElement.webidl | 1 - dom/webidl/SVGURIReference.webidl | 2 - dom/webidl/WebIDL.mk | 1 + 86 files changed, 221 insertions(+), 190 deletions(-) create mode 100644 content/svg/content/src/SVGAnimatedString.cpp create mode 100644 content/svg/content/src/SVGAnimatedString.h delete mode 100644 dom/interfaces/svg/nsIDOMSVGAnimatedString.idl create mode 100644 dom/webidl/SVGAnimatedString.webidl diff --git a/content/svg/content/src/SVGAElement.cpp b/content/svg/content/src/SVGAElement.cpp index af317698947c..e493825a8c80 100644 --- a/content/svg/content/src/SVGAElement.cpp +++ b/content/svg/content/src/SVGAElement.cpp @@ -50,7 +50,7 @@ SVGAElement::SVGAElement(already_AddRefed aNodeInfo) { } -already_AddRefed +already_AddRefed SVGAElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); @@ -79,7 +79,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGAElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGAElement::Target() { return mStringAttributes[TARGET].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGAElement.h b/content/svg/content/src/SVGAElement.h index fd4dd86bda4d..36533e66c98b 100644 --- a/content/svg/content/src/SVGAElement.h +++ b/content/svg/content/src/SVGAElement.h @@ -66,8 +66,8 @@ public: bool aNotify) MOZ_OVERRIDE; // WebIDL - already_AddRefed Href(); - already_AddRefed Target(); + already_AddRefed Href(); + already_AddRefed Target(); void GetDownload(nsAString & aDownload); void SetDownload(const nsAString & aDownload, ErrorResult& rv); diff --git a/content/svg/content/src/SVGAltGlyphElement.cpp b/content/svg/content/src/SVGAltGlyphElement.cpp index 0e6a4d97e9e0..a1191165480e 100644 --- a/content/svg/content/src/SVGAltGlyphElement.cpp +++ b/content/svg/content/src/SVGAltGlyphElement.cpp @@ -36,7 +36,7 @@ SVGAltGlyphElement::SVGAltGlyphElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGAltGlyphElement) -already_AddRefed +already_AddRefed SVGAltGlyphElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGAltGlyphElement.h b/content/svg/content/src/SVGAltGlyphElement.h index 74e438b96792..286f7aae184f 100644 --- a/content/svg/content/src/SVGAltGlyphElement.h +++ b/content/svg/content/src/SVGAltGlyphElement.h @@ -33,7 +33,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed Href(); + already_AddRefed Href(); void GetGlyphRef(nsAString & aGlyphRef); void SetGlyphRef(const nsAString & aGlyphRef, ErrorResult& rv); void GetFormat(nsAString & aFormat); diff --git a/content/svg/content/src/SVGAnimatedString.cpp b/content/svg/content/src/SVGAnimatedString.cpp new file mode 100644 index 000000000000..6079d14aa0eb --- /dev/null +++ b/content/svg/content/src/SVGAnimatedString.cpp @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#include "mozilla/dom/SVGAnimatedString.h" +#include "mozilla/dom/SVGAnimatedStringBinding.h" + +namespace mozilla { +namespace dom { + +JSObject* +SVGAnimatedString::WrapObject(JSContext* aCx, + JS::Handle aScope) +{ + return SVGAnimatedStringBinding::Wrap(aCx, aScope, this); +} + +} // namespace dom +} // namespace mozilla diff --git a/content/svg/content/src/SVGAnimatedString.h b/content/svg/content/src/SVGAnimatedString.h new file mode 100644 index 000000000000..690930f06b1f --- /dev/null +++ b/content/svg/content/src/SVGAnimatedString.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef mozilla_dom_SVGAnimatedString_h +#define mozilla_dom_SVGAnimatedString_h + +#include "nsSVGElement.h" + +namespace mozilla { +namespace dom { + +class SVGAnimatedString : public nsISupports, + public nsWrapperCache +{ +public: + SVGAnimatedString(nsSVGElement* aSVGElement) + : mSVGElement(aSVGElement) + { + SetIsDOMBinding(); + } + + virtual JSObject* WrapObject(JSContext* aCx, + JS::Handle aScope) MOZ_OVERRIDE; + + // WebIDL + nsSVGElement* GetParentObject() const + { + return mSVGElement; + } + + virtual void GetBaseVal(nsAString& aResult) = 0; + virtual void SetBaseVal(const nsAString& aValue) = 0; + virtual void GetAnimVal(nsAString& aResult) = 0; + + nsRefPtr mSVGElement; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_SVGAnimatedString_h diff --git a/content/svg/content/src/SVGFEBlendElement.cpp b/content/svg/content/src/SVGFEBlendElement.cpp index 5a664a81ad49..1acea503df7b 100644 --- a/content/svg/content/src/SVGFEBlendElement.cpp +++ b/content/svg/content/src/SVGFEBlendElement.cpp @@ -50,13 +50,13 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEBlendElement) //---------------------------------------------------------------------- // nsIDOMSVGFEBlendElement methods -already_AddRefed +already_AddRefed SVGFEBlendElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); } -already_AddRefed +already_AddRefed SVGFEBlendElement::In2() { return mStringAttributes[IN2].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEBlendElement.h b/content/svg/content/src/SVGFEBlendElement.h index 1a6bfb27a2b0..265a0d3f13d8 100644 --- a/content/svg/content/src/SVGFEBlendElement.h +++ b/content/svg/content/src/SVGFEBlendElement.h @@ -48,8 +48,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); - already_AddRefed In2(); + already_AddRefed In1(); + already_AddRefed In2(); already_AddRefed Mode(); protected: diff --git a/content/svg/content/src/SVGFEColorMatrixElement.cpp b/content/svg/content/src/SVGFEColorMatrixElement.cpp index 4572f00e8105..ecb5a945d691 100644 --- a/content/svg/content/src/SVGFEColorMatrixElement.cpp +++ b/content/svg/content/src/SVGFEColorMatrixElement.cpp @@ -57,7 +57,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEColorMatrixElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEColorMatrixElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEColorMatrixElement.h b/content/svg/content/src/SVGFEColorMatrixElement.h index 9b66f680aa8c..56271c06b259 100644 --- a/content/svg/content/src/SVGFEColorMatrixElement.h +++ b/content/svg/content/src/SVGFEColorMatrixElement.h @@ -49,7 +49,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed Type(); already_AddRefed Values(); diff --git a/content/svg/content/src/SVGFEComponentTransferElement.cpp b/content/svg/content/src/SVGFEComponentTransferElement.cpp index 0e4f85f5c0cc..c559684fd10e 100644 --- a/content/svg/content/src/SVGFEComponentTransferElement.cpp +++ b/content/svg/content/src/SVGFEComponentTransferElement.cpp @@ -30,7 +30,7 @@ nsSVGElement::StringInfo SVGFEComponentTransferElement::sStringInfo[2] = NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEComponentTransferElement) -already_AddRefed +already_AddRefed SVGFEComponentTransferElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEComponentTransferElement.h b/content/svg/content/src/SVGFEComponentTransferElement.h index 4bc4808fadca..7b91ff996a44 100644 --- a/content/svg/content/src/SVGFEComponentTransferElement.h +++ b/content/svg/content/src/SVGFEComponentTransferElement.h @@ -42,7 +42,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); protected: virtual bool OperatesOnPremultipledAlpha(int32_t) MOZ_OVERRIDE { return false; } diff --git a/content/svg/content/src/SVGFECompositeElement.cpp b/content/svg/content/src/SVGFECompositeElement.cpp index ce94195cdc93..b2353602fdd9 100644 --- a/content/svg/content/src/SVGFECompositeElement.cpp +++ b/content/svg/content/src/SVGFECompositeElement.cpp @@ -55,13 +55,13 @@ nsSVGElement::StringInfo SVGFECompositeElement::sStringInfo[3] = NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFECompositeElement) -already_AddRefed +already_AddRefed SVGFECompositeElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); } -already_AddRefed +already_AddRefed SVGFECompositeElement::In2() { return mStringAttributes[IN2].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFECompositeElement.h b/content/svg/content/src/SVGFECompositeElement.h index db5efc07155f..7ad13bf4c392 100644 --- a/content/svg/content/src/SVGFECompositeElement.h +++ b/content/svg/content/src/SVGFECompositeElement.h @@ -55,8 +55,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); - already_AddRefed In2(); + already_AddRefed In1(); + already_AddRefed In2(); already_AddRefed Operator(); already_AddRefed K1(); already_AddRefed K2(); diff --git a/content/svg/content/src/SVGFEConvolveMatrixElement.cpp b/content/svg/content/src/SVGFEConvolveMatrixElement.cpp index 922f8d855a43..757e4e48eabb 100644 --- a/content/svg/content/src/SVGFEConvolveMatrixElement.cpp +++ b/content/svg/content/src/SVGFEConvolveMatrixElement.cpp @@ -85,7 +85,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEConvolveMatrixElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEConvolveMatrixElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEConvolveMatrixElement.h b/content/svg/content/src/SVGFEConvolveMatrixElement.h index eff647abc361..89a53fe68390 100644 --- a/content/svg/content/src/SVGFEConvolveMatrixElement.h +++ b/content/svg/content/src/SVGFEConvolveMatrixElement.h @@ -58,7 +58,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed OrderX(); already_AddRefed OrderY(); already_AddRefed KernelMatrix(); diff --git a/content/svg/content/src/SVGFEDiffuseLightingElement.cpp b/content/svg/content/src/SVGFEDiffuseLightingElement.cpp index 25d052fc1e06..f8900170aacc 100644 --- a/content/svg/content/src/SVGFEDiffuseLightingElement.cpp +++ b/content/svg/content/src/SVGFEDiffuseLightingElement.cpp @@ -25,7 +25,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEDiffuseLightingElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEDiffuseLightingElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEDiffuseLightingElement.h b/content/svg/content/src/SVGFEDiffuseLightingElement.h index a7793b5dafb0..8994f4854788 100644 --- a/content/svg/content/src/SVGFEDiffuseLightingElement.h +++ b/content/svg/content/src/SVGFEDiffuseLightingElement.h @@ -35,7 +35,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed SurfaceScale(); already_AddRefed DiffuseConstant(); already_AddRefed KernelUnitLengthX(); diff --git a/content/svg/content/src/SVGFEDisplacementMapElement.cpp b/content/svg/content/src/SVGFEDisplacementMapElement.cpp index 5ea9feccc8cc..42f58a1976ee 100644 --- a/content/svg/content/src/SVGFEDisplacementMapElement.cpp +++ b/content/svg/content/src/SVGFEDisplacementMapElement.cpp @@ -65,13 +65,13 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEDisplacementMapElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEDisplacementMapElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); } -already_AddRefed +already_AddRefed SVGFEDisplacementMapElement::In2() { return mStringAttributes[IN2].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEDisplacementMapElement.h b/content/svg/content/src/SVGFEDisplacementMapElement.h index 942ca417fd66..372d2f343e58 100644 --- a/content/svg/content/src/SVGFEDisplacementMapElement.h +++ b/content/svg/content/src/SVGFEDisplacementMapElement.h @@ -49,8 +49,8 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); - already_AddRefed In2(); + already_AddRefed In1(); + already_AddRefed In2(); already_AddRefed Scale(); already_AddRefed XChannelSelector(); already_AddRefed YChannelSelector(); diff --git a/content/svg/content/src/SVGFEGaussianBlurElement.cpp b/content/svg/content/src/SVGFEGaussianBlurElement.cpp index 175da8bd564b..5bfe9ea0e692 100644 --- a/content/svg/content/src/SVGFEGaussianBlurElement.cpp +++ b/content/svg/content/src/SVGFEGaussianBlurElement.cpp @@ -37,7 +37,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEGaussianBlurElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEGaussianBlurElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEGaussianBlurElement.h b/content/svg/content/src/SVGFEGaussianBlurElement.h index ab4afef7e726..27a36a5f08e1 100644 --- a/content/svg/content/src/SVGFEGaussianBlurElement.h +++ b/content/svg/content/src/SVGFEGaussianBlurElement.h @@ -50,7 +50,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed StdDeviationX(); already_AddRefed StdDeviationY(); void SetStdDeviation(float stdDeviationX, float stdDeviationY); diff --git a/content/svg/content/src/SVGFEImageElement.cpp b/content/svg/content/src/SVGFEImageElement.cpp index 92d575679de8..2e5033a4fb43 100644 --- a/content/svg/content/src/SVGFEImageElement.cpp +++ b/content/svg/content/src/SVGFEImageElement.cpp @@ -175,7 +175,7 @@ SVGFEImageElement::IntrinsicState() const NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEImageElement) -already_AddRefed +already_AddRefed SVGFEImageElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEImageElement.h b/content/svg/content/src/SVGFEImageElement.h index 55633f1f1dc5..00a777953b20 100644 --- a/content/svg/content/src/SVGFEImageElement.h +++ b/content/svg/content/src/SVGFEImageElement.h @@ -65,7 +65,7 @@ public: void MaybeLoadSVGImage(); // WebIDL - already_AddRefed Href(); + already_AddRefed Href(); already_AddRefed PreserveAspectRatio(); private: diff --git a/content/svg/content/src/SVGFEMergeNodeElement.cpp b/content/svg/content/src/SVGFEMergeNodeElement.cpp index 29077d88cffc..019df46ff1f9 100644 --- a/content/svg/content/src/SVGFEMergeNodeElement.cpp +++ b/content/svg/content/src/SVGFEMergeNodeElement.cpp @@ -37,7 +37,7 @@ SVGFEMergeNodeElement::AttributeAffectsRendering(int32_t aNameSpaceID, return aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::in; } -already_AddRefed +already_AddRefed SVGFEMergeNodeElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEMergeNodeElement.h b/content/svg/content/src/SVGFEMergeNodeElement.h index 43ba3431556a..4fab9ec7ffef 100644 --- a/content/svg/content/src/SVGFEMergeNodeElement.h +++ b/content/svg/content/src/SVGFEMergeNodeElement.h @@ -37,7 +37,7 @@ public: const nsSVGString* GetIn1() { return &mStringAttributes[IN1]; } // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); protected: virtual StringAttributesInfo GetStringInfo() MOZ_OVERRIDE; diff --git a/content/svg/content/src/SVGFEMorphologyElement.cpp b/content/svg/content/src/SVGFEMorphologyElement.cpp index bf3ab4102d89..ad3273a37f84 100644 --- a/content/svg/content/src/SVGFEMorphologyElement.cpp +++ b/content/svg/content/src/SVGFEMorphologyElement.cpp @@ -58,7 +58,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEMorphologyElement) //---------------------------------------------------------------------- // SVGFEMorphologyElement methods -already_AddRefed +already_AddRefed SVGFEMorphologyElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEMorphologyElement.h b/content/svg/content/src/SVGFEMorphologyElement.h index a7bc8156a20d..929bb3bea956 100644 --- a/content/svg/content/src/SVGFEMorphologyElement.h +++ b/content/svg/content/src/SVGFEMorphologyElement.h @@ -50,7 +50,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed Operator(); already_AddRefed RadiusX(); already_AddRefed RadiusY(); diff --git a/content/svg/content/src/SVGFEOffsetElement.cpp b/content/svg/content/src/SVGFEOffsetElement.cpp index 68693d79a2d6..a22b64c65cbe 100644 --- a/content/svg/content/src/SVGFEOffsetElement.cpp +++ b/content/svg/content/src/SVGFEOffsetElement.cpp @@ -39,7 +39,7 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEOffsetElement) //---------------------------------------------------------------------- -already_AddRefed +already_AddRefed SVGFEOffsetElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFEOffsetElement.h b/content/svg/content/src/SVGFEOffsetElement.h index 8ba21e1488f3..a04ffdbcba6b 100644 --- a/content/svg/content/src/SVGFEOffsetElement.h +++ b/content/svg/content/src/SVGFEOffsetElement.h @@ -49,7 +49,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed Dx(); already_AddRefed Dy(); diff --git a/content/svg/content/src/SVGFESpecularLightingElement.cpp b/content/svg/content/src/SVGFESpecularLightingElement.cpp index 0c87cd070e3c..ceabd9b42d73 100644 --- a/content/svg/content/src/SVGFESpecularLightingElement.cpp +++ b/content/svg/content/src/SVGFESpecularLightingElement.cpp @@ -23,7 +23,7 @@ SVGFESpecularLightingElement::WrapNode(JSContext* aCx, JS::Handle aSc NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFESpecularLightingElement) -already_AddRefed +already_AddRefed SVGFESpecularLightingElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFESpecularLightingElement.h b/content/svg/content/src/SVGFESpecularLightingElement.h index 2aa2f07051cd..14a883329222 100644 --- a/content/svg/content/src/SVGFESpecularLightingElement.h +++ b/content/svg/content/src/SVGFESpecularLightingElement.h @@ -41,7 +41,7 @@ public: int32_t aNameSpaceID, nsIAtom* aAttribute) const; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); already_AddRefed SurfaceScale(); already_AddRefed SpecularConstant(); already_AddRefed SpecularExponent(); diff --git a/content/svg/content/src/SVGFETileElement.cpp b/content/svg/content/src/SVGFETileElement.cpp index c96dfc3c7b87..00ab316dfed1 100644 --- a/content/svg/content/src/SVGFETileElement.cpp +++ b/content/svg/content/src/SVGFETileElement.cpp @@ -31,7 +31,7 @@ nsSVGElement::StringInfo SVGFETileElement::sStringInfo[2] = NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETileElement) -already_AddRefed +already_AddRefed SVGFETileElement::In1() { return mStringAttributes[IN1].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFETileElement.h b/content/svg/content/src/SVGFETileElement.h index 89b08e93ed62..fe3a962b6b43 100644 --- a/content/svg/content/src/SVGFETileElement.h +++ b/content/svg/content/src/SVGFETileElement.h @@ -49,7 +49,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; // WebIDL - already_AddRefed In1(); + already_AddRefed In1(); protected: virtual StringAttributesInfo GetStringInfo() MOZ_OVERRIDE; diff --git a/content/svg/content/src/SVGFilterElement.cpp b/content/svg/content/src/SVGFilterElement.cpp index 49b1efaf0948..f0254e2befe3 100644 --- a/content/svg/content/src/SVGFilterElement.cpp +++ b/content/svg/content/src/SVGFilterElement.cpp @@ -125,7 +125,7 @@ SVGFilterElement::SetFilterRes(uint32_t filterResX, uint32_t filterResY) mIntegerPairAttributes[FILTERRES].SetBaseValues(filterResX, filterResY, this); } -already_AddRefed +already_AddRefed SVGFilterElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGFilterElement.h b/content/svg/content/src/SVGFilterElement.h index 553e0cea4478..0cbb7c7c438c 100644 --- a/content/svg/content/src/SVGFilterElement.h +++ b/content/svg/content/src/SVGFilterElement.h @@ -57,7 +57,7 @@ public: already_AddRefed FilterResX(); already_AddRefed FilterResY(); void SetFilterRes(uint32_t filterResX, uint32_t filterResY); - already_AddRefed Href(); + already_AddRefed Href(); protected: diff --git a/content/svg/content/src/SVGGradientElement.cpp b/content/svg/content/src/SVGGradientElement.cpp index d965507fa5f9..a796efa95982 100644 --- a/content/svg/content/src/SVGGradientElement.cpp +++ b/content/svg/content/src/SVGGradientElement.cpp @@ -93,7 +93,7 @@ SVGGradientElement::SpreadMethod() return mEnumAttributes[SPREADMETHOD].ToDOMAnimatedEnum(this); } -already_AddRefed +already_AddRefed SVGGradientElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGGradientElement.h b/content/svg/content/src/SVGGradientElement.h index 42e1779cfb60..e4c9f39780a0 100644 --- a/content/svg/content/src/SVGGradientElement.h +++ b/content/svg/content/src/SVGGradientElement.h @@ -62,7 +62,7 @@ public: already_AddRefed GradientUnits(); already_AddRefed GradientTransform(); already_AddRefed SpreadMethod(); - already_AddRefed Href(); + already_AddRefed Href(); protected: virtual EnumAttributesInfo GetEnumInfo() MOZ_OVERRIDE; diff --git a/content/svg/content/src/SVGImageElement.cpp b/content/svg/content/src/SVGImageElement.cpp index 7f4fa807644e..6514938b08fe 100644 --- a/content/svg/content/src/SVGImageElement.cpp +++ b/content/svg/content/src/SVGImageElement.cpp @@ -103,7 +103,7 @@ SVGImageElement::PreserveAspectRatio() return ratio.forget(); } -already_AddRefed +already_AddRefed SVGImageElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGImageElement.h b/content/svg/content/src/SVGImageElement.h index 7b56e141baff..ea68f156846e 100644 --- a/content/svg/content/src/SVGImageElement.h +++ b/content/svg/content/src/SVGImageElement.h @@ -73,7 +73,7 @@ public: already_AddRefed Width(); already_AddRefed Height(); already_AddRefed PreserveAspectRatio(); - already_AddRefed Href(); + already_AddRefed Href(); protected: nsresult LoadSVGImage(bool aForce, bool aNotify); diff --git a/content/svg/content/src/SVGMPathElement.cpp b/content/svg/content/src/SVGMPathElement.cpp index f8c0696cb7f1..dff72b6d26bf 100644 --- a/content/svg/content/src/SVGMPathElement.cpp +++ b/content/svg/content/src/SVGMPathElement.cpp @@ -78,7 +78,7 @@ SVGMPathElement::~SVGMPathElement() NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGMPathElement) -already_AddRefed +already_AddRefed SVGMPathElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGMPathElement.h b/content/svg/content/src/SVGMPathElement.h index 927f66de2baa..a59ff405fe4f 100644 --- a/content/svg/content/src/SVGMPathElement.h +++ b/content/svg/content/src/SVGMPathElement.h @@ -62,7 +62,7 @@ public: SVGPathElement* GetReferencedPath(); // WebIDL - already_AddRefed Href(); + already_AddRefed Href(); protected: class PathReference : public nsReferencedElement { diff --git a/content/svg/content/src/SVGPatternElement.cpp b/content/svg/content/src/SVGPatternElement.cpp index a36b90f5bbfa..4a0f64225e09 100644 --- a/content/svg/content/src/SVGPatternElement.cpp +++ b/content/svg/content/src/SVGPatternElement.cpp @@ -125,7 +125,7 @@ SVGPatternElement::Height() return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); } -already_AddRefed +already_AddRefed SVGPatternElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGPatternElement.h b/content/svg/content/src/SVGPatternElement.h index 0b5e552b77c5..6f605aa0b7b6 100644 --- a/content/svg/content/src/SVGPatternElement.h +++ b/content/svg/content/src/SVGPatternElement.h @@ -63,7 +63,7 @@ public: already_AddRefed Y(); already_AddRefed Width(); already_AddRefed Height(); - already_AddRefed Href(); + already_AddRefed Href(); protected: diff --git a/content/svg/content/src/SVGScriptElement.cpp b/content/svg/content/src/SVGScriptElement.cpp index 8281b12f99c8..a624fd3b0fda 100644 --- a/content/svg/content/src/SVGScriptElement.cpp +++ b/content/svg/content/src/SVGScriptElement.cpp @@ -98,7 +98,7 @@ SVGScriptElement::SetCrossOrigin(const nsAString & aOrigin, ErrorResult& rv) rv = SetAttr(kNameSpaceID_None, nsGkAtoms::crossorigin, aOrigin, true); } -already_AddRefed +already_AddRefed SVGScriptElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGScriptElement.h b/content/svg/content/src/SVGScriptElement.h index dda32d5f83fc..e5eb908b66b8 100644 --- a/content/svg/content/src/SVGScriptElement.h +++ b/content/svg/content/src/SVGScriptElement.h @@ -69,7 +69,7 @@ public: void SetType(const nsAString & aType, ErrorResult& rv); void GetCrossOrigin(nsAString & aOrigin); void SetCrossOrigin(const nsAString & aOrigin, ErrorResult& rv); - already_AddRefed Href(); + already_AddRefed Href(); protected: virtual StringAttributesInfo GetStringInfo() MOZ_OVERRIDE; diff --git a/content/svg/content/src/SVGTextPathElement.cpp b/content/svg/content/src/SVGTextPathElement.cpp index f13b06476af4..6497655d1812 100644 --- a/content/svg/content/src/SVGTextPathElement.cpp +++ b/content/svg/content/src/SVGTextPathElement.cpp @@ -70,7 +70,7 @@ SVGTextPathElement::SVGTextPathElement(already_AddRefed aNodeInfo) NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGTextPathElement) -already_AddRefed +already_AddRefed SVGTextPathElement::Href() { return mStringAttributes[HREF].ToDOMAnimatedString(this); diff --git a/content/svg/content/src/SVGTextPathElement.h b/content/svg/content/src/SVGTextPathElement.h index 475a6c8ff67c..07db029c0b0a 100644 --- a/content/svg/content/src/SVGTextPathElement.h +++ b/content/svg/content/src/SVGTextPathElement.h @@ -55,7 +55,7 @@ public: already_AddRefed StartOffset(); already_AddRefed Method(); already_AddRefed Spacing(); - already_AddRefed Href(); + already_AddRefed Href(); protected: diff --git a/content/svg/content/src/SVGUseElement.cpp b/content/svg/content/src/SVGUseElement.cpp index 6e09169ffa9b..481b0b696def 100644 --- a/content/svg/content/src/SVGUseElement.cpp +++ b/content/svg/content/src/SVGUseElement.cpp @@ -115,12 +115,10 @@ SVGUseElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const return NS_FAILED(rv1) ? rv1 : rv2; } -already_AddRefed +already_AddRefed SVGUseElement::Href() { - nsCOMPtr href; - mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this); - return href.forget(); + return mStringAttributes[HREF].ToDOMAnimatedString(this); } //---------------------------------------------------------------------- diff --git a/content/svg/content/src/SVGUseElement.h b/content/svg/content/src/SVGUseElement.h index fbf088fe4563..504c22475fa2 100644 --- a/content/svg/content/src/SVGUseElement.h +++ b/content/svg/content/src/SVGUseElement.h @@ -70,7 +70,7 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE; // WebIDL - already_AddRefed Href(); + already_AddRefed Href(); already_AddRefed X(); already_AddRefed Y(); already_AddRefed Width(); diff --git a/content/svg/content/src/moz.build b/content/svg/content/src/moz.build index 9f8d7ecbb728..aa2875463202 100644 --- a/content/svg/content/src/moz.build +++ b/content/svg/content/src/moz.build @@ -25,6 +25,7 @@ EXPORTS.mozilla.dom += [ 'SVGAnimatedBoolean.h', 'SVGAnimatedLength.h', 'SVGAnimatedRect.h', + 'SVGAnimatedString.h', 'SVGAnimatedTransformList.h', 'SVGAnimationElement.h', 'SVGCircleElement.h', @@ -122,6 +123,7 @@ CPP_SOURCES += [ 'SVGAnimatedPointList.cpp', 'SVGAnimatedPreserveAspectRatio.cpp', 'SVGAnimatedRect.cpp', + 'SVGAnimatedString.cpp', 'SVGAnimatedTransformList.cpp', 'SVGAnimationElement.cpp', 'SVGAttrValueWrapper.cpp', diff --git a/content/svg/content/src/nsSVGClass.cpp b/content/svg/content/src/nsSVGClass.cpp index b231ce0e7c52..a1a79b15e387 100644 --- a/content/svg/content/src/nsSVGClass.cpp +++ b/content/svg/content/src/nsSVGClass.cpp @@ -7,22 +7,54 @@ #include "nsSVGElement.h" #include "nsSMILValue.h" #include "SMILStringType.h" +#include "mozilla/dom/SVGAnimatedString.h" using namespace mozilla; +using namespace mozilla::dom; -NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGClass::DOMAnimatedString, mSVGElement) +struct DOMAnimatedString MOZ_FINAL : public SVGAnimatedString +{ + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMAnimatedString) -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGClass::DOMAnimatedString) -NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGClass::DOMAnimatedString) + DOMAnimatedString(nsSVGClass* aVal, nsSVGElement* aSVGElement) + : SVGAnimatedString(aSVGElement) + , mVal(aVal) + {} -DOMCI_DATA(SVGAnimatedClass, nsSVGClass::DOMAnimatedString) + nsSVGClass* mVal; // kept alive because it belongs to content -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGClass::DOMAnimatedString) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString) + void GetBaseVal(nsAString& aResult) MOZ_OVERRIDE + { + mVal->GetBaseValue(aResult, mSVGElement); + } + + void SetBaseVal(const nsAString& aValue) MOZ_OVERRIDE + { + mVal->SetBaseValue(aValue, mSVGElement, true); + } + + void GetAnimVal(nsAString& aResult) MOZ_OVERRIDE; +}; + +NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMAnimatedString, mSVGElement) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMAnimatedString) +NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMAnimatedString) + + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMAnimatedString) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedString) NS_INTERFACE_MAP_END +already_AddRefed +nsSVGClass::ToDOMAnimatedString(nsSVGElement* aSVGElement) +{ + nsRefPtr result = new DOMAnimatedString(this, aSVGElement); + return result.forget(); +} + /* Implementation */ void @@ -72,12 +104,11 @@ nsSVGClass::SetAnimValue(const nsAString& aValue, nsSVGElement *aSVGElement) aSVGElement->DidAnimateClass(); } -NS_IMETHODIMP -nsSVGClass::DOMAnimatedString::GetAnimVal(nsAString& aResult) -{ +void +DOMAnimatedString::GetAnimVal(nsAString& aResult) +{ mSVGElement->FlushAnimations(); mVal->GetAnimValue(aResult, mSVGElement); - return NS_OK; } nsISMILAttr* diff --git a/content/svg/content/src/nsSVGClass.h b/content/svg/content/src/nsSVGClass.h index 91d0e31cb8fa..28f940de86e0 100644 --- a/content/svg/content/src/nsSVGClass.h +++ b/content/svg/content/src/nsSVGClass.h @@ -9,13 +9,18 @@ #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsError.h" -#include "nsIDOMSVGAnimatedString.h" #include "nsISMILAttr.h" #include "nsString.h" #include "mozilla/Attributes.h" class nsSVGElement; +namespace mozilla { +namespace dom { +class SVGAnimatedString; +} +} + class nsSVGClass { @@ -34,18 +39,8 @@ public: bool IsAnimated() const { return !!mAnimVal; } - already_AddRefed - ToDOMAnimatedString(nsSVGElement* aSVGElement) - { - nsRefPtr result = new DOMAnimatedString(this, aSVGElement); - return result.forget(); - } - nsresult ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult, - nsSVGElement *aSVGElement) - { - *aResult = ToDOMAnimatedString(aSVGElement).get(); - return NS_OK; - } + already_AddRefed + ToDOMAnimatedString(nsSVGElement* aSVGElement); // Returns a new nsISMILAttr object that the caller must delete nsISMILAttr* ToSMILAttr(nsSVGElement *aSVGElement); @@ -55,24 +50,6 @@ private: nsAutoPtr mAnimVal; public: - struct DOMAnimatedString MOZ_FINAL : public nsIDOMSVGAnimatedString - { - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString) - - DOMAnimatedString(nsSVGClass *aVal, nsSVGElement *aSVGElement) - : mVal(aVal), mSVGElement(aSVGElement) {} - - nsSVGClass* mVal; // kept alive because it belongs to content - nsRefPtr mSVGElement; - - NS_IMETHOD GetBaseVal(nsAString& aResult) MOZ_OVERRIDE - { mVal->GetBaseValue(aResult, mSVGElement); return NS_OK; } - NS_IMETHOD SetBaseVal(const nsAString& aValue) MOZ_OVERRIDE - { mVal->SetBaseValue(aValue, mSVGElement, true); return NS_OK; } - - NS_IMETHOD GetAnimVal(nsAString& aResult) MOZ_OVERRIDE; - }; struct SMILString : public nsISMILAttr { public: diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 66057ee35ff9..7a98fb5d90e2 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -93,9 +93,9 @@ nsSVGElement::WrapNode(JSContext *aCx, JS::Handle aScope) //---------------------------------------------------------------------- -/* readonly attribute nsIDOMSVGAnimatedString className; */ +/* readonly attribute SVGAnimatedString className; */ NS_IMETHODIMP -nsSVGElement::GetClassName(nsIDOMSVGAnimatedString** aClassName) +nsSVGElement::GetClassName(nsISupports** aClassName) { *aClassName = ClassName().get(); return NS_OK; @@ -1142,7 +1142,7 @@ nsSVGElement::GetViewportElement() return SVGContentUtils::GetNearestViewportElement(this); } -already_AddRefed +already_AddRefed nsSVGElement::ClassName() { return mClassAttribute.ToDOMAnimatedString(this); diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index f6ddcf9de176..95cc207fbbdb 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -306,7 +306,7 @@ public: // WebIDL mozilla::dom::SVGSVGElement* GetOwnerSVGElement(mozilla::ErrorResult& rv); nsSVGElement* GetViewportElement(); - already_AddRefed ClassName(); + already_AddRefed ClassName(); already_AddRefed GetPresentationAttribute(const nsAString& aName, mozilla::ErrorResult& rv); protected: virtual JSObject* WrapNode(JSContext *cx, diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index 4575b629f13d..e928223f04dc 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -273,7 +273,7 @@ nsSVGFE::Height() return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); } -already_AddRefed +already_AddRefed nsSVGFE::Result() { return GetResultImageName().ToDOMAnimatedString(this); diff --git a/content/svg/content/src/nsSVGFilters.h b/content/svg/content/src/nsSVGFilters.h index 03cf27ffc11e..88e6647cb36d 100644 --- a/content/svg/content/src/nsSVGFilters.h +++ b/content/svg/content/src/nsSVGFilters.h @@ -207,7 +207,7 @@ public: already_AddRefed Y(); already_AddRefed Width(); already_AddRefed Height(); - already_AddRefed Result(); + already_AddRefed Result(); protected: virtual bool OperatesOnPremultipledAlpha(int32_t) { return true; } diff --git a/content/svg/content/src/nsSVGString.cpp b/content/svg/content/src/nsSVGString.cpp index b017b729c0a2..a5232ce5b429 100644 --- a/content/svg/content/src/nsSVGString.cpp +++ b/content/svg/content/src/nsSVGString.cpp @@ -9,18 +9,16 @@ #include "SMILStringType.h" using namespace mozilla; +using namespace mozilla::dom; -NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString, mSVGElement) +NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(nsSVGString::DOMAnimatedString, mSVGElement) NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGString::DOMAnimatedString) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGString::DOMAnimatedString) -DOMCI_DATA(SVGAnimatedString, nsSVGString::DOMAnimatedString) - NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString) - NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedString) NS_INTERFACE_MAP_END static inline @@ -78,15 +76,7 @@ nsSVGString::SetAnimValue(const nsAString& aValue, nsSVGElement *aSVGElement) } } -nsresult -nsSVGString::ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult, - nsSVGElement *aSVGElement) -{ - *aResult = ToDOMAnimatedString(aSVGElement).get(); - return NS_OK; -} - -already_AddRefed +already_AddRefed nsSVGString::ToDOMAnimatedString(nsSVGElement* aSVGElement) { nsRefPtr domAnimatedString = diff --git a/content/svg/content/src/nsSVGString.h b/content/svg/content/src/nsSVGString.h index f5feabca031d..5f00f403abaf 100644 --- a/content/svg/content/src/nsSVGString.h +++ b/content/svg/content/src/nsSVGString.h @@ -7,9 +7,9 @@ #define __NS_SVGSTRING_H__ #include "nsError.h" -#include "nsIDOMSVGAnimatedString.h" #include "nsSVGElement.h" #include "mozilla/Attributes.h" +#include "mozilla/dom/SVGAnimatedString.h" class nsSVGString { @@ -38,9 +38,7 @@ public: bool IsExplicitlySet() const { return !!mAnimVal || mIsBaseSet; } - nsresult ToDOMAnimatedString(nsIDOMSVGAnimatedString **aResult, - nsSVGElement *aSVGElement); - already_AddRefed + already_AddRefed ToDOMAnimatedString(nsSVGElement* aSVGElement); // Returns a new nsISMILAttr object that the caller must delete @@ -53,27 +51,34 @@ private: bool mIsBaseSet; public: - struct DOMAnimatedString MOZ_FINAL : public nsIDOMSVGAnimatedString + struct DOMAnimatedString MOZ_FINAL : public mozilla::dom::SVGAnimatedString { NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMAnimatedString) + + DOMAnimatedString(nsSVGString* aVal, nsSVGElement* aSVGElement) + : mozilla::dom::SVGAnimatedString(aSVGElement) + , mVal(aVal) + {} - DOMAnimatedString(nsSVGString *aVal, nsSVGElement *aSVGElement) - : mVal(aVal), mSVGElement(aSVGElement) {} virtual ~DOMAnimatedString(); nsSVGString* mVal; // kept alive because it belongs to content - nsRefPtr mSVGElement; - NS_IMETHOD GetBaseVal(nsAString & aResult) MOZ_OVERRIDE - { mVal->GetBaseValue(aResult, mSVGElement); return NS_OK; } - NS_IMETHOD SetBaseVal(const nsAString & aValue) MOZ_OVERRIDE - { mVal->SetBaseValue(aValue, mSVGElement, true); return NS_OK; } + void GetBaseVal(nsAString & aResult) MOZ_OVERRIDE + { + mVal->GetBaseValue(aResult, mSVGElement); + } - NS_IMETHOD GetAnimVal(nsAString & aResult) MOZ_OVERRIDE - { + void SetBaseVal(const nsAString & aValue) MOZ_OVERRIDE + { + mVal->SetBaseValue(aValue, mSVGElement, true); + } + + void GetAnimVal(nsAString & aResult) MOZ_OVERRIDE + { mSVGElement->FlushAnimations(); - mVal->GetAnimValue(aResult, mSVGElement); return NS_OK; + mVal->GetAnimValue(aResult, mSVGElement); } }; diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d6cc34708dd5..e2f716968fbd 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -191,7 +191,6 @@ #include "nsIDOMSVGAnimatedEnum.h" #include "nsIDOMSVGAnimatedInteger.h" #include "nsIDOMSVGAnimatedNumber.h" -#include "nsIDOMSVGAnimatedString.h" #include "nsIDOMSVGLength.h" #include "nsIDOMSVGNumber.h" @@ -618,8 +617,6 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGAnimatedNumber, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(SVGAnimatedString, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGLength, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGNumber, nsDOMGenericSH, @@ -1639,10 +1636,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedNumber) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(SVGAnimatedString, nsIDOMSVGAnimatedString) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedString) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(SVGLength, nsIDOMSVGLength) DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLength) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index d5096effce71..a20699dbc657 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -87,7 +87,6 @@ DOMCI_CLASS(CSSSupportsRule) DOMCI_CLASS(SVGAnimatedEnumeration) DOMCI_CLASS(SVGAnimatedInteger) DOMCI_CLASS(SVGAnimatedNumber) -DOMCI_CLASS(SVGAnimatedString) DOMCI_CLASS(SVGLength) DOMCI_CLASS(SVGNumber) diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 0b30e8cef631..ab13f158ff74 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1657,7 +1657,6 @@ addExternalIface('Selection', nativeType='nsISelection') addExternalIface('StyleSheetList') addExternalIface('SVGAnimatedEnumeration', headerFile='nsIDOMSVGAnimatedEnum.h') addExternalIface('SVGAnimatedNumber') -addExternalIface('SVGAnimatedString') addExternalIface('SVGLength') addExternalIface('SVGNumber') addExternalIface('TouchList', headerFile='nsIDOMTouchEvent.h') diff --git a/dom/interfaces/svg/moz.build b/dom/interfaces/svg/moz.build index 1b34a9d7167f..b3808823edcb 100644 --- a/dom/interfaces/svg/moz.build +++ b/dom/interfaces/svg/moz.build @@ -9,7 +9,6 @@ XPIDL_SOURCES += [ 'nsIDOMSVGAnimatedInteger.idl', 'nsIDOMSVGAnimatedLength.idl', 'nsIDOMSVGAnimatedNumber.idl', - 'nsIDOMSVGAnimatedString.idl', 'nsIDOMSVGElement.idl', 'nsIDOMSVGLength.idl', 'nsIDOMSVGNumber.idl', diff --git a/dom/interfaces/svg/nsIDOMSVGAnimatedString.idl b/dom/interfaces/svg/nsIDOMSVGAnimatedString.idl deleted file mode 100644 index a1c1d420423b..000000000000 --- a/dom/interfaces/svg/nsIDOMSVGAnimatedString.idl +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "domstubs.idl" - -[scriptable, uuid(36f18f12-61a9-4529-8fa9-30050bd6ac00)] -interface nsIDOMSVGAnimatedString - : nsISupports -{ - attribute DOMString baseVal; - // raises DOMException on setting - readonly attribute DOMString animVal; -}; diff --git a/dom/interfaces/svg/nsIDOMSVGElement.idl b/dom/interfaces/svg/nsIDOMSVGElement.idl index da783684931d..4a2a996d8be1 100644 --- a/dom/interfaces/svg/nsIDOMSVGElement.idl +++ b/dom/interfaces/svg/nsIDOMSVGElement.idl @@ -5,7 +5,6 @@ #include "nsIDOMElement.idl" -interface nsIDOMSVGAnimatedString; interface nsIDOMCSSStyleDeclaration; interface nsIDOMCSSValue; @@ -18,7 +17,7 @@ interface nsIDOMSVGElement : nsIDOMElement readonly attribute nsIDOMSVGElement ownerSVGElement; readonly attribute nsIDOMSVGElement viewportElement; - readonly attribute nsIDOMSVGAnimatedString className; + readonly attribute nsISupports className; readonly attribute nsIDOMCSSStyleDeclaration style; // Not implemented diff --git a/dom/webidl/SVGAElement.webidl b/dom/webidl/SVGAElement.webidl index 0de7c5561b46..f15866911397 100644 --- a/dom/webidl/SVGAElement.webidl +++ b/dom/webidl/SVGAElement.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - interface SVGAElement : SVGGraphicsElement { readonly attribute SVGAnimatedString target; diff --git a/dom/webidl/SVGAnimatedString.webidl b/dom/webidl/SVGAnimatedString.webidl new file mode 100644 index 000000000000..eaf3773d0e2a --- /dev/null +++ b/dom/webidl/SVGAnimatedString.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * The origin of this IDL file is + * http://www.w3.org/TR/SVG2/ + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface SVGAnimatedString { + attribute DOMString baseVal; + readonly attribute DOMString animVal; +}; diff --git a/dom/webidl/SVGElement.webidl b/dom/webidl/SVGElement.webidl index 2e66feef34cb..9243744e9261 100644 --- a/dom/webidl/SVGElement.webidl +++ b/dom/webidl/SVGElement.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - interface SVGElement : Element { attribute DOMString id; /* [SetterThrows] diff --git a/dom/webidl/SVGFEBlendElement.webidl b/dom/webidl/SVGFEBlendElement.webidl index 03b9a196ffda..bf65478efda1 100644 --- a/dom/webidl/SVGFEBlendElement.webidl +++ b/dom/webidl/SVGFEBlendElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedEnumeration; -interface SVGAnimatedString; interface SVGFEBlendElement : SVGElement { diff --git a/dom/webidl/SVGFEColorMatrixElement.webidl b/dom/webidl/SVGFEColorMatrixElement.webidl index 87a70ec96389..717e36d89a2f 100644 --- a/dom/webidl/SVGFEColorMatrixElement.webidl +++ b/dom/webidl/SVGFEColorMatrixElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedEnumeration; -interface SVGAnimatedString; interface SVGFEColorMatrixElement : SVGElement { diff --git a/dom/webidl/SVGFEComponentTransferElement.webidl b/dom/webidl/SVGFEComponentTransferElement.webidl index 2f4dfa0017f8..8a774f447bdc 100644 --- a/dom/webidl/SVGFEComponentTransferElement.webidl +++ b/dom/webidl/SVGFEComponentTransferElement.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - interface SVGFEComponentTransferElement : SVGElement { readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFECompositeElement.webidl b/dom/webidl/SVGFECompositeElement.webidl index b7c47d27925b..1d9d0f4736ac 100644 --- a/dom/webidl/SVGFECompositeElement.webidl +++ b/dom/webidl/SVGFECompositeElement.webidl @@ -12,7 +12,6 @@ interface SVGAnimatedEnumeration; interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFECompositeElement : SVGElement { diff --git a/dom/webidl/SVGFEConvolveMatrixElement.webidl b/dom/webidl/SVGFEConvolveMatrixElement.webidl index 7dc57b7f5926..ad45fc9f108a 100644 --- a/dom/webidl/SVGFEConvolveMatrixElement.webidl +++ b/dom/webidl/SVGFEConvolveMatrixElement.webidl @@ -12,7 +12,6 @@ interface SVGAnimatedEnumeration; interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEConvolveMatrixElement : SVGElement { diff --git a/dom/webidl/SVGFEDiffuseLightingElement.webidl b/dom/webidl/SVGFEDiffuseLightingElement.webidl index 3ca202ca0bb7..176950c3a1f9 100644 --- a/dom/webidl/SVGFEDiffuseLightingElement.webidl +++ b/dom/webidl/SVGFEDiffuseLightingElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEDiffuseLightingElement : SVGElement { readonly attribute SVGAnimatedString in1; diff --git a/dom/webidl/SVGFEDisplacementMapElement.webidl b/dom/webidl/SVGFEDisplacementMapElement.webidl index de31a8ea4c3f..ae2353eb1dec 100644 --- a/dom/webidl/SVGFEDisplacementMapElement.webidl +++ b/dom/webidl/SVGFEDisplacementMapElement.webidl @@ -12,7 +12,6 @@ interface SVGAnimatedEnumeration; interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEDisplacementMapElement : SVGElement { diff --git a/dom/webidl/SVGFEGaussianBlurElement.webidl b/dom/webidl/SVGFEGaussianBlurElement.webidl index 042ea24e5cbb..dfd932ed3657 100644 --- a/dom/webidl/SVGFEGaussianBlurElement.webidl +++ b/dom/webidl/SVGFEGaussianBlurElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEGaussianBlurElement : SVGElement { readonly attribute SVGAnimatedString in1; diff --git a/dom/webidl/SVGFEMergeNodeElement.webidl b/dom/webidl/SVGFEMergeNodeElement.webidl index a74d367a650c..bec3e5931e09 100644 --- a/dom/webidl/SVGFEMergeNodeElement.webidl +++ b/dom/webidl/SVGFEMergeNodeElement.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - interface SVGFEMergeNodeElement : SVGElement { readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFEMorphologyElement.webidl b/dom/webidl/SVGFEMorphologyElement.webidl index 28c27730cbed..2928c41a3c37 100644 --- a/dom/webidl/SVGFEMorphologyElement.webidl +++ b/dom/webidl/SVGFEMorphologyElement.webidl @@ -12,7 +12,6 @@ interface SVGAnimatedEnumeration; interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEMorphologyElement : SVGElement { diff --git a/dom/webidl/SVGFEOffsetElement.webidl b/dom/webidl/SVGFEOffsetElement.webidl index 128d7e569f95..039cf5c86d5d 100644 --- a/dom/webidl/SVGFEOffsetElement.webidl +++ b/dom/webidl/SVGFEOffsetElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFEOffsetElement : SVGElement { readonly attribute SVGAnimatedString in1; diff --git a/dom/webidl/SVGFESpecularLightingElement.webidl b/dom/webidl/SVGFESpecularLightingElement.webidl index 97086a87b1b9..4f885dc8a5a9 100644 --- a/dom/webidl/SVGFESpecularLightingElement.webidl +++ b/dom/webidl/SVGFESpecularLightingElement.webidl @@ -11,7 +11,6 @@ */ interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFESpecularLightingElement : SVGElement { readonly attribute SVGAnimatedString in1; diff --git a/dom/webidl/SVGFETileElement.webidl b/dom/webidl/SVGFETileElement.webidl index 511fce6ed787..d414279bd1a9 100644 --- a/dom/webidl/SVGFETileElement.webidl +++ b/dom/webidl/SVGFETileElement.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - interface SVGFETileElement : SVGElement { readonly attribute SVGAnimatedString in1; }; diff --git a/dom/webidl/SVGFETurbulenceElement.webidl b/dom/webidl/SVGFETurbulenceElement.webidl index dc531aa6dcbe..521286908b01 100644 --- a/dom/webidl/SVGFETurbulenceElement.webidl +++ b/dom/webidl/SVGFETurbulenceElement.webidl @@ -13,7 +13,6 @@ interface SVGAnimatedEnumeration; interface SVGAnimatedInteger; interface SVGAnimatedNumber; -interface SVGAnimatedString; interface SVGFETurbulenceElement : SVGElement { diff --git a/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl b/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl index b3d040d758cd..9dc94c38bdc2 100644 --- a/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl +++ b/dom/webidl/SVGFilterPrimitiveStandardAttributes.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - [NoInterfaceObject] interface SVGFilterPrimitiveStandardAttributes { readonly attribute SVGAnimatedLength x; diff --git a/dom/webidl/SVGSVGElement.webidl b/dom/webidl/SVGSVGElement.webidl index 1c23e8b9309d..51095a67576f 100644 --- a/dom/webidl/SVGSVGElement.webidl +++ b/dom/webidl/SVGSVGElement.webidl @@ -10,7 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; interface SVGViewSpec; interface SVGSVGElement : SVGGraphicsElement { diff --git a/dom/webidl/SVGURIReference.webidl b/dom/webidl/SVGURIReference.webidl index 29426b3acb96..672349a03c9b 100644 --- a/dom/webidl/SVGURIReference.webidl +++ b/dom/webidl/SVGURIReference.webidl @@ -10,8 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGAnimatedString; - [NoInterfaceObject] interface SVGURIReference { readonly attribute SVGAnimatedString href; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index e6a2573d2a00..acb04107519f 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -231,6 +231,7 @@ webidl_files = \ SVGAnimatedPoints.webidl \ SVGAnimatedPreserveAspectRatio.webidl \ SVGAnimatedRect.webidl \ + SVGAnimatedString.webidl \ SVGAnimatedTransformList.webidl \ SVGAnimateElement.webidl \ SVGAnimateMotionElement.webidl \ From b82bc8ad7208f080e91b9736ef3c4a863a37d5be Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Thu, 13 Jun 2013 15:54:30 -0700 Subject: [PATCH 010/615] Bug 882959 - Initialize app.geo.reportdata pref to avoid annoying nsIPrefBranch.getCharPref() exceptions. r=blassey --- mobile/android/app/mobile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 55b93e775af9..4414365f9cef 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -388,6 +388,7 @@ pref("privacy.item.syncAccount", true); // enable geo pref("geo.enabled", true); +pref("app.geo.reportdata", 0); // content sink control -- controls responsiveness during page load // see https://bugzilla.mozilla.org/show_bug.cgi?id=481566#c9 From 2b3690735eedb93e40e7a7f3ecd0ed684a859e4e Mon Sep 17 00:00:00 2001 From: Julian Reschke Date: Fri, 14 Jun 2013 15:52:36 -0700 Subject: [PATCH 011/615] Bug 875615: re-enable RFC2047 decoding (disable bug 601933) until we have telemetry r=jduell --- netwerk/mime/nsMIMEHeaderParamImpl.cpp | 5 ++++- netwerk/test/unit/test_MIME_params.js | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/netwerk/mime/nsMIMEHeaderParamImpl.cpp b/netwerk/mime/nsMIMEHeaderParamImpl.cpp index a25016e8a8ed..86ea1fa9d4db 100644 --- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp +++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp @@ -94,7 +94,10 @@ nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal, nsAutoCString str1; rv = internalDecodeParameter(med, charset.get(), nullptr, false, - aDecoding == MIME_FIELD_ENCODING, str1); + // was aDecoding == MIME_FIELD_ENCODING + // see bug 875615 + true, + str1); NS_ENSURE_SUCCESS(rv, rv); if (!aFallbackCharset.IsEmpty()) diff --git a/netwerk/test/unit/test_MIME_params.js b/netwerk/test/unit/test_MIME_params.js index 801630c629a9..f8a4b6b50940 100644 --- a/netwerk/test/unit/test_MIME_params.js +++ b/netwerk/test/unit/test_MIME_params.js @@ -266,11 +266,11 @@ var tests = [ // Bug 601933: RFC 2047 does not apply to parameters (at least in HTTP) ["attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=", "attachment", "foo-\u00e4.html", - "attachment", "=?ISO-8859-1?Q?foo-=E4.html?="], + /* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */], ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"", "attachment", "foo-\u00e4.html", - "attachment", "=?ISO-8859-1?Q?foo-=E4.html?="], + /* "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" */], // format sent by GMail as of 2012-07-23 (5987 overrides 2047) ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"; filename*=UTF-8''5987", From 7fd6f5b4f165070dfb5d504f065affafadbde2e5 Mon Sep 17 00:00:00 2001 From: Mike Shal Date: Thu, 13 Jun 2013 13:49:01 -0400 Subject: [PATCH 012/615] Bug 882738 - Remove SRCS_IN_OBJDIR from Makefile.in; r=joey From a071ba8cffdd4584b3cd31eae207e5b76b9e9c95 Mon Sep 17 00:00:00 2001 --- accessible/public/ia2/Makefile.in | 2 -- accessible/public/msaa/Makefile.in | 2 -- media/mtransport/build/Makefile.in | 1 - media/mtransport/standalone/Makefile.in | 2 -- uriloader/exthandler/Makefile.in | 1 - xpcom/glue/standalone/Makefile.in | 2 -- xpcom/glue/standalone/staticruntime/Makefile.in | 2 -- 7 files changed, 12 deletions(-) diff --git a/accessible/public/ia2/Makefile.in b/accessible/public/ia2/Makefile.in index 7454229bcfd7..b6f3d15fa670 100644 --- a/accessible/public/ia2/Makefile.in +++ b/accessible/public/ia2/Makefile.in @@ -20,8 +20,6 @@ GARBAGE += $(MIDL_GENERATED_FILES) FORCE_SHARED_LIB = 1 -SRCS_IN_OBJDIR = 1 - # Please keep this list in sync with the moz.build file until the rest of this # Makefile is ported over. MIDL_INTERFACES = \ diff --git a/accessible/public/msaa/Makefile.in b/accessible/public/msaa/Makefile.in index c03fa5b873cf..9a1d37338bf5 100644 --- a/accessible/public/msaa/Makefile.in +++ b/accessible/public/msaa/Makefile.in @@ -18,8 +18,6 @@ GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c FORCE_SHARED_LIB = 1 -SRCS_IN_OBJDIR = 1 - CSRCS = \ dlldata.c \ ISimpleDOMNode_p.c \ diff --git a/media/mtransport/build/Makefile.in b/media/mtransport/build/Makefile.in index 60ad3881ebf1..35d761840ddc 100644 --- a/media/mtransport/build/Makefile.in +++ b/media/mtransport/build/Makefile.in @@ -19,7 +19,6 @@ endif LIBXUL_LIBRARY=1 -SRCS_IN_OBJDIR = 1 ifndef _MSC_VER FAIL_ON_WARNINGS = 1 endif # !_MSC_VER diff --git a/media/mtransport/standalone/Makefile.in b/media/mtransport/standalone/Makefile.in index 064dd4563909..803098b9da40 100644 --- a/media/mtransport/standalone/Makefile.in +++ b/media/mtransport/standalone/Makefile.in @@ -18,8 +18,6 @@ ifeq (WINNT,$(OS_TARGET)) VISIBILITY_FLAGS = endif -SRCS_IN_OBJDIR = 1 - # Make a copy into the local directory for dual compilation export:: $(MTRANSPORT_CPPSRCS) $(INSTALL) $^ . diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in index eaf8aad0c82e..24cb887c6938 100644 --- a/uriloader/exthandler/Makefile.in +++ b/uriloader/exthandler/Makefile.in @@ -85,7 +85,6 @@ EXTRA_COMPONENTS = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 -SRCS_IN_OBJDIR = 1 include $(topsrcdir)/config/config.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk diff --git a/xpcom/glue/standalone/Makefile.in b/xpcom/glue/standalone/Makefile.in index b876ef3656f7..db18267cd1cf 100644 --- a/xpcom/glue/standalone/Makefile.in +++ b/xpcom/glue/standalone/Makefile.in @@ -35,8 +35,6 @@ STL_FLAGS = GARBAGE += $(XPCOM_GLUE_SRC_LCPPSRCS) -SRCS_IN_OBJDIR = 1 - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER diff --git a/xpcom/glue/standalone/staticruntime/Makefile.in b/xpcom/glue/standalone/staticruntime/Makefile.in index a1f0289fbd4a..5254e893eaad 100644 --- a/xpcom/glue/standalone/staticruntime/Makefile.in +++ b/xpcom/glue/standalone/staticruntime/Makefile.in @@ -34,8 +34,6 @@ STL_FLAGS = GARBAGE += $(XPCOM_GLUE_SRC_LCPPSRCS) -SRCS_IN_OBJDIR = 1 - include $(topsrcdir)/config/rules.mk ifdef _MSC_VER From 834467796d466ba7520ba2b8dae546da26d297ae Mon Sep 17 00:00:00 2001 From: Jonathan Wilde Date: Fri, 14 Jun 2013 16:05:09 -0700 Subject: [PATCH 013/615] Bug 811406 - Work - Trim http:// and single trailing slash from location text in the Firefox app bar. r=fryn --- .../base/content/bindings/autocomplete.xml | 7 + browser/metro/base/content/browser-ui.js | 124 ++++++++++++++++++ browser/metro/profile/metro.js | 1 + browser/metro/theme/browser.css | 6 + 4 files changed, 138 insertions(+) diff --git a/browser/metro/base/content/bindings/autocomplete.xml b/browser/metro/base/content/bindings/autocomplete.xml index 11b17c07a159..f9a888b95d13 100644 --- a/browser/metro/base/content/bindings/autocomplete.xml +++ b/browser/metro/base/content/bindings/autocomplete.xml @@ -46,6 +46,13 @@ ]]> + + + + + diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 0d217cae7798..49bd7e893e5e 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -98,7 +98,10 @@ var BrowserUI = { Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false); Services.prefs.addObserver("browser.urlbar.formatting.enabled", this, false); + Services.prefs.addObserver("browser.urlbar.trimURLs", this, false); Services.obs.addObserver(this, "metro_viewstate_changed", false); + + this._edit.inputField.controllers.insertControllerAt(0, this._copyCutURIController); // Init core UI modules ContextUI.init(); @@ -564,6 +567,9 @@ var BrowserUI = { case "browser.urlbar.formatting.enabled": this._formattingEnabled = Services.prefs.getBookPref(aData); break; + case "browser.urlbar.trimURLs": + this._mayTrimURLs = Services.prefs.getBoolPref(aData); + break; } break; case "metro_viewstate_changed": @@ -654,11 +660,120 @@ var BrowserUI = { Elements.urlbarState.setAttribute("mode", "view"); }, + _trimURL: function _trimURL(aURL) { + // This function must not modify the given URL such that calling + // nsIURIFixup::createFixupURI with the result will produce a different URI. + return aURL /* remove single trailing slash for http/https/ftp URLs */ + .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1") + /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */ + .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1"); + }, + + trimURL: function trimURL(aURL) { + return this.mayTrimURLs ? this._trimURL(aURL) : aURL; + }, + _setURI: function _setURI(aURL) { this._edit.value = aURL; this.lastKnownGoodURL = aURL; }, + _getSelectedURIForClipboard: function _getSelectedURIForClipboard() { + // Grab the actual input field's value, not our value, which could include moz-action: + let inputVal = this._edit.inputField.value; + let selectedVal = inputVal.substring(this._edit.selectionStart, this._edit.electionEnd); + + // If the selection doesn't start at the beginning or doesn't span the full domain or + // the URL bar is modified, nothing else to do here. + if (this._edit.selectionStart > 0 || this._edit.valueIsTyped) + return selectedVal; + // The selection doesn't span the full domain if it doesn't contain a slash and is + // followed by some character other than a slash. + if (!selectedVal.contains("/")) { + let remainder = inputVal.replace(selectedVal, ""); + if (remainder != "" && remainder[0] != "/") + return selectedVal; + } + + let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup); + + let uri; + try { + uri = uriFixup.createFixupURI(inputVal, Ci.nsIURIFixup.FIXUP_FLAG_USE_UTF8); + } catch (e) {} + if (!uri) + return selectedVal; + + // Only copy exposable URIs + try { + uri = uriFixup.createExposableURI(uri); + } catch (ex) {} + + // If the entire URL is selected, just use the actual loaded URI. + if (inputVal == selectedVal) { + // ... but only if isn't a javascript: or data: URI, since those + // are hard to read when encoded + if (!uri.schemeIs("javascript") && !uri.schemeIs("data")) { + // Parentheses are known to confuse third-party applications (bug 458565). + selectedVal = uri.spec.replace(/[()]/g, function (c) escape(c)); + } + + return selectedVal; + } + + // Just the beginning of the URL is selected, check for a trimmed value + let spec = uri.spec; + let trimmedSpec = this.trimURL(spec); + if (spec != trimmedSpec) { + // Prepend the portion that trimURL removed from the beginning. + // This assumes trimURL will only truncate the URL at + // the beginning or end (or both). + let trimmedSegments = spec.split(trimmedSpec); + selectedVal = trimmedSegments[0] + selectedVal; + } + + return selectedVal; + }, + + _copyCutURIController: { + doCommand: function(aCommand) { + let urlbar = BrowserUI._edit; + let val = BrowserUI._getSelectedURIForClipboard(); + if (!val) + return; + + if (aCommand == "cmd_cut" && this.isCommandEnabled(aCommand)) { + let start = urlbar.selectionStart; + let end = urlbar.selectionEnd; + urlbar.inputField.value = urlbar.inputField.value.substring(0, start) + + urlbar.inputField.value.substring(end); + urlbar.selectionStart = urlbar.selectionEnd = start; + } + + Cc["@mozilla.org/widget/clipboardhelper;1"] + .getService(Ci.nsIClipboardHelper) + .copyString(val, document); + }, + + supportsCommand: function(aCommand) { + switch (aCommand) { + case "cmd_copy": + case "cmd_cut": + return true; + } + return false; + }, + + isCommandEnabled: function(aCommand) { + let urlbar = BrowserUI._edit; + return this.supportsCommand(aCommand) && + (aCommand != "cmd_cut" || !urlbar.readOnly) && + urlbar.selectionStart < urlbar.selectionEnd; + }, + + onEvent: function(aEventName) {} + }, + _urlbarClicked: function _urlbarClicked() { // If the urlbar is not already focused, focus it and select the contents. if (Elements.urlbarState.getAttribute("mode") != "edit") @@ -1039,6 +1154,15 @@ var BrowserUI = { return this._formattingEnabled; }, + _mayTrimURLs: null, + + get mayTrimURLs() { + if (this._mayTrimURLs === null) { + this._mayTrimURLs = Services.prefs.getBoolPref("browser.urlbar.trimURLs"); + } + return this._mayTrimURLs; + }, + supportsCommand : function(cmd) { var isSupported = false; switch (cmd) { diff --git a/browser/metro/profile/metro.js b/browser/metro/profile/metro.js index 988538f01980..821487976a04 100644 --- a/browser/metro/profile/metro.js +++ b/browser/metro/profile/metro.js @@ -261,6 +261,7 @@ pref("places.favicons.optimizeToDimension", 25); // various and sundry awesomebar prefs (should remove/re-evaluate // these once bug 447900 is fixed) +pref("browser.urlbar.trimURLs", true); pref("browser.urlbar.formatting.enabled", true); pref("browser.urlbar.clickSelectsAll", true); pref("browser.urlbar.doubleClickSelectsAll", true); diff --git a/browser/metro/theme/browser.css b/browser/metro/theme/browser.css index fe61d5cecb62..c791912f49b6 100644 --- a/browser/metro/theme/browser.css +++ b/browser/metro/theme/browser.css @@ -308,6 +308,12 @@ documenttab[selected] .documenttab-selection { padding: 0 !important; } +#urlbar-edit :invalid { + /* Hide error glow around the address bar that shows by default + * when URLs are made invalid by trmming. */ + box-shadow: none !important; +} + /* Combined stop-reload button */ #tool-reload { list-style-image: url("chrome://browser/skin/images/reload.png"); From aca88101add10b1bed87ee7924b2f9f547841752 Mon Sep 17 00:00:00 2001 From: Nick Alexander Date: Fri, 14 Jun 2013 16:17:42 -0700 Subject: [PATCH 014/615] Bug 878079 - Clarify |make install| message when no Android devices are connected. r=ted DONTBUILD since NPOTB --- mobile/android/build.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/android/build.mk b/mobile/android/build.mk index 885d5a1ede4e..69f4004d5b14 100644 --- a/mobile/android/build.mk +++ b/mobile/android/build.mk @@ -22,6 +22,11 @@ export ANDROID_SERIAL else # Determine if there's more than one device connected android_devices=$(filter device,$(shell $(ANDROID_PLATFORM_TOOLS)/adb devices)) +ifeq ($(android_devices),) +install:: + @echo "No devices are connected. Connect a device or start an emulator." + @exit 1 +else ifneq ($(android_devices),device) install:: @echo "Multiple devices are connected. Define ANDROID_SERIAL to specify the install target." @@ -29,6 +34,7 @@ install:: @exit 1 endif endif +endif install:: $(ANDROID_PLATFORM_TOOLS)/adb install -r $(DIST)/$(PKG_PATH)$(PKG_BASENAME).apk From cb9b136b223a8873b7bec07336c55b89e8c5330e Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 14 Jun 2013 14:24:10 -0700 Subject: [PATCH 015/615] Bug 883381 - SpiderMonkey does not yet support C++11; r=Waldo --HG-- extra : rebase_source : 009192000c3e9f6229c53694aab23e508e661f52 --- js/src/configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/configure.in b/js/src/configure.in index f0d62942e626..5f1ade086fe1 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2337,8 +2337,8 @@ AC_LANG_CPLUSPLUS if test "$GNU_CXX"; then _SAVE_CXXFLAGS=$CXXFLAGS - CXXFLAGS="$CXXFLAGS -std=gnu++0x" - USE_CXX11=1 + CXXFLAGS="$CXXFLAGS" + USE_CXX11= AC_CACHE_CHECK(for gcc c++0x headers bug without rtti, ac_cv_cxx0x_headers_bug, From 341606e8658cde1d87c8cd3190e1fff82472a96c Mon Sep 17 00:00:00 2001 From: Frank Yan Date: Fri, 14 Jun 2013 15:41:15 -0700 Subject: [PATCH 016/615] Bug 883415 - Clean up orbit throbber stylesheet. r=jwilde --- browser/metro/theme/cssthrobber.css | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/browser/metro/theme/cssthrobber.css b/browser/metro/theme/cssthrobber.css index fb0fd9c63dee..63b699b207aa 100644 --- a/browser/metro/theme/cssthrobber.css +++ b/browser/metro/theme/cssthrobber.css @@ -47,15 +47,15 @@ border-radius: 5px; position: absolute; background: #0095dd; - left:0px; - top:0px; + left: 0; + top: 0; } @keyframes orbit { 0% { opacity: 1; - z-index:99; + z-index: 99; transform: rotate(180deg); animation-timing-function: ease-out; } @@ -64,39 +64,34 @@ opacity: 1; transform: rotate(300deg); animation-timing-function: linear; - origin:0%; } 30% { opacity: 1; - transform:rotate(410deg); + transform: rotate(410deg); animation-timing-function: ease-in-out; - origin:7%; } 39% { opacity: 1; transform: rotate(645deg); animation-timing-function: linear; - origin:30%; } 70% { opacity: 1; transform: rotate(770deg); animation-timing-function: ease-out; - origin:39%; } 75% { opacity: 1; transform: rotate(900deg); animation-timing-function: ease-out; - origin:70%; } 76%, 100% { opacity: 0; - transform:rotate(900deg); + transform: rotate(900deg); } } From c2dfa6e0694704df5115adec07eefabf14bd986a Mon Sep 17 00:00:00 2001 From: Jonathan Wilde Date: Thu, 13 Jun 2013 13:51:46 -0700 Subject: [PATCH 017/615] Bug 774870 - Work - Display unicode characters properly in the location field of the Firefox app bar. r=fryn --HG-- extra : amend_source : ae1b8c97ed1af70edd0992d3ea75a55645e0bf98 --- browser/metro/base/content/browser-ui.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 49bd7e893e5e..1d21706378fe 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -243,11 +243,20 @@ var BrowserUI = { getDisplayURI: function(browser) { let uri = browser.currentURI; + let spec = uri.spec; + try { - uri = gURIFixup.createExposableURI(uri); + spec = gURIFixup.createExposableURI(uri).spec; } catch (ex) {} - return uri.spec; + try { + let charset = browser.characterSet; + let textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"]. + getService(Ci.nsITextToSubURI); + spec = textToSubURI.unEscapeNonAsciiURI(charset, spec); + } catch (ex) {} + + return spec; }, /** From 81228503c632772187e77c4194d6e93a9ddf1f76 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 14 Jun 2013 17:47:56 -0400 Subject: [PATCH 018/615] Bug 883392 - clean up TabChild.h's #includes; r=smaug --- dom/ipc/TabChild.cpp | 8 ++++++++ dom/ipc/TabChild.h | 15 ++------------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index da3d31c9a897..29df3e6d5ed0 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1020,6 +1020,14 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener, return NS_OK; } +already_AddRefed +TabChild::GetDOMWindowUtils() +{ + nsCOMPtr window = do_GetInterface(mWebNav); + nsCOMPtr utils = do_GetInterface(window); + return utils.forget(); +} + static nsInterfaceHashtable, nsIDialogParamBlock> gActiveDialogs; NS_IMETHODIMP diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 5b50a5fdc7b1..22f9d9ffe5f5 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -23,10 +23,7 @@ #include "nsIDOMEventListener.h" #include "nsIInterfaceRequestor.h" #include "nsIWindowProvider.h" -#include "nsIXPCScriptable.h" -#include "nsIClassInfo.h" #include "jsapi.h" -#include "nsIXPConnect.h" #include "nsIDOMWindow.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" @@ -34,17 +31,13 @@ #include "nsIDocument.h" #include "nsNetUtil.h" #include "nsFrameMessageManager.h" -#include "nsIScriptContext.h" #include "nsIWebProgressListener.h" #include "nsDOMEventTargetHelper.h" #include "nsIDialogCreator.h" #include "nsIDialogParamBlock.h" -#include "nsIDOMWindowUtils.h" #include "nsIPresShell.h" #include "nsIPrincipal.h" #include "nsIScriptObjectPrincipal.h" -#include "nsIScriptContext.h" -#include "nsPIDOMWindow.h" #include "nsWeakReference.h" #include "nsITabChild.h" #include "mozilla/Attributes.h" @@ -54,6 +47,7 @@ struct gfxMatrix; class nsICachedFileDescriptorListener; +class nsIDOMWindowUtils; namespace mozilla { namespace layout { @@ -422,12 +416,7 @@ private: bool* aWindowIsNew, nsIDOMWindow** aReturn); - nsIDOMWindowUtils* GetDOMWindowUtils() - { - nsCOMPtr window = do_GetInterface(mWebNav); - nsCOMPtr utils = do_GetInterface(window); - return utils; - } + already_AddRefed GetDOMWindowUtils(); class CachedFileDescriptorInfo; class CachedFileDescriptorCallbackRunnable; From 6a83f0d559b2b717db4a61b414c0301173429d81 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Fri, 14 Jun 2013 19:01:45 -0400 Subject: [PATCH 019/615] Bug 883423 - mark even more reftests as needs-focus; r=dholbert --- editor/reftests/reftest.list | 20 ++++++++++---------- layout/reftests/selection/reftest.list | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/editor/reftests/reftest.list b/editor/reftests/reftest.list index b4e83e59220c..ae4fd7b18d15 100644 --- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -98,13 +98,13 @@ skip-if(Android||B2G) needs-focus == 462758-grabbers-resizers.html 462758-grabbe == 388980-1.html 388980-1-ref.html needs-focus == spellcheck-superscript-1.html spellcheck-superscript-1-ref.html skip-if(B2G) fails-if(Android) needs-focus != spellcheck-superscript-2.html spellcheck-superscript-2-ref.html # bug 783658 -== 824080-1.html 824080-1-ref.html -== 824080-2.html 824080-2-ref.html -== 824080-3.html 824080-3-ref.html -!= 824080-2.html 824080-3.html -== 824080-4.html 824080-4-ref.html -== 824080-5.html 824080-5-ref.html -!= 824080-4.html 824080-5.html -== 824080-6.html 824080-6-ref.html -== 824080-7.html 824080-7-ref.html -!= 824080-6.html 824080-7.html +needs-focus == 824080-1.html 824080-1-ref.html +needs-focus == 824080-2.html 824080-2-ref.html +needs-focus == 824080-3.html 824080-3-ref.html +needs-focus != 824080-2.html 824080-3.html +needs-focus == 824080-4.html 824080-4-ref.html +needs-focus == 824080-5.html 824080-5-ref.html +needs-focus != 824080-4.html 824080-5.html +needs-focus == 824080-6.html 824080-6-ref.html +needs-focus == 824080-7.html 824080-7-ref.html +needs-focus != 824080-6.html 824080-7.html diff --git a/layout/reftests/selection/reftest.list b/layout/reftests/selection/reftest.list index dee8ed4c07f5..5b3427b855a9 100644 --- a/layout/reftests/selection/reftest.list +++ b/layout/reftests/selection/reftest.list @@ -27,8 +27,8 @@ # these 3 random-if(Android) are a difference of Native & Xul, see bug 739714 random-if(Android||B2G) needs-focus != pseudo-element-of-native-anonymous.html pseudo-element-of-native-anonymous-ref.html # bug 676641 # These tests uses Highlight and HighlightText color keywords, they are not same as text selection color on Mac. -random-if(Android||B2G) fails-if(cocoaWidget) == non-themed-widget.html non-themed-widget-ref.html # bug 773482 -random-if(Android||B2G) fails-if(cocoaWidget) == themed-widget.html themed-widget-ref.html +random-if(Android||B2G) fails-if(cocoaWidget) needs-focus == non-themed-widget.html non-themed-widget-ref.html # bug 773482 +random-if(Android||B2G) fails-if(cocoaWidget) needs-focus == themed-widget.html themed-widget-ref.html == addrange-1.html addrange-ref.html == addrange-2.html addrange-ref.html == splitText-normalize.html splitText-normalize-ref.html From ada1c6e81d6e6c0ba9d035b4acebec078c878b7a Mon Sep 17 00:00:00 2001 From: Gary Kwong Date: Fri, 14 Jun 2013 17:00:49 -0700 Subject: [PATCH 020/615] Backout rev 18c1fd169792 for causing issues with the fuzzers. r=luke in-person --- js/src/builtin/ParallelArray.js | 37 +++++++++--------- js/src/ion/IonBuilder.cpp | 34 ++++++----------- js/src/ion/IonBuilder.h | 18 +-------- js/src/ion/MCallOptimize.cpp | 31 +--------------- js/src/ion/MIR.h | 15 ++------ js/src/jscntxt.h | 3 -- js/src/vm/SelfHosting.cpp | 66 ++++----------------------------- 7 files changed, 41 insertions(+), 163 deletions(-) diff --git a/js/src/builtin/ParallelArray.js b/js/src/builtin/ParallelArray.js index 0a2db707446f..98213378053a 100644 --- a/js/src/builtin/ParallelArray.js +++ b/js/src/builtin/ParallelArray.js @@ -377,7 +377,7 @@ function ParallelArrayMap(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = UnsafeGetImmutableElement(self.shape, 0); + var length = self.shape[0]; var buffer = NewDenseArray(length); parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc @@ -432,7 +432,7 @@ function ParallelArrayReduce(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = UnsafeGetImmutableElement(self.shape, 0); + var length = self.shape[0]; if (length === 0) ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY); @@ -519,7 +519,7 @@ function ParallelArrayScan(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = UnsafeGetImmutableElement(self.shape, 0); + var length = self.shape[0]; if (length === 0) ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY); @@ -726,7 +726,7 @@ function ParallelArrayScatter(targets, defaultValue, conflictFunc, length, mode) var self = this; if (length === undefined) - length = UnsafeGetImmutableElement(self.shape, 0); + length = self.shape[0]; // The Divide-Scatter-Vector strategy: // 1. Slice |targets| array of indices ("scatter-vector") into N @@ -977,7 +977,7 @@ function ParallelArrayFilter(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = UnsafeGetImmutableElement(self.shape, 0); + var length = self.shape[0]; parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc if (ShouldForceSequential()) @@ -1151,11 +1151,6 @@ function ParallelArrayFlatten() { function ParallelArrayGet1(i) { if (i === undefined) return undefined; - - // We could use UnsafeGetImmutableElement here, but I am not doing - // so (for the moment) since using the default path enables - // bounds-check hoisting, which is (currently) not possible - // otherwise. return this.buffer[this.offset + i]; } @@ -1163,25 +1158,27 @@ function ParallelArrayGet1(i) { * Specialized variant of get() for two-dimensional case */ function ParallelArrayGet2(x, y) { - var xDimension = UnsafeGetImmutableElement(this.shape, 0); - var yDimension = UnsafeGetImmutableElement(this.shape, 1); - if (x === undefined || TO_INT32(x) !== x || x >= xDimension) + var xDimension = this.shape[0]; + var yDimension = this.shape[1]; + if (x === undefined) + return undefined; + if (x >= xDimension) return undefined; if (y === undefined) return NewParallelArray(ParallelArrayView, [yDimension], this.buffer, this.offset + x * yDimension); - if (TO_INT32(y) !== y || y >= yDimension) + if (y >= yDimension) return undefined; var offset = y + x * yDimension; - return UnsafeGetImmutableElement(this.buffer, this.offset + offset); + return this.buffer[this.offset + offset]; } /** * Specialized variant of get() for three-dimensional case */ function ParallelArrayGet3(x, y, z) { - var xDimension = UnsafeGetImmutableElement(this.shape, 0); - var yDimension = UnsafeGetImmutableElement(this.shape, 1); - var zDimension = UnsafeGetImmutableElement(this.shape, 2); + var xDimension = this.shape[0]; + var yDimension = this.shape[1]; + var zDimension = this.shape[2]; if (x === undefined) return undefined; if (x >= xDimension) @@ -1197,7 +1194,7 @@ function ParallelArrayGet3(x, y, z) { if (z >= zDimension) return undefined; var offset = z + y*zDimension + x * yDimension * zDimension; - return UnsafeGetImmutableElement(this.buffer, this.offset + offset); + return this.buffer[this.offset + offset]; } /** @@ -1231,7 +1228,7 @@ function ParallelArrayGetN(...coords) { /** The length property yields the outermost dimension */ function ParallelArrayLength() { - return UnsafeGetImmutableElement(this.shape, 0); + return this.shape[0]; } function ParallelArrayToString() { diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index defa2286ded3..2dcd2f9b22fe 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -6266,11 +6266,8 @@ IonBuilder::jsop_getelem() if (ElementAccessIsDenseNative(obj, index)) { // Don't generate a fast path if there have been bounds check failures // and this access might be on a sparse property. - if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_) { - MDefinition *id = current->pop(); - MDefinition *obj = current->pop(); - return jsop_getelem_dense(GetElem_Normal, obj, id); - } + if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_) + return jsop_getelem_dense(); } int arrayType = TypedArray::TYPE_MAX; @@ -6335,8 +6332,11 @@ IonBuilder::jsop_getelem() } bool -IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefinition *id) +IonBuilder::jsop_getelem_dense() { + MDefinition *id = current->pop(); + MDefinition *obj = current->pop(); + types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc); if (JSOp(*pc) == JSOP_CALLELEM && !id->mightBeType(MIRType_String) && types->noConstraints()) { @@ -6353,7 +6353,6 @@ IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefiniti // undefined values have been observed at this access site and the access // cannot hit another indexed property on the object or its prototypes. bool readOutOfBounds = - safety == GetElem_Normal && types->hasType(types::Type::UndefinedType()) && !ElementAccessHasExtraIndexedProperty(cx, obj); @@ -6390,6 +6389,9 @@ IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefiniti if (loadDouble) elements = addConvertElementsToDoubles(elements); + MInitializedLength *initLength = MInitializedLength::New(elements); + current->add(initLength); + MInstruction *load; if (!readOutOfBounds) { @@ -6397,28 +6399,14 @@ IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefiniti // in-bounds elements, and the array is packed or its holes are not // read. This is the best case: we can separate the bounds check for // hoisting. - switch (safety) { - case GetElem_Normal: { - MInitializedLength *initLength = MInitializedLength::New(elements); - current->add(initLength); - id = addBoundsCheck(id, initLength); - break; - } + id = addBoundsCheck(id, initLength); - case GetElem_Unsafe: break; - case GetElem_UnsafeImmutable: break; - } - - bool knownImmutable = (safety == GetElem_UnsafeImmutable); - load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble, - knownImmutable); + load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble); current->add(load); } else { // This load may return undefined, so assume that we *can* read holes, // or that we can read out-of-bounds accesses. In this case, the bounds // check is part of the opcode. - MInitializedLength *initLength = MInitializedLength::New(elements); - current->add(initLength); load = MLoadElementHole::New(elements, id, initLength, needsHoleCheck); current->add(load); diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index d918f84eca56..e1a47e2c01da 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -41,20 +41,6 @@ class IonBuilder : public MIRGenerator SetElem_Unsafe, }; - enum GetElemSafety { - // Normal read like a[b] - GetElem_Normal, - - // Read due to UnsafeGetElement: - // - assumed to be in bounds, - GetElem_Unsafe, - - // Read due to UnsafeGetImmutableElement: - // - assumed to be in bounds, - // - assumed not to alias any stores - GetElem_UnsafeImmutable, - }; - struct DeferredEdge : public TempObject { MBasicBlock *block; @@ -405,7 +391,7 @@ class IonBuilder : public MIRGenerator bool jsop_intrinsic(HandlePropertyName name); bool jsop_bindname(PropertyName *name); bool jsop_getelem(); - bool jsop_getelem_dense(GetElemSafety safety, MDefinition *object, MDefinition *index); + bool jsop_getelem_dense(); bool jsop_getelem_typed(int arrayType); bool jsop_getelem_typed_static(bool *psucceeded); bool jsop_getelem_string(); @@ -500,8 +486,6 @@ class IonBuilder : public MIRGenerator InliningStatus inlineUnsafeSetElement(CallInfo &callInfo); bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base); bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, int arrayType); - InliningStatus inlineUnsafeGetElement(CallInfo &callInfo, - GetElemSafety safety); InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo); InliningStatus inlineNewDenseArray(CallInfo &callInfo); InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo); diff --git a/js/src/ion/MCallOptimize.cpp b/js/src/ion/MCallOptimize.cpp index 06cb9a79297f..e2691532e577 100644 --- a/js/src/ion/MCallOptimize.cpp +++ b/js/src/ion/MCallOptimize.cpp @@ -90,10 +90,6 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native) // Array intrinsics. if (native == intrinsic_UnsafeSetElement) return inlineUnsafeSetElement(callInfo); - if (native == intrinsic_UnsafeGetElement) - return inlineUnsafeGetElement(callInfo, GetElem_Unsafe); - if (native == intrinsic_UnsafeGetImmutableElement) - return inlineUnsafeGetElement(callInfo, GetElem_UnsafeImmutable); if (native == intrinsic_NewDenseArray) return inlineNewDenseArray(callInfo); @@ -956,10 +952,9 @@ IonBuilder::inlineUnsafeSetElement(CallInfo &callInfo) /* Important: * * Here we inline each of the stores resulting from a call to - * UnsafeSetElement(). It is essential that these stores occur + * %UnsafeSetElement(). It is essential that these stores occur * atomically and cannot be interrupted by a stack or recursion * check. If this is not true, race conditions can occur. - * See definition of UnsafeSetElement() for more details. */ for (uint32_t base = 0; base < argc; base += 3) { @@ -1058,30 +1053,6 @@ IonBuilder::inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, return true; } -IonBuilder::InliningStatus -IonBuilder::inlineUnsafeGetElement(CallInfo &callInfo, - GetElemSafety safety) -{ - JS_ASSERT(safety != GetElem_Normal); - - uint32_t argc = callInfo.argc(); - if (argc < 2 || callInfo.constructing()) - return InliningStatus_NotInlined; - const uint32_t obj = 0; - const uint32_t index = 1; - if (!ElementAccessIsDenseNative(callInfo.getArg(obj), - callInfo.getArg(index))) - return InliningStatus_NotInlined; - if (ElementAccessHasExtraIndexedProperty(cx, callInfo.getArg(obj))) - return InliningStatus_NotInlined; - callInfo.unwrapArgs(); - if (!jsop_getelem_dense(safety, - callInfo.getArg(obj), - callInfo.getArg(index))) - return InliningStatus_Error; - return InliningStatus_Inlined; -} - IonBuilder::InliningStatus IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo) { diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 3a36021cb223..4450915e2a9c 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -4510,13 +4510,11 @@ class MLoadElement { bool needsHoleCheck_; bool loadDoubles_; - bool knownImmutable_; // load of data that is known to be immutable - MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles, bool knownImmutable) + MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles) : MBinaryInstruction(elements, index), needsHoleCheck_(needsHoleCheck), - loadDoubles_(loadDoubles), - knownImmutable_(knownImmutable) + loadDoubles_(loadDoubles) { setResultType(MIRType_Value); setMovable(); @@ -4528,10 +4526,8 @@ class MLoadElement INSTRUCTION_HEADER(LoadElement) static MLoadElement *New(MDefinition *elements, MDefinition *index, - bool needsHoleCheck, bool loadDoubles, - bool knownImmutable) { - return new MLoadElement(elements, index, needsHoleCheck, loadDoubles, - knownImmutable); + bool needsHoleCheck, bool loadDoubles) { + return new MLoadElement(elements, index, needsHoleCheck, loadDoubles); } TypePolicy *typePolicy() { @@ -4553,9 +4549,6 @@ class MLoadElement return needsHoleCheck(); } AliasSet getAliasSet() const { - if (knownImmutable_) - return AliasSet::None(); - return AliasSet::Load(AliasSet::Element); } }; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 42a8b7bc6fee..2ffbeb0ace11 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -2366,9 +2366,6 @@ JSBool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp); -JSBool intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp); -JSBool intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc, - Value *vp); JSBool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp); diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 20addd06ae27..a3f7798046d8 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -341,26 +341,15 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp) /* * UnsafeSetElement(arr0, idx0, elem0, ..., arrN, idxN, elemN): For * each set of (arr, idx, elem) arguments that are passed, performs - * the assignment `arr[idx] = elem`. `arr` must be either a dense array + * the assignment |arr[idx] = elem|. |arr| must be either a dense array * or a typed array. * - * If `arr` is a dense array, the index must be an int32 less than the - * initialized length of `arr`. Use `NewDenseAllocatedArray` to ensure - * that the initialized length is long enough. + * If |arr| is a dense array, the index must be an int32 less than the + * initialized length of |arr|. Use |%EnsureDenseResultArrayElements| + * to ensure that the initialized length is long enough. * - * If `arr` is a typed array, the index must be an int32 less than the - * length of `arr`. - * - * The reason that `UnsafeSetElement` takes multiple - * array/index/element triples is not for convenience but rather for - * semantic reasons: there are a few places in the parallel code where - * correctness relies on the fact that *all of the assignments occur - * or none of them*. This occurs in operations like reduce or fold - * which mutate the same data in place. That is, we do not want to - * bail out or interrupt in between the individual assignments. To - * convey this notion, we place all the assignments together into one - * `UnsafeSetElement` call. It is preferable to use multiple calls if - * it is not important that the assignments occur all-or-nothing. + * If |arr| is a typed array, the index must be an int32 less than the + * length of |arr|. */ JSBool js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) @@ -391,6 +380,7 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) } else { JS_ASSERT(idx < TypedArray::length(arrobj)); RootedValue tmp(cx, args[elemi]); + // XXX: Always non-strict. if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false)) return false; } @@ -400,46 +390,6 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) return true; } -/* - * UnsafeGetElement(arr, idx)=elem: - * - * Loads an element from an array. Requires that `arr` be a dense - * array and `idx` be in bounds. In ion compiled code, no bounds - * check will be emitted. - */ -JSBool -js::intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - - const uint32_t arri = 0; - const uint32_t idxi = 1; - - JS_ASSERT(args[arri].isObject()); - JS_ASSERT(args[idxi].isInt32()); - - RootedObject arrobj(cx, &args[arri].toObject()); - uint32_t idx = args[idxi].toInt32(); - - JS_ASSERT(args[arri].toObject().isNative()); - JS_ASSERT(idx < arrobj->getDenseInitializedLength()); - args.rval().set(arrobj->getDenseElement(idx)); - return true; -} - -/* - * UnsafeGetImmutableElement(arr, idx)=elem: - * - * Same as `UnsafeGetElement(arr, idx)`, except that the array is - * known by the self-hosting code to be immutable. Therefore, ion - * compilation can reorder this load freely with respect to stores. - */ -JSBool -js::intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc, Value *vp) -{ - return intrinsic_UnsafeGetElement(cx, argc, vp); -} - /* * ParallelTestsShouldPass(): Returns false if we are running in a * mode (such as --ion-eager) that is known to cause additional @@ -518,8 +468,6 @@ const JSFunctionSpec intrinsic_functions[] = { JS_FN("NewParallelArray", intrinsic_NewParallelArray, 3,0), JS_FN("NewDenseArray", intrinsic_NewDenseArray, 1,0), JS_FN("UnsafeSetElement", intrinsic_UnsafeSetElement, 3,0), - JS_FN("UnsafeGetElement", intrinsic_UnsafeGetElement, 2,0), - JS_FN("UnsafeGetImmutableElement", intrinsic_UnsafeGetImmutableElement, 2,0), JS_FN("ShouldForceSequential", intrinsic_ShouldForceSequential, 0,0), JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0), From 44557460f9b964271b039810b6dd3bde6e9b337a Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Fri, 14 Jun 2013 17:26:28 -0700 Subject: [PATCH 021/615] Bug 881470. r=jandem --- js/src/ion/IonBuilder.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 2dcd2f9b22fe..3e65abd2a04f 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -6689,6 +6689,9 @@ IonBuilder::jsop_setelem() if (!icInspect.sawDenseWrite()) break; + if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value)) + break; + MInstruction *ins = MSetElementCache::New(object, index, value, script()->strict); current->add(ins); current->push(value); From ee997bb486b0de92447e55b3f6117c77d8bd726d Mon Sep 17 00:00:00 2001 From: Steve Workman Date: Fri, 14 Jun 2013 19:34:17 -0700 Subject: [PATCH 022/615] Bug 497003 - Adjust partial content test and revert httpd.js r=jduell --- netwerk/test/httpserver/httpd.js | 5 +- netwerk/test/mochitests/partial_content.sjs | 63 ++++++++++++------- .../test_partially_cached_content.html | 18 +++++- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/netwerk/test/httpserver/httpd.js b/netwerk/test/httpserver/httpd.js index cbf95287e7a0..5a40cc4fa584 100644 --- a/netwerk/test/httpserver/httpd.js +++ b/netwerk/test/httpserver/httpd.js @@ -3974,10 +3974,7 @@ Response.prototype = var avail = bodyStream ? bodyStream.available() : 0; // XXX assumes stream will always report the full amount of data available - // Set "Content-Length" if not already set by request handler. - if (!headers.hasHeader("Content-Length")) { - headers.setHeader("Content-Length", "" + avail, false); - } + headers.setHeader("Content-Length", "" + avail, false); } diff --git a/netwerk/test/mochitests/partial_content.sjs b/netwerk/test/mochitests/partial_content.sjs index 39fc44ede52b..d6c82039c499 100644 --- a/netwerk/test/mochitests/partial_content.sjs +++ b/netwerk/test/mochitests/partial_content.sjs @@ -4,23 +4,28 @@ * 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/. */ -// HTTP Version from request, used for response. -var gHttpVersion; - /* Debug and Error wrapper functions for dump(). */ function ERR(response, responseCode, responseCodeStr, msg) { + // Reset state var. + setState("expectedRequestType", ""); // Dump to console log and send to client in response. dump("SERVER ERROR: " + msg + "\n"); - response.setStatusLine(gHttpVersion, responseCode, responseCodeStr); + response.write("HTTP/1.1" + responseCode + responseCodeStr + "\r\n"); + response.write("Content-Type: text/html; charset=UTF-8\r\n"); + response.write("Content-Length: " + msg.length + "\r\n"); + response.write("\r\n"); response.write(msg); } function DBG(msg) { - // Dump to console only. - dump("SERVER DEBUG: " + msg + "\n"); + // enable when you want to debug + if (0) { + // Dump to console only. + dump("SERVER DEBUG: " + msg + "\n"); + } } /* Delivers content in parts to test partially cached content: requires two @@ -35,24 +40,28 @@ function DBG(msg) */ function handleRequest(request, response) { - // Set http version for error responses. - gHttpVersion = request.httpVersion; - - // All responses, inc. errors, are text/html. - response.setHeader("Content-Type", "text/html; charset=UTF-8", false); + DBG("Trying to seize power"); + response.seizePower(); + DBG("About to check state vars"); // Get state var to determine if this is the first or second request. var expectedRequestType; + var lastModified; if (getState("expectedRequestType") === "") { DBG("First call: Should be requesting full content."); expectedRequestType = "fullRequest"; // Set state var for second request. setState("expectedRequestType", "partialRequest"); + // Create lastModified variable for responses. + lastModified = (new Date()).toUTCString(); + setState("lastModified", lastModified); } else if (getState("expectedRequestType") === "partialRequest") { DBG("Second call: Should be requesting undelivered content."); expectedRequestType = "partialRequest"; // Reset state var for first request. setState("expectedRequestType", ""); + // Get last modified date and reset state var. + lastModified = getState("lastModified"); } else { ERR(response, 500, "Internal Server Error", "Invalid expectedRequestType \"" + expectedRequestType + "\"in " + @@ -105,24 +114,34 @@ function handleRequest(request, response) DBG("totalLength: " + totalLength); // Prepare common headers for the two responses. - response.setHeader("ETag", "abcd0123", false); - response.setHeader("Accept-Ranges", "bytes", false); + date = new Date(); + DBG("Date: " + date.toUTCString() + ", Last-Modified: " + lastModified); + var commonHeaders = "Date: " + date.toUTCString() + "\r\n" + + "Last-Modified: " + lastModified + "\r\n" + + "Content-Type: text/html; charset=UTF-8\r\n" + + "ETag: abcd0123\r\n" + + "Accept-Ranges: bytes\r\n"; + // Prepare specific headers and content for first and second responses. if (expectedRequestType === "fullRequest") { DBG("First response: Sending partial content with a full header"); - response.setStatusLine(request.httpVersion, 200, "OK"); - response.write(partialContent, partialContent.length); + response.write("HTTP/1.1 200 OK\r\n"); + response.write(commonHeaders); // Set Content-Length to full length of resource. - response.setHeader("Content-Length", "" + totalLength, false); + response.write("Content-Length: " + totalLength + "\r\n"); + response.write("\r\n"); + response.write(partialContent); } else if (expectedRequestType === "partialRequest") { DBG("Second response: Sending remaining content with a range header"); - response.setStatusLine(request.httpVersion, 206, "Partial Content"); - response.setHeader("Content-Range", "bytes " + partialContent.length + "-" + - (totalLength - 1) + "/" + totalLength); - response.write(remainderContent); + response.write("HTTP/1.1 206 Partial Content\r\n"); + response.write(commonHeaders); // Set Content-Length to length of bytes transmitted. - response.setHeader("Content-Length", "" + remainderContent.length, false); + response.write("Content-Length: " + remainderContent.length + "\r\n"); + response.write("Content-Range: bytes " + partialContent.length + "-" + + (totalLength - 1) + "/" + totalLength + "\r\n"); + response.write("\r\n"); + response.write(remainderContent); } else { // Somewhat redundant, but a check for errors in this test code. ERR(response, 500, "Internal Server Error", @@ -130,4 +149,6 @@ function handleRequest(request, response) "towards the end of handleRequest! - \"" + expectedRequestType + "\""); return; } + + response.finish(); } diff --git a/netwerk/test/mochitests/test_partially_cached_content.html b/netwerk/test/mochitests/test_partially_cached_content.html index 0c4ed80bba6d..05a8bca69e24 100644 --- a/netwerk/test/mochitests/test_partially_cached_content.html +++ b/netwerk/test/mochitests/test_partially_cached_content.html @@ -33,7 +33,11 @@ function expectInitialContent(e) { // Expect "First response" in received HTML. var firstResponse = frameWindow.document.getElementById('firstResponse'); - is(firstResponse.innerHTML, "First response", "firstResponse"); + ok(firstResponse, "First response should exist"); + if (firstResponse) { + is(firstResponse.innerHTML, "First response", + "First response should be correct"); + } // Expect NOT to get any second response element. var secondResponse = frameWindow.document.getElementById('secondResponse'); @@ -57,11 +61,19 @@ function expectFullContent(e) // Expect "First response" to still be there var firstResponse = frameWindow.document.getElementById('firstResponse'); - is(firstResponse.innerHTML, "First response", "firstResponse"); + ok(firstResponse, "First response should exist"); + if (firstResponse) { + is(firstResponse.innerHTML, "First response", + "First response should be correct"); + } // Expect "Second response" to be there also. var secondResponse = frameWindow.document.getElementById('secondResponse'); - is(secondResponse.innerHTML, "Second response", "secondResponse"); + ok(secondResponse, "Second response should exist"); + if (secondResponse) { + is(secondResponse.innerHTML, "Second response", + "Second response should be correct"); + } SimpleTest.finish(); } From 22be445ea572f9a33f854b474819ccc026650d02 Mon Sep 17 00:00:00 2001 From: Steve Workman Date: Fri, 14 Jun 2013 19:34:18 -0700 Subject: [PATCH 023/615] Bug 497003 - Replace some QueryInterface calls in nsHttpChannel with do_QueryObject r=jduell --- netwerk/protocol/http/nsHttpChannel.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index a3a6cc5b7be1..a009c3e02ea8 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -5257,17 +5257,13 @@ nsHttpChannel::RetargetDeliveryTo(nsIEventTarget* aNewTarget) nsCOMPtr retargetableCachePump; nsCOMPtr retargetableTransactionPump; if (mCachePump) { - // Direct call to QueryInterface to avoid multiple inheritance issues. - rv = mCachePump->QueryInterface(NS_GET_IID(nsIThreadRetargetableRequest), - getter_AddRefs(retargetableCachePump)); + retargetableCachePump = do_QueryObject(mCachePump); // nsInputStreamPump should implement this interface. MOZ_ASSERT(retargetableCachePump); rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget); } if (NS_SUCCEEDED(rv) && mTransactionPump) { - // Direct call to QueryInterface to avoid multiple inheritance issues. - rv = mTransactionPump->QueryInterface(NS_GET_IID(nsIThreadRetargetableRequest), - getter_AddRefs(retargetableTransactionPump)); + retargetableTransactionPump = do_QueryObject(mTransactionPump); // nsInputStreamPump should implement this interface. MOZ_ASSERT(retargetableTransactionPump); rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget); From 7423a235e58a5b95306955803d7340bce4892afc Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Fri, 22 Mar 2013 14:09:40 -0400 Subject: [PATCH 024/615] Bug 356821 - Update add-search-engine-as-current checkbox label. r=mak --- toolkit/components/search/nsSearchService.js | 2 +- toolkit/locales/en-US/chrome/search/search.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index 5819f1a995c4..6b4419f5ebc7 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -1272,7 +1272,7 @@ Engine.prototype = { [this._name, this._uri.host], 2); var checkboxMessage = null; if (!getBoolPref(BROWSER_SEARCH_PREF + "noCurrentEngine", false)) - checkboxMessage = stringBundle.GetStringFromName("addEngineUseNowText"); + checkboxMessage = stringBundle.GetStringFromName("addEngineAsCurrentText"); var addButtonLabel = stringBundle.GetStringFromName("addEngineAddButtonLabel"); diff --git a/toolkit/locales/en-US/chrome/search/search.properties b/toolkit/locales/en-US/chrome/search/search.properties index 3483f838dbdf..66a158c9187c 100644 --- a/toolkit/locales/en-US/chrome/search/search.properties +++ b/toolkit/locales/en-US/chrome/search/search.properties @@ -4,7 +4,7 @@ addEngineConfirmTitle=Add Search Engine addEngineConfirmation=Add "%S" to the list of engines available in the search bar?\n\nFrom: %S -addEngineUseNowText=Start &using it right away +addEngineAsCurrentText=Make this the c&urrent search engine addEngineAddButtonLabel=Add error_loading_engine_title=Download Error From c7efed20429e57831d518636a218e89c2fb58f19 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 13 Jun 2013 22:34:37 -0700 Subject: [PATCH 025/615] Bug 882573 patch 1: Move the style attribute style sheet from nsDocument to nsIDocument, and devirtualize its getter. r=bzbarsky --- content/base/public/nsIDocument.h | 5 ++++- content/base/src/nsDocument.h | 9 --------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 710c0ba465ec..3b130e2ffb60 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -766,7 +766,9 @@ public: * Get this document's inline style sheet. May return null if there * isn't one */ - virtual nsHTMLCSSStyleSheet* GetInlineStyleSheet() const = 0; + nsHTMLCSSStyleSheet* GetInlineStyleSheet() const { + return mStyleAttrStyleSheet; + } /** * Get/set the object from which a document can get a script context @@ -2178,6 +2180,7 @@ protected: nsRefPtr mCSSLoader; nsRefPtr mStyleImageLoader; nsRefPtr mAttrStyleSheet; + nsRefPtr mStyleAttrStyleSheet; // The set of all object, embed, applet, video and audio elements for // which this is the owner document. (They might not be in the document.) diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index b7e36e35eab2..fc960561824b 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -641,14 +641,6 @@ public: return mChannel; } - /** - * Get this document's inline style sheet. May return null if there - * isn't one - */ - virtual nsHTMLCSSStyleSheet* GetInlineStyleSheet() const MOZ_OVERRIDE { - return mStyleAttrStyleSheet; - } - /** * Set the object from which a document can get a script context. * This is the context within which all scripts (during document @@ -1308,7 +1300,6 @@ protected: // The channel that got passed to StartDocumentLoad(), if any nsCOMPtr mChannel; - nsRefPtr mStyleAttrStyleSheet; // A document "without a browsing context" that owns the content of // HTMLTemplateElement. From cf9ba9869ae31cf484ce3ce8ce97840742a1c3ee Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 13 Jun 2013 22:34:37 -0700 Subject: [PATCH 026/615] Bug 882573 patch 2: Add a separate DirtyRuleProcessors method to nsStyleSet, and use it from existing methods. r=heycam --- layout/style/nsStyleSet.cpp | 36 ++++++++++++------------------------ layout/style/nsStyleSet.h | 2 ++ 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 7105db27e632..fbb373e8cbf1 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -423,11 +423,7 @@ nsStyleSet::AppendStyleSheet(sheetType aType, nsIStyleSheet *aSheet) if (!mSheets[aType].AppendObject(aSheet)) return NS_ERROR_OUT_OF_MEMORY; - if (!mBatching) - return GatherRuleProcessors(aType); - - mDirty |= 1 << aType; - return NS_OK; + return DirtyRuleProcessors(aType); } nsresult @@ -440,11 +436,7 @@ nsStyleSet::PrependStyleSheet(sheetType aType, nsIStyleSheet *aSheet) if (!mSheets[aType].InsertObjectAt(aSheet, 0)) return NS_ERROR_OUT_OF_MEMORY; - if (!mBatching) - return GatherRuleProcessors(aType); - - mDirty |= 1 << aType; - return NS_OK; + return DirtyRuleProcessors(aType); } nsresult @@ -454,11 +446,8 @@ nsStyleSet::RemoveStyleSheet(sheetType aType, nsIStyleSheet *aSheet) NS_ASSERTION(aSheet->IsComplete(), "Incomplete sheet being removed from style set"); mSheets[aType].RemoveObject(aSheet); - if (!mBatching) - return GatherRuleProcessors(aType); - mDirty |= 1 << aType; - return NS_OK; + return DirtyRuleProcessors(aType); } nsresult @@ -469,11 +458,7 @@ nsStyleSet::ReplaceSheets(sheetType aType, if (!mSheets[aType].AppendObjects(aNewSheets)) return NS_ERROR_OUT_OF_MEMORY; - if (!mBatching) - return GatherRuleProcessors(aType); - - mDirty |= 1 << aType; - return NS_OK; + return DirtyRuleProcessors(aType); } nsresult @@ -488,10 +473,16 @@ nsStyleSet::InsertStyleSheetBefore(sheetType aType, nsIStyleSheet *aNewSheet, int32_t idx = mSheets[aType].IndexOf(aReferenceSheet); if (idx < 0) return NS_ERROR_INVALID_ARG; - + if (!mSheets[aType].InsertObjectAt(aNewSheet, idx)) return NS_ERROR_OUT_OF_MEMORY; + return DirtyRuleProcessors(aType); +} + +nsresult +nsStyleSet::DirtyRuleProcessors(sheetType aType) +{ if (!mBatching) return GatherRuleProcessors(aType); @@ -559,11 +550,8 @@ nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) } if (!sheets.InsertObjectAt(aSheet, index)) return NS_ERROR_OUT_OF_MEMORY; - if (!mBatching) - return GatherRuleProcessors(type); - mDirty |= 1 << type; - return NS_OK; + return DirtyRuleProcessors(type); } nsresult diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 1a0ae8f082ce..006c0124e05d 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -259,6 +259,8 @@ class nsStyleSet nsresult InsertStyleSheetBefore(sheetType aType, nsIStyleSheet *aNewSheet, nsIStyleSheet *aReferenceSheet); + nsresult DirtyRuleProcessors(sheetType aType); + // Enable/Disable entire author style level (Doc, ScopedDoc & PresHint levels) bool GetAuthorStyleDisabled(); nsresult SetAuthorStyleDisabled(bool aStyleDisabled); From f753ac02c06c4f18efd2bbbe98cb81b03abf6874 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 13 Jun 2013 22:34:37 -0700 Subject: [PATCH 027/615] Bug 882573 patch 3: Stop putting the presentational hint and style attribute style sheets in the style set's list of style sheets; put them only in the list of rule processors. r=heycam --- content/base/src/nsDocument.cpp | 26 ++++------------------- layout/style/nsStyleSet.cpp | 37 +++++++++++++++++++++------------ layout/style/nsStyleSet.h | 3 +++ 3 files changed, 31 insertions(+), 35 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 4184ba13ba47..003b5a802e6e 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2234,12 +2234,6 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI) // Now reset our inline style and attribute sheets. if (mAttrStyleSheet) { - // Remove this sheet from all style sets - nsCOMPtr shell = GetShell(); - if (shell) { - shell->StyleSet()->RemoveStyleSheet(nsStyleSet::ePresHintSheet, - mAttrStyleSheet); - } mAttrStyleSheet->Reset(aURI); } else { mAttrStyleSheet = new nsHTMLStyleSheet(aURI, this); @@ -2250,12 +2244,6 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI) mAttrStyleSheet->SetOwningDocument(this); if (mStyleAttrStyleSheet) { - // Remove this sheet from all style sets - nsCOMPtr shell = GetShell(); - if (shell) { - shell->StyleSet()-> - RemoveStyleSheet(nsStyleSet::eStyleAttrSheet, mStyleAttrStyleSheet); - } mStyleAttrStyleSheet->Reset(aURI); } else { mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet(aURI, this); @@ -2295,19 +2283,13 @@ void nsDocument::FillStyleSet(nsStyleSet* aStyleSet) { NS_PRECONDITION(aStyleSet, "Must have a style set"); - NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::ePresHintSheet) == 0, - "Style set already has a preshint sheet?"); NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eDocSheet) == 0, "Style set already has document sheets?"); - NS_PRECONDITION(aStyleSet->SheetCount(nsStyleSet::eStyleAttrSheet) == 0, - "Style set already has style attr sheets?"); - NS_PRECONDITION(mStyleAttrStyleSheet, "No style attr stylesheet?"); - NS_PRECONDITION(mAttrStyleSheet, "No attr stylesheet?"); - aStyleSet->AppendStyleSheet(nsStyleSet::ePresHintSheet, mAttrStyleSheet); - - aStyleSet->AppendStyleSheet(nsStyleSet::eStyleAttrSheet, - mStyleAttrStyleSheet); + // We could consider moving this to nsStyleSet::Init, to match its + // handling of the eAnimationSheet and eTransitionSheet levels. + aStyleSet->DirtyRuleProcessors(nsStyleSet::ePresHintSheet); + aStyleSet->DirtyRuleProcessors(nsStyleSet::eStyleAttrSheet); int32_t i; for (i = mStyleSheets.Count() - 1; i >= 0; --i) { diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index fbb373e8cbf1..4f5dff656783 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -30,6 +30,8 @@ #include "nsStyleSheetService.h" #include "mozilla/dom/Element.h" #include "GeckoProfiler.h" +#include "nsHTMLCSSStyleSheet.h" +#include "nsHTMLStyleSheet.h" using namespace mozilla; using namespace mozilla::dom; @@ -318,19 +320,28 @@ nsStyleSet::GatherRuleProcessors(sheetType aType) // elements later if mAuthorStyleDisabled. return NS_OK; } - if (aType == eAnimationSheet) { - // We have no sheet for the animations level; just a rule - // processor. (XXX: We should probably do this for the other - // non-CSS levels too!) - mRuleProcessors[aType] = PresContext()->AnimationManager(); - return NS_OK; - } - if (aType == eTransitionSheet) { - // We have no sheet for the transitions level; just a rule - // processor. (XXX: We should probably do this for the other - // non-CSS levels too!) - mRuleProcessors[aType] = PresContext()->TransitionManager(); - return NS_OK; + switch (aType) { + // handle the types for which have a rule processor that does not + // implement the style sheet interface. + case eAnimationSheet: + MOZ_ASSERT(mSheets[aType].Count() == 0); + mRuleProcessors[aType] = PresContext()->AnimationManager(); + return NS_OK; + case eTransitionSheet: + MOZ_ASSERT(mSheets[aType].Count() == 0); + mRuleProcessors[aType] = PresContext()->TransitionManager(); + return NS_OK; + case eStyleAttrSheet: + MOZ_ASSERT(mSheets[aType].Count() == 0); + mRuleProcessors[aType] = PresContext()->Document()->GetInlineStyleSheet(); + return NS_OK; + case ePresHintSheet: + MOZ_ASSERT(mSheets[aType].Count() == 0); + mRuleProcessors[aType] = PresContext()->Document()->GetAttributeStyleSheet(); + return NS_OK; + default: + // keep going + break; } if (aType == eScopedDocSheet) { // Create a rule processor for each scope. diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 006c0124e05d..1e46261d5a4b 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -394,6 +394,9 @@ class nsStyleSet // The sheets in each array in mSheets are stored with the most significant // sheet last. + // The arrays for ePresHintSheet, eStyleAttrSheet, eTransitionSheet, + // and eAnimationSheet are always empty. (FIXME: We should reduce + // the storage needed for them.) nsCOMArray mSheets[eSheetTypeCount]; // mRuleProcessors[eScopedDocSheet] is always null; rule processors From d8bcb54fbd1d9f88ff8a82106f09c840dc59f079 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 13 Jun 2013 22:34:37 -0700 Subject: [PATCH 028/615] Bug 882573 patch 4: Make nsHTMLStyleSheet and nsHTMLCSSStyleSheet stop implementing nsIStyleSheet. r=heycam Note that this removes the Reset method and the mURL and mDocument members (and arguments to set them) from nsHTMLCSSStyleSheet. On the other hand, from nsHTMLStyleSheet it only removes mURL (and equivalent arguments), and nsHTMLStyleSheet keeps the SetOwningDocument method that was previously part of nsIStyleSheet (but no longer virtual). --- content/base/src/nsDocument.cpp | 21 ++---- layout/style/nsHTMLCSSStyleSheet.cpp | 105 +-------------------------- layout/style/nsHTMLCSSStyleSheet.h | 32 +------- layout/style/nsHTMLStyleSheet.cpp | 96 ++---------------------- layout/style/nsHTMLStyleSheet.h | 27 ++----- 5 files changed, 19 insertions(+), 262 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 003b5a802e6e..6014b96e49c6 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1478,8 +1478,6 @@ nsDocument::~nsDocument() if (mAttrStyleSheet) { mAttrStyleSheet->SetOwningDocument(nullptr); } - if (mStyleAttrStyleSheet) - mStyleAttrStyleSheet->SetOwningDocument(nullptr); if (mListenerManager) { mListenerManager->Disconnect(); @@ -2234,25 +2232,16 @@ nsDocument::ResetStylesheetsToURI(nsIURI* aURI) // Now reset our inline style and attribute sheets. if (mAttrStyleSheet) { - mAttrStyleSheet->Reset(aURI); + mAttrStyleSheet->Reset(); + mAttrStyleSheet->SetOwningDocument(this); } else { - mAttrStyleSheet = new nsHTMLStyleSheet(aURI, this); + mAttrStyleSheet = new nsHTMLStyleSheet(this); } - // Don't use AddStyleSheet, since it'll put the sheet into style - // sets in the document level, which is not desirable here. - mAttrStyleSheet->SetOwningDocument(this); - - if (mStyleAttrStyleSheet) { - mStyleAttrStyleSheet->Reset(aURI); - } else { - mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet(aURI, this); + if (!mStyleAttrStyleSheet) { + mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet(); } - // The loop over style sets below will handle putting this sheet - // into style sets as needed. - mStyleAttrStyleSheet->SetOwningDocument(this); - // Now set up our style sets nsCOMPtr shell = GetShell(); if (shell) { diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 1c93aceefcf7..c3d3882b8bd0 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -39,12 +39,8 @@ ClearAttrCache(const nsAString& aKey, MiscContainer*& aValue, void*) } // anonymous namespace -nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet(nsIURI* aURL, nsIDocument* aDocument) - : mURL(aURL) - , mDocument(aDocument) // not refcounted! +nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet() { - MOZ_ASSERT(aURL); - MOZ_ASSERT(aDocument); mCachedStyleAttrs.Init(); } @@ -55,9 +51,7 @@ nsHTMLCSSStyleSheet::~nsHTMLCSSStyleSheet() mCachedStyleAttrs.Enumerate(ClearAttrCache, nullptr); } -NS_IMPL_ISUPPORTS2(nsHTMLCSSStyleSheet, - nsIStyleSheet, - nsIStyleRuleProcessor) +NS_IMPL_ISUPPORTS1(nsHTMLCSSStyleSheet, nsIStyleRuleProcessor) /* virtual */ void nsHTMLCSSStyleSheet::RulesMatching(ElementRuleProcessorData* aData) @@ -175,98 +169,3 @@ nsHTMLCSSStyleSheet::LookupStyleAttr(const nsAString& aSerialized) { return mCachedStyleAttrs.Get(aSerialized); } - -void -nsHTMLCSSStyleSheet::Reset(nsIURI* aURL) -{ - mURL = aURL; -} - -/* virtual */ nsIURI* -nsHTMLCSSStyleSheet::GetSheetURI() const -{ - return mURL; -} - -/* virtual */ nsIURI* -nsHTMLCSSStyleSheet::GetBaseURI() const -{ - return mURL; -} - -/* virtual */ void -nsHTMLCSSStyleSheet::GetTitle(nsString& aTitle) const -{ - aTitle.AssignLiteral("Internal HTML/CSS Style Sheet"); -} - -/* virtual */ void -nsHTMLCSSStyleSheet::GetType(nsString& aType) const -{ - aType.AssignLiteral("text/html"); -} - -/* virtual */ bool -nsHTMLCSSStyleSheet::HasRules() const -{ - // Say we always have rules, since we don't know. - return true; -} - -/* virtual */ bool -nsHTMLCSSStyleSheet::IsApplicable() const -{ - return true; -} - -/* virtual */ void -nsHTMLCSSStyleSheet::SetEnabled(bool aEnabled) -{ // these can't be disabled -} - -/* virtual */ bool -nsHTMLCSSStyleSheet::IsComplete() const -{ - return true; -} - -/* virtual */ void -nsHTMLCSSStyleSheet::SetComplete() -{ -} - -// style sheet owner info -/* virtual */ nsIStyleSheet* -nsHTMLCSSStyleSheet::GetParentSheet() const -{ - return nullptr; -} - -/* virtual */ nsIDocument* -nsHTMLCSSStyleSheet::GetOwningDocument() const -{ - return mDocument; -} - -/* virtual */ void -nsHTMLCSSStyleSheet::SetOwningDocument(nsIDocument* aDocument) -{ - mDocument = aDocument; -} - -#ifdef DEBUG -/* virtual */ void -nsHTMLCSSStyleSheet::List(FILE* out, int32_t aIndent) const -{ - // Indent - for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); - - fputs("HTML CSS Style Sheet: ", out); - nsAutoCString urlSpec; - mURL->GetSpec(urlSpec); - if (!urlSpec.IsEmpty()) { - fputs(urlSpec.get(), out); - } - fputs("\n", out); -} -#endif diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index 9336ad83da00..b3e8a16c6fe2 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -19,34 +19,14 @@ struct MiscContainer; -class nsHTMLCSSStyleSheet MOZ_FINAL : public nsIStyleSheet, - public nsIStyleRuleProcessor +class nsHTMLCSSStyleSheet MOZ_FINAL : public nsIStyleRuleProcessor { public: - nsHTMLCSSStyleSheet(nsIURI* aURL, nsIDocument* aDocument); + nsHTMLCSSStyleSheet(); ~nsHTMLCSSStyleSheet(); NS_DECL_ISUPPORTS - void Reset(nsIURI* aURL); - - // nsIStyleSheet - virtual nsIURI* GetSheetURI() const MOZ_OVERRIDE; - virtual nsIURI* GetBaseURI() const MOZ_OVERRIDE; - virtual void GetTitle(nsString& aTitle) const MOZ_OVERRIDE; - virtual void GetType(nsString& aType) const MOZ_OVERRIDE; - virtual bool HasRules() const MOZ_OVERRIDE; - virtual bool IsApplicable() const MOZ_OVERRIDE; - virtual void SetEnabled(bool aEnabled) MOZ_OVERRIDE; - virtual bool IsComplete() const MOZ_OVERRIDE; - virtual void SetComplete() MOZ_OVERRIDE; - virtual nsIStyleSheet* GetParentSheet() const MOZ_OVERRIDE; // will be null - virtual nsIDocument* GetOwningDocument() const MOZ_OVERRIDE; - virtual void SetOwningDocument(nsIDocument* aDocument) MOZ_OVERRIDE; -#ifdef DEBUG - virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; -#endif - // nsIStyleRuleProcessor virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE; virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE; @@ -73,15 +53,7 @@ private: nsHTMLCSSStyleSheet& operator=(const nsHTMLCSSStyleSheet& aCopy) MOZ_DELETE; protected: - nsCOMPtr mURL; - nsIDocument* mDocument; nsDataHashtable mCachedStyleAttrs; }; -inline nsISupports* -ToSupports(nsHTMLCSSStyleSheet* aPointer) -{ - return static_cast(aPointer); -} - #endif /* !defined(nsHTMLCSSStyleSheet_h_) */ diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index d1ef8c23347c..e91f71da60ad 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -227,13 +227,11 @@ static PLDHashTableOps LangRuleTable_Ops = { // ----------------------------------------------------------- -nsHTMLStyleSheet::nsHTMLStyleSheet(nsIURI* aURL, nsIDocument* aDocument) - : mURL(aURL) - , mDocument(aDocument) +nsHTMLStyleSheet::nsHTMLStyleSheet(nsIDocument* aDocument) + : mDocument(aDocument) , mTableQuirkColorRule(new TableQuirkColorRule()) , mTableTHRule(new TableTHRule()) { - MOZ_ASSERT(aURL); MOZ_ASSERT(aDocument); mMappedAttrTable.ops = nullptr; mLangRuleTable.ops = nullptr; @@ -247,7 +245,7 @@ nsHTMLStyleSheet::~nsHTMLStyleSheet() PL_DHashTableFinish(&mMappedAttrTable); } -NS_IMPL_ISUPPORTS2(nsHTMLStyleSheet, nsIStyleSheet, nsIStyleRuleProcessor) +NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet, nsIStyleRuleProcessor) /* virtual */ void nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData) @@ -402,82 +400,15 @@ nsHTMLStyleSheet::RulesMatching(XULTreeRuleProcessorData* aData) } #endif - // nsIStyleSheet api -/* virtual */ nsIURI* -nsHTMLStyleSheet::GetSheetURI() const -{ - return mURL; -} - -/* virtual */ nsIURI* -nsHTMLStyleSheet::GetBaseURI() const -{ - return mURL; -} - -/* virtual */ void -nsHTMLStyleSheet::GetTitle(nsString& aTitle) const -{ - aTitle.Truncate(); -} - -/* virtual */ void -nsHTMLStyleSheet::GetType(nsString& aType) const -{ - aType.AssignLiteral("text/html"); -} - -/* virtual */ bool -nsHTMLStyleSheet::HasRules() const -{ - return true; // We have rules at all reasonable times -} - -/* virtual */ bool -nsHTMLStyleSheet::IsApplicable() const -{ - return true; -} - -/* virtual */ void -nsHTMLStyleSheet::SetEnabled(bool aEnabled) -{ // these can't be disabled -} - -/* virtual */ bool -nsHTMLStyleSheet::IsComplete() const -{ - return true; -} - -/* virtual */ void -nsHTMLStyleSheet::SetComplete() -{ -} - -/* virtual */ nsIStyleSheet* -nsHTMLStyleSheet::GetParentSheet() const -{ - return nullptr; -} - -/* virtual */ nsIDocument* -nsHTMLStyleSheet::GetOwningDocument() const -{ - return mDocument; -} - -/* virtual */ void +void nsHTMLStyleSheet::SetOwningDocument(nsIDocument* aDocument) { mDocument = aDocument; // not refcounted } void -nsHTMLStyleSheet::Reset(nsIURI* aURL) +nsHTMLStyleSheet::Reset() { - mURL = aURL; - mLinkRule = nullptr; mVisitedRule = nullptr; mActiveRule = nullptr; @@ -594,23 +525,6 @@ nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage) return entry->mRule; } -#ifdef DEBUG -/* virtual */ void -nsHTMLStyleSheet::List(FILE* out, int32_t aIndent) const -{ - // Indent - for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); - - fputs("HTML Style Sheet: ", out); - nsAutoCString urlSpec; - mURL->GetSpec(urlSpec); - if (!urlSpec.IsEmpty()) { - fputs(urlSpec.get(), out); - } - fputs("\n", out); -} -#endif - static size_t SizeOfAttributesEntryExcludingThis(PLDHashEntryHdr* aEntry, nsMallocSizeOfFun aMallocSizeOf, diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index c56b4bfa4cfb..886745df66e7 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -24,31 +24,15 @@ class nsMappedAttributes; -class nsHTMLStyleSheet MOZ_FINAL : public nsIStyleSheet, - public nsIStyleRuleProcessor +class nsHTMLStyleSheet MOZ_FINAL : public nsIStyleRuleProcessor { public: - nsHTMLStyleSheet(nsIURI* aURL, nsIDocument* aDocument); + nsHTMLStyleSheet(nsIDocument* aDocument); + + void SetOwningDocument(nsIDocument* aDocument); NS_DECL_ISUPPORTS - // nsIStyleSheet api - virtual nsIURI* GetSheetURI() const MOZ_OVERRIDE; - virtual nsIURI* GetBaseURI() const MOZ_OVERRIDE; - virtual void GetTitle(nsString& aTitle) const MOZ_OVERRIDE; - virtual void GetType(nsString& aType) const MOZ_OVERRIDE; - virtual bool HasRules() const MOZ_OVERRIDE; - virtual bool IsApplicable() const MOZ_OVERRIDE; - virtual void SetEnabled(bool aEnabled) MOZ_OVERRIDE; - virtual bool IsComplete() const MOZ_OVERRIDE; - virtual void SetComplete() MOZ_OVERRIDE; - virtual nsIStyleSheet* GetParentSheet() const MOZ_OVERRIDE; // will be null - virtual nsIDocument* GetOwningDocument() const MOZ_OVERRIDE; - virtual void SetOwningDocument(nsIDocument* aDocumemt) MOZ_OVERRIDE; -#ifdef DEBUG - virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; -#endif - // nsIStyleRuleProcessor API virtual void RulesMatching(ElementRuleProcessorData* aData) MOZ_OVERRIDE; virtual void RulesMatching(PseudoElementRuleProcessorData* aData) MOZ_OVERRIDE; @@ -67,7 +51,7 @@ public: const MOZ_MUST_OVERRIDE MOZ_OVERRIDE; size_t DOMSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; - void Reset(nsIURI* aURL); + void Reset(); nsresult SetLinkColor(nscolor aColor); nsresult SetActiveLinkColor(nscolor aColor); nsresult SetVisitedLinkColor(nscolor aColor); @@ -159,7 +143,6 @@ public: // for mLangRuleTable structures only }; private: - nsCOMPtr mURL; nsIDocument* mDocument; nsRefPtr mLinkRule; nsRefPtr mVisitedRule; From 56c8dc207993a3dde409c5ae6dbf70cfcd7f3f71 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 14 Jun 2013 08:09:20 +0200 Subject: [PATCH 029/615] Bug 863475 - integrate ARM EXIDX unwind parsing into Breakpad. r=glandium,ted --- .../crashreporter/google-breakpad/Makefile.am | 6 + .../google-breakpad/src/common/Makefile.in | 2 + .../src/common/arm_ex_reader.cc | 502 ++++++++++++++++++ .../src/common/arm_ex_reader.h | 115 ++++ .../src/common/arm_ex_to_module.cc | 206 +++++++ .../src/common/arm_ex_to_module.h | 129 +++++ .../src/common/linux/dump_symbols.cc | 74 +++ .../google-breakpad/src/common/module.cc | 2 +- .../google-breakpad/src/common/module.h | 9 +- .../google-breakpad/src/common/moz.build | 2 + .../src/common/unique_string.h | 21 + .../src/processor/cfi_frame_info.cc | 6 +- 12 files changed, 1069 insertions(+), 5 deletions(-) create mode 100644 toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc create mode 100644 toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h create mode 100644 toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc create mode 100644 toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h diff --git a/toolkit/crashreporter/google-breakpad/Makefile.am b/toolkit/crashreporter/google-breakpad/Makefile.am index 8649816f79cd..61fcc7b9cc21 100644 --- a/toolkit/crashreporter/google-breakpad/Makefile.am +++ b/toolkit/crashreporter/google-breakpad/Makefile.am @@ -433,6 +433,8 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \ src/common/dwarf/bytereader.cc \ src/common/dwarf/dwarf2diehandler.cc \ src/common/dwarf/dwarf2reader.cc \ + src/common/arm_ex_reader.cc \ + src/common/arm_ex_to_module.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elfutils.cc \ @@ -1015,6 +1017,10 @@ EXTRA_DIST = \ src/common/convert_UTF.h \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols.h \ + src/common/arm_ex_reader.cc \ + src/common/arm_ex_reader.h \ + src/common/arm_ex_to_module.cc \ + src/common/arm_ex_to_module.h \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elf_symbols_to_module.h \ src/common/linux/elfutils.cc \ diff --git a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in index c607793f423b..d7f070133067 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in +++ b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in @@ -32,6 +32,8 @@ HOST_CPPSRCS = \ stabs_to_module.cc \ stabs_reader.cc \ dwarf_line_to_module.cc \ + arm_ex_reader.cc \ + arm_ex_to_module.cc \ pathname_stripper.cc \ logging.cc \ $(NULL) diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc new file mode 100644 index 000000000000..5d87ab40906c --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc @@ -0,0 +1,502 @@ + +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Derived from libunwind, with extensive modifications. + + +#include "common/arm_ex_reader.h" +#include "common/logging.h" + +#include + +// This file, in conjunction with arm_ex_to_module.cc, translates +// EXIDX unwind information into the same format that Breakpad uses +// for CFI information. Hence Breakpad's CFI unwinding abilities +// also become usable for EXIDX. +// +// See: "Exception Handling ABI for the ARM Architecture", ARM IHI 0038A +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf + +// EXIDX data is presented in two parts: +// +// * an index table. This contains two words per routine, +// the first of which identifies the routine, and the second +// of which is a reference to the unwind bytecode. If the +// bytecode is very compact -- 3 bytes or less -- it can be +// stored directly in the second word. +// +// * an area containing the unwind bytecodes. + +// General flow is: ExceptionTableInfo::Start iterates over all +// of the index table entries (pairs). For each entry, it: +// +// * calls ExceptionTableInfo::ExtabEntryExtract to copy the bytecode +// out into an intermediate buffer. + +// * uses ExceptionTableInfo::ExtabEntryDecode to parse the intermediate +// buffer. Each bytecode instruction is bundled into a +// arm_ex_to_module::extab_data structure, and handed to .. +// +// * .. ARMExToModule::ImproveStackFrame, which in turn hands it to +// ARMExToModule::TranslateCmd, and that generates the pseudo-CFI +// records that Breakpad stores. + +#define ARM_EXIDX_CANT_UNWIND 0x00000001 +#define ARM_EXIDX_COMPACT 0x80000000 +#define ARM_EXTBL_OP_FINISH 0xb0 +#define ARM_EXIDX_TABLE_LIMIT (255*4) + +namespace arm_ex_reader { + +using arm_ex_to_module::ARM_EXIDX_CMD_FINISH; +using arm_ex_to_module::ARM_EXIDX_CMD_SUB_FROM_VSP; +using arm_ex_to_module::ARM_EXIDX_CMD_ADD_TO_VSP; +using arm_ex_to_module::ARM_EXIDX_CMD_REG_POP; +using arm_ex_to_module::ARM_EXIDX_CMD_REG_TO_SP; +using arm_ex_to_module::ARM_EXIDX_CMD_VFP_POP; +using arm_ex_to_module::ARM_EXIDX_CMD_WREG_POP; +using arm_ex_to_module::ARM_EXIDX_CMD_WCGR_POP; +using arm_ex_to_module::ARM_EXIDX_CMD_RESERVED; +using arm_ex_to_module::ARM_EXIDX_CMD_REFUSED; +using arm_ex_to_module::exidx_entry; +using arm_ex_to_module::ARM_EXIDX_VFP_SHIFT_16; +using arm_ex_to_module::ARM_EXIDX_VFP_FSTMD; +using google_breakpad::MemoryRange; + + +static void* Prel31ToAddr(const void* addr) +{ + uint32_t offset32 = *reinterpret_cast(addr); + // sign extend offset32[30:0] to 64 bits -- copy bit 30 to positions + // 63:31 inclusive. + uint64_t offset64 = offset32; + if (offset64 & (1ULL << 30)) + offset64 |= 0xFFFFFFFF80000000ULL; + else + offset64 &= 0x000000007FFFFFFFULL; + return ((char*)addr) + (uintptr_t)offset64; +} + + +// Extract unwind bytecode for the function denoted by |entry| into |buf|, +// and return the number of bytes of |buf| written, along with a code +// indicating the outcome. + +ExceptionTableInfo::ExExtractResult +ExceptionTableInfo::ExtabEntryExtract(const struct exidx_entry* entry, + uint8_t* buf, size_t buf_size, + /*OUT*/size_t* buf_used) +{ + MemoryRange mr_out(buf, buf_size); + + *buf_used = 0; + +# define PUT_BUF_U8(_byte) \ + do { if (!mr_out.Covers(*buf_used, 1)) return ExOutBufOverflow; \ + buf[(*buf_used)++] = (_byte); } while (0) + +# define GET_EX_U32(_lval, _addr, _sec_mr) \ + do { if (!(_sec_mr).Covers(reinterpret_cast(_addr) \ + - (_sec_mr).data(), 4)) \ + return ExInBufOverflow; \ + (_lval) = *(reinterpret_cast(_addr)); } while (0) + +# define GET_EXIDX_U32(_lval, _addr) \ + GET_EX_U32(_lval, _addr, mr_exidx_) +# define GET_EXTAB_U32(_lval, _addr) \ + GET_EX_U32(_lval, _addr, mr_extab_) + + uint32_t data; + GET_EXIDX_U32(data, &entry->data); + + // A function can be marked CANT_UNWIND if (eg) it is known to be + // at the bottom of the stack. + if (data == ARM_EXIDX_CANT_UNWIND) + return ExCantUnwind; + + uint32_t pers; // personality number + uint32_t extra; // number of extra data words required + uint32_t extra_allowed; // number of extra data words allowed + uint32_t* extbl_data; // the handler entry, if not inlined + + if (data & ARM_EXIDX_COMPACT) { + // The handler table entry has been inlined into the index table entry. + // In this case it can only be an ARM-defined compact model, since + // bit 31 is 1. Only personalities 0, 1 and 2 are defined for the + // ARM compact model, but 1 and 2 are "Long format" and may require + // extra data words. Hence the allowable personalities here are: + // personality 0, in which case 'extra' has no meaning + // personality 1, with zero extra words + // personality 2, with zero extra words + extbl_data = NULL; + pers = (data >> 24) & 0x0F; + extra = (data >> 16) & 0xFF; + extra_allowed = 0; + } + else { + // The index table entry is a pointer to the handler entry. Note + // that Prel31ToAddr will read the given address, but we already + // range-checked above. + extbl_data = reinterpret_cast(Prel31ToAddr(&entry->data)); + GET_EXTAB_U32(data, extbl_data); + if (!(data & ARM_EXIDX_COMPACT)) { + // This denotes a "generic model" handler. That will involve + // executing arbitary machine code, which is something we + // can't represent here; hence reject it. + return ExCantRepresent; + } + // So we have a compact model representation. Again, 3 possible + // personalities, but this time up to 255 allowable extra words. + pers = (data >> 24) & 0x0F; + extra = (data >> 16) & 0xFF; + extra_allowed = 255; + extbl_data++; + } + + // Now look at the the handler table entry. The first word is + // |data| and subsequent words start at |*extbl_data|. The number + // of extra words to use is |extra|, provided that the personality + // allows extra words. Even if it does, none may be available -- + // extra_allowed is the maximum number of extra words allowed. */ + if (pers == 0) { + // "Su16" in the documentation -- 3 unwinding insn bytes + // |extra| has no meaning here; instead that byte is an unwind-info byte + PUT_BUF_U8(data >> 16); + PUT_BUF_U8(data >> 8); + PUT_BUF_U8(data); + } + else if ((pers == 1 || pers == 2) && extra <= extra_allowed) { + // "Lu16" or "Lu32" respectively -- 2 unwinding insn bytes, + // and up to 255 extra words. + PUT_BUF_U8(data >> 8); + PUT_BUF_U8(data); + for (uint32_t j = 0; j < extra; j++) { + GET_EXTAB_U32(data, extbl_data); + extbl_data++; + PUT_BUF_U8(data >> 24); + PUT_BUF_U8(data >> 16); + PUT_BUF_U8(data >> 8); + PUT_BUF_U8(data >> 0); + } + } + else { + // The entry is invalid. + return ExInvalid; + } + + // Make sure the entry is terminated with "FINISH" + if (*buf_used > 0 && buf[(*buf_used) - 1] != ARM_EXTBL_OP_FINISH) + PUT_BUF_U8(ARM_EXTBL_OP_FINISH); + + return ExSuccess; + +# undef GET_EXTAB_U32 +# undef GET_EXIDX_U32 +# undef GET_U32 +# undef PUT_BUF_U8 +} + + +// Take the unwind information extracted by ExtabEntryExtract +// and parse it into frame-unwind instructions. These are as +// specified in "Table 4, ARM-defined frame-unwinding instructions" +// in the specification document detailed in comments at the top +// of this file. +// +// This reads from |buf[0, +data_size)|. It checks for overruns of +// the input buffer and returns a negative value if that happens, or +// for any other failure cases. It returns zero in case of success. +int ExceptionTableInfo::ExtabEntryDecode(const uint8_t* buf, size_t buf_size) +{ + if (buf == NULL || buf_size == 0) + return -1; + + MemoryRange mr_in(buf, buf_size); + const uint8_t* buf_initially = buf; + +# define GET_BUF_U8(_lval) \ + do { if (!mr_in.Covers(buf - buf_initially, 1)) return -1; \ + (_lval) = *(buf++); } while (0) + + const uint8_t* end = buf + buf_size; + + while (buf < end) { + struct arm_ex_to_module::extab_data edata; + memset(&edata, 0, sizeof(edata)); + + uint8_t op; + GET_BUF_U8(op); + if ((op & 0xc0) == 0x00) { + // vsp = vsp + (xxxxxx << 2) + 4 + edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP; + edata.data = (((int)op & 0x3f) << 2) + 4; + } + else if ((op & 0xc0) == 0x40) { + // vsp = vsp - (xxxxxx << 2) - 4 + edata.cmd = ARM_EXIDX_CMD_SUB_FROM_VSP; + edata.data = (((int)op & 0x3f) << 2) + 4; + } + else if ((op & 0xf0) == 0x80) { + uint8_t op2; + GET_BUF_U8(op2); + if (op == 0x80 && op2 == 0x00) { + // Refuse to unwind + edata.cmd = ARM_EXIDX_CMD_REFUSED; + } else { + // Pop up to 12 integer registers under masks {r15-r12},{r11-r4} + edata.cmd = ARM_EXIDX_CMD_REG_POP; + edata.data = ((op & 0xf) << 8) | op2; + edata.data = edata.data << 4; + } + } + else if ((op & 0xf0) == 0x90) { + if (op == 0x9d || op == 0x9f) { + // 9d: Reserved as prefix for ARM register to register moves + // 9f: Reserved as perfix for Intel Wireless MMX reg to reg moves + edata.cmd = ARM_EXIDX_CMD_RESERVED; + } else { + // Set vsp = r[nnnn] + edata.cmd = ARM_EXIDX_CMD_REG_TO_SP; + edata.data = op & 0x0f; + } + } + else if ((op & 0xf0) == 0xa0) { + // Pop r4 to r[4+nnn], or + // Pop r4 to r[4+nnn] and r14 or + unsigned end = (op & 0x07); + edata.data = (1 << (end + 1)) - 1; + edata.data = edata.data << 4; + if (op & 0x08) edata.data |= 1 << 14; + edata.cmd = ARM_EXIDX_CMD_REG_POP; + } + else if (op == ARM_EXTBL_OP_FINISH) { + // Finish + edata.cmd = ARM_EXIDX_CMD_FINISH; + buf = end; + } + else if (op == 0xb1) { + uint8_t op2; + GET_BUF_U8(op2); + if (op2 == 0 || (op2 & 0xf0)) { + // Spare + edata.cmd = ARM_EXIDX_CMD_RESERVED; + } else { + // Pop integer registers under mask {r3,r2,r1,r0} + edata.cmd = ARM_EXIDX_CMD_REG_POP; + edata.data = op2 & 0x0f; + } + } + else if (op == 0xb2) { + // vsp = vsp + 0x204 + (uleb128 << 2) + uint64_t offset = 0; + uint8_t byte, shift = 0; + do { + GET_BUF_U8(byte); + offset |= (byte & 0x7f) << shift; + shift += 7; + } while ((byte & 0x80) && buf < end); + edata.data = offset * 4 + 0x204; + edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP; + } + else if (op == 0xb3 || op == 0xc8 || op == 0xc9) { + // b3: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDX-ishly + // c8: Pop VFP regs D[16+ssss] to D[16+ssss+cccc], FSTMFDD-ishly + // c9: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDD-ishly + edata.cmd = ARM_EXIDX_CMD_VFP_POP; + GET_BUF_U8(edata.data); + if (op == 0xc8) edata.data |= ARM_EXIDX_VFP_SHIFT_16; + if (op != 0xb3) edata.data |= ARM_EXIDX_VFP_FSTMD; + } + else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) { + // b8: Pop VFP regs D[8] to D[8+nnn], FSTMFDX-ishly + // d0: Pop VFP regs D[8] to D[8+nnn], FSTMFDD-ishly + edata.cmd = ARM_EXIDX_CMD_VFP_POP; + edata.data = 0x80 | (op & 0x07); + if ((op & 0xf8) == 0xd0) edata.data |= ARM_EXIDX_VFP_FSTMD; + } + else if (op >= 0xc0 && op <= 0xc5) { + // Intel Wireless MMX pop wR[10]-wr[10+nnn], nnn != 6,7 + edata.cmd = ARM_EXIDX_CMD_WREG_POP; + edata.data = 0xa0 | (op & 0x07); + } + else if (op == 0xc6) { + // Intel Wireless MMX pop wR[ssss] to wR[ssss+cccc] + edata.cmd = ARM_EXIDX_CMD_WREG_POP; + GET_BUF_U8(edata.data); + } + else if (op == 0xc7) { + uint8_t op2; + GET_BUF_U8(op2); + if (op2 == 0 || (op2 & 0xf0)) { + // Spare + edata.cmd = ARM_EXIDX_CMD_RESERVED; + } else { + // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} + edata.cmd = ARM_EXIDX_CMD_WCGR_POP; + edata.data = op2 & 0x0f; + } + } + else { + // Spare + edata.cmd = ARM_EXIDX_CMD_RESERVED; + } + + int ret = handler_->ImproveStackFrame(&edata); + if (ret < 0) return ret; + } + return 0; + +# undef GET_BUF_U8 +} + +void ExceptionTableInfo::Start() +{ + const struct exidx_entry* start + = reinterpret_cast(mr_exidx_.data()); + const struct exidx_entry* end + = reinterpret_cast(mr_exidx_.data() + + mr_exidx_.length()); + + // Iterate over each of the EXIDX entries (pairs of 32-bit words). + // These occupy the entire .exidx section. + for (const struct exidx_entry* entry = start; entry < end; ++entry) { + + // Figure out the code address range that this table entry is + // associated with. + uint32_t addr = (reinterpret_cast(Prel31ToAddr(&entry->addr)) + - mapping_addr_ + loading_addr_) & 0x7fffffff; + uint32_t next_addr; + if (entry < end - 1) + next_addr = (reinterpret_cast(Prel31ToAddr(&((entry + 1)->addr))) + - mapping_addr_ + loading_addr_) & 0x7fffffff; + else { + // This is the last EXIDX entry in the sequence, so we don't + // have an address for the start of the next function, to limit + // this one. Instead use the address of the last byte of the + // text section associated with this .exidx section, that we + // have been given. So as to avoid junking up the CFI unwind + // tables with absurdly large address ranges in the case where + // text_last_svma_ is wrong, only use the value if it is nonzero + // and within one page of |addr|. Otherwise assume a length of 1. + // + // In some cases, gcc has been observed to finish the exidx + // section with an entry of length 1 marked CANT_UNWIND, + // presumably exactly for the purpose of giving a definite + // length for the last real entry, without having to look at + // text segment boundaries. + bool plausible = false; + next_addr = addr + 1; + if (text_last_svma_ != 0) { + uint32_t maybe_next_addr = text_last_svma_ + 1; + if (maybe_next_addr > addr && maybe_next_addr - addr <= 4096) { + next_addr = maybe_next_addr; + plausible = true; + } + } + if (!plausible) + BPLOG(INFO) << "ExceptionTableInfo: implausible EXIDX last entry size " + << (int32_t)(text_last_svma_ - addr) + << "; using 1 instead."; + } + + // Extract the unwind info into |buf|. This might fail for + // various reasons. It involves reading both the .exidx and + // .extab sections. All accesses to those sections are + // bounds-checked. + uint8_t buf[ARM_EXIDX_TABLE_LIMIT]; + size_t buf_used = 0; + ExExtractResult res = ExtabEntryExtract(entry, buf, sizeof(buf), &buf_used); + if (res != ExSuccess) { + // Couldn't extract the unwind info, for some reason. Move on. + switch (res) { + case ExInBufOverflow: + BPLOG(INFO) << "ExtabEntryExtract: .exidx/.extab section overrun"; + break; + case ExOutBufOverflow: + BPLOG(INFO) << "ExtabEntryExtract: bytecode buffer overflow"; + break; + case ExCantUnwind: + BPLOG(INFO) << "ExtabEntryExtract: function is marked CANT_UNWIND"; + break; + case ExCantRepresent: + BPLOG(INFO) << "ExtabEntryExtract: bytecode can't be represented"; + break; + case ExInvalid: + BPLOG(INFO) << "ExtabEntryExtract: index table entry is invalid"; + break; + default: + BPLOG(INFO) << "ExtabEntryExtract: unknown error: " << (int)res; + break; + } + continue; + } + + // Finally, work through the unwind instructions in |buf| and + // create CFI entries that Breakpad can use. This can also fail. + // First, add a new stack frame entry, into which ExtabEntryDecode + // will write the CFI entries. + handler_->AddStackFrame(addr, next_addr - addr); + int ret = ExtabEntryDecode(buf, buf_used); + if (ret < 0) { + handler_->DeleteStackFrame(); + BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret; + continue; + } + handler_->SubmitStackFrame(); + + } /* iterating over .exidx */ +} + +} // arm_ex_reader diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h new file mode 100644 index 000000000000..450438e60137 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h @@ -0,0 +1,115 @@ + +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Derived from libunwind, with extensive modifications. + +#ifndef COMMON_ARM_EX_READER_H__ +#define COMMON_ARM_EX_READER_H__ + +#include "common/arm_ex_to_module.h" +#include "common/memory_range.h" + +namespace arm_ex_reader { + +// This class is a reader for ARM unwind information +// from .ARM.exidx and .ARM.extab sections. +class ExceptionTableInfo { + public: + ExceptionTableInfo(const char* exidx, size_t exidx_size, + const char* extab, size_t extab_size, + uint32_t text_last_svma, + arm_ex_to_module::ARMExToModule* handler, + const char* mapping_addr, + uint32_t loading_addr) + : mr_exidx_(google_breakpad::MemoryRange(exidx, exidx_size)), + mr_extab_(google_breakpad::MemoryRange(extab, extab_size)), + text_last_svma_(text_last_svma), + handler_(handler), mapping_addr_(mapping_addr), + loading_addr_(loading_addr) { } + + ~ExceptionTableInfo() { } + + // Parses the entries in .ARM.exidx and possibly + // in .ARM.extab tables, reports what we find to + // arm_ex_to_module::ARMExToModule. + void Start(); + + private: + google_breakpad::MemoryRange mr_exidx_; + google_breakpad::MemoryRange mr_extab_; + uint32_t text_last_svma_; + arm_ex_to_module::ARMExToModule* handler_; + const char* mapping_addr_; + uint32_t loading_addr_; + + enum ExExtractResult { + ExSuccess, // success + ExInBufOverflow, // out-of-range while reading .exidx + ExOutBufOverflow, // output buffer is too small + ExCantUnwind, // this function is marked CANT_UNWIND + ExCantRepresent, // entry valid, but we can't represent it + ExInvalid // entry is invalid + }; + ExExtractResult + ExtabEntryExtract(const struct arm_ex_to_module::exidx_entry* entry, + uint8_t* buf, size_t buf_size, + /*OUT*/size_t* buf_used); + + int ExtabEntryDecode(const uint8_t* buf, size_t buf_size); +}; + +} // namespace arm_ex_reader + +#endif // COMMON_ARM_EX_READER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc new file mode 100644 index 000000000000..27bc51be27ff --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc @@ -0,0 +1,206 @@ + +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Derived from libunwind, with extensive modifications. + +#include "common/unique_string.h" +#include "common/arm_ex_to_module.h" + +#include +#include + +// For big-picture comments on how the EXIDX reader works, +// see arm_ex_reader.cc. + +#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) +#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) +#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) + +using google_breakpad::ustr__pc; +using google_breakpad::ustr__lr; +using google_breakpad::ustr__sp; +using google_breakpad::Module; +using google_breakpad::ToUniqueString; +using google_breakpad::UniqueString; + +namespace arm_ex_to_module { + +// Translate command from extab_data to command for Module. +int ARMExToModule::TranslateCmd(const struct extab_data* edata, + Module::StackFrameEntry* entry, string& vsp) { + int ret = 0; + switch (edata->cmd) { + case ARM_EXIDX_CMD_FINISH: + /* Copy LR to PC if there isn't currently a rule for PC in force. */ + if (entry->initial_rules.find(ustr__pc()) + == entry->initial_rules.end()) { + if (entry->initial_rules.find(ustr__lr()) + == entry->initial_rules.end()) { + entry->initial_rules[ustr__pc()] = Module::Expr("lr"); + } else { + entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()]; + } + } + break; + case ARM_EXIDX_CMD_SUB_FROM_VSP: + { + char c[16]; + sprintf(c, " %d -", edata->data); + vsp += c; + } + break; + case ARM_EXIDX_CMD_ADD_TO_VSP: + { + char c[16]; + sprintf(c, " %d +", edata->data); + vsp += c; + } + break; + case ARM_EXIDX_CMD_REG_POP: + for (unsigned int i = 0; i < 16; i++) { + if (edata->data & (1 << i)) { + entry->initial_rules[ToUniqueString(regnames[i])] + = Module::Expr(vsp + " ^"); + vsp += " 4 +"; + } + } + /* Set cfa in case the SP got popped. */ + if (edata->data & (1 << 13)) { + Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()]; + // It must be a postfix expression (we don't generate anything + // else here), so return -1 to fail out if it isn't. + if (!vsp_expr.isExprPostfix()) { + ret = -1; + break; + }; + vsp = vsp_expr.getExprPostfix(); + } + break; + case ARM_EXIDX_CMD_REG_TO_SP: { + assert (edata->data < 16); + const char* const regname = regnames[edata->data]; + const UniqueString* regname_us = ToUniqueString(regname); + if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) { + entry->initial_rules[ustr__sp()] = Module::Expr(regname); + } else { + entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us]; + } + Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()]; + if (!vsp_expr.isExprPostfix()) { + ret = -1; + break; + }; + vsp = vsp_expr.getExprPostfix(); + break; + } + case ARM_EXIDX_CMD_VFP_POP: + /* Don't recover VFP registers, but be sure to adjust the stack + pointer. */ + for (unsigned int i = ARM_EXBUF_START(edata->data); + i <= ARM_EXBUF_END(edata->data); i++) { + vsp += " 8 +"; + } + if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) { + vsp += " 4 +"; + } + break; + case ARM_EXIDX_CMD_WREG_POP: + for (unsigned int i = ARM_EXBUF_START(edata->data); + i <= ARM_EXBUF_END(edata->data); i++) { + vsp += " 8 +"; + } + break; + case ARM_EXIDX_CMD_WCGR_POP: + // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4" + for (unsigned int i = 0; i < 4; i++) { + if (edata->data & (1 << i)) { + vsp += " 4 +"; + } + } + break; + case ARM_EXIDX_CMD_REFUSED: + case ARM_EXIDX_CMD_RESERVED: + ret = -1; + break; + } + return ret; +} + +void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) { + stack_frame_entry_ = new Module::StackFrameEntry; + stack_frame_entry_->address = addr; + stack_frame_entry_->size = size; + stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp"); + vsp_ = "sp"; +} + +int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) { + return TranslateCmd(edata, stack_frame_entry_, vsp_) ; +} + +void ARMExToModule::DeleteStackFrame() { + delete stack_frame_entry_; +} + +void ARMExToModule::SubmitStackFrame() { + // return address always winds up in pc + stack_frame_entry_->initial_rules[ToUniqueString(kRA)] + = stack_frame_entry_->initial_rules[ustr__pc()]; + // the final value of vsp is the new value of sp + stack_frame_entry_->initial_rules[ustr__sp()] = vsp_; + module_->AddStackFrameEntry(stack_frame_entry_); +} + +} // namespace arm_ex_to_module diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h new file mode 100644 index 000000000000..d35c693226e6 --- /dev/null +++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h @@ -0,0 +1,129 @@ + +/* libunwind - a platform-independent unwind library + Copyright 2011 Linaro Limited + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +// Copyright (c) 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Derived from libunwind, with extensive modifications. + +#ifndef COMMON_ARM_EX_TO_MODULE__ +#define COMMON_ARM_EX_TO_MODULE__ + +#include "common/module.h" + +#include + +namespace arm_ex_to_module { + +using google_breakpad::Module; + +typedef enum extab_cmd { + ARM_EXIDX_CMD_FINISH, + ARM_EXIDX_CMD_SUB_FROM_VSP, + ARM_EXIDX_CMD_ADD_TO_VSP, + ARM_EXIDX_CMD_REG_POP, + ARM_EXIDX_CMD_REG_TO_SP, + ARM_EXIDX_CMD_VFP_POP, + ARM_EXIDX_CMD_WREG_POP, + ARM_EXIDX_CMD_WCGR_POP, + ARM_EXIDX_CMD_RESERVED, + ARM_EXIDX_CMD_REFUSED, +} extab_cmd_t; + +struct exidx_entry { + uint32_t addr; + uint32_t data; +}; + +struct extab_data { + extab_cmd_t cmd; + uint32_t data; +}; + +enum extab_cmd_flags { + ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, + ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX +}; + +const string kRA = ".ra"; +const string kCFA = ".cfa"; + +static const char* const regnames[] = { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "fps", "cpsr" +}; + +// Receives information from arm_ex_reader::ExceptionTableInfo +// and adds it to the Module object +class ARMExToModule { + public: + ARMExToModule(Module* module) + : module_(module) { } + ~ARMExToModule() { } + void AddStackFrame(uintptr_t addr, size_t size); + int ImproveStackFrame(const struct extab_data* edata); + void DeleteStackFrame(); + void SubmitStackFrame(); + private: + Module* module_; + Module::StackFrameEntry* stack_frame_entry_; + string vsp_; + int TranslateCmd(const struct extab_data* edata, + Module::StackFrameEntry* entry, + string& vsp); +}; + +} // namespace arm_ex_to_module + +#endif // COMMON_ARM_EX_TO_MODULE__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc index 172860eb4f35..6eebf3dcd697 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc @@ -52,6 +52,7 @@ #include #include +#include "common/arm_ex_reader.h" #include "common/dwarf/bytereader-inl.h" #include "common/dwarf/dwarf2diehandler.h" #include "common/dwarf_cfi_to_module.h" @@ -70,6 +71,10 @@ #include "common/using_std_string.h" #include "common/logging.h" +#if defined(__ANDROID__) && !defined(SHT_ARM_EXIDX) +# define SHT_ARM_EXIDX (SHT_LOPROC + 1) +#endif + // This namespace contains helper functions. namespace { @@ -345,6 +350,52 @@ bool LoadDwarfCFI(const string& dwarf_filename, return true; } +template +bool LoadARMexidx(const typename ElfClass::Ehdr* elf_header, + const typename ElfClass::Shdr* exidx_section, + const typename ElfClass::Shdr* extab_section, + uint32_t loading_addr, + Module* module) { + // To do this properly we need to know: + // * the bounds of the .ARM.exidx section in the mapped image + // * the bounds of the .ARM.extab section in the mapped image + // * the vma of the last byte in the text section associated with the .exidx + // The first two are easy. The third is a bit tricky. If we can't + // figure out what it is, just pass in zero. + const char *exidx_img + = GetOffset(elf_header, exidx_section->sh_offset); + size_t exidx_size = exidx_section->sh_size; + const char *extab_img + = GetOffset(elf_header, extab_section->sh_offset); + size_t extab_size = extab_section->sh_size; + + // The sh_link field of the exidx section gives the section number + // for the associated text section. + uint32_t exidx_text_last_svma = 0; + int exidx_text_sno = exidx_section->sh_link; + typedef typename ElfClass::Shdr Shdr; + // |sections| points to the section header table + const Shdr* sections + = GetOffset(elf_header, elf_header->e_shoff); + const int num_sections = elf_header->e_shnum; + if (exidx_text_sno >= 0 && exidx_text_sno < num_sections) { + const Shdr* exidx_text_shdr = §ions[exidx_text_sno]; + if (exidx_text_shdr->sh_size > 0) { + exidx_text_last_svma + = exidx_text_shdr->sh_addr + exidx_text_shdr->sh_size - 1; + } + } + + arm_ex_to_module::ARMExToModule handler(module); + arm_ex_reader::ExceptionTableInfo + parser(exidx_img, exidx_size, extab_img, extab_size, exidx_text_last_svma, + &handler, + reinterpret_cast(elf_header), + loading_addr); + parser.Start(); + return true; +} + bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper, void** elf_header) { int obj_fd = open(obj_file.c_str(), O_RDONLY); @@ -634,6 +685,29 @@ bool LoadSymbols(const string& obj_file, } } + // ARM has special unwind tables that can be used. + const Shdr* arm_exidx_section = + FindElfSectionByName(".ARM.exidx", SHT_ARM_EXIDX, + sections, names, names_end, + elf_header->e_shnum); + const Shdr* arm_extab_section = + FindElfSectionByName(".ARM.extab", SHT_PROGBITS, + sections, names, names_end, + elf_header->e_shnum); + // Only load information from this section if there isn't a .debug_info + // section. + if (!found_debug_info_section + && arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) { + info->LoadedSection(".ARM.exidx"); + info->LoadedSection(".ARM.extab"); + bool result = LoadARMexidx(elf_header, + arm_exidx_section, arm_extab_section, + loading_addr, module); + found_usable_info = found_usable_info || result; + if (result) + BPLOG(INFO) << "LoadSymbols: read EXIDX from .ARM.{exidx,extab}"; + } + if (!found_debug_info_section && symbol_data != ONLY_CFI) { fprintf(stderr, "%s: file contains no debugging information" " (no \".stab\" or \".debug_info\" sections)\n", diff --git a/toolkit/crashreporter/google-breakpad/src/common/module.cc b/toolkit/crashreporter/google-breakpad/src/common/module.cc index 1edacbced506..5b3d334ec397 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/module.cc +++ b/toolkit/crashreporter/google-breakpad/src/common/module.cc @@ -258,7 +258,7 @@ bool Module::ReportError() { } std::ostream& operator<<(std::ostream& stream, const Module::Expr& expr) { - assert(!expr.invalid()); + assert(!expr.isExprInvalid()); switch (expr.how_) { case Module::kExprSimple: stream << expr.ident_ << " " << expr.offset_ << " +"; diff --git a/toolkit/crashreporter/google-breakpad/src/common/module.h b/toolkit/crashreporter/google-breakpad/src/common/module.h index f67274749e6a..ef894f83397c 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/module.h +++ b/toolkit/crashreporter/google-breakpad/src/common/module.h @@ -165,7 +165,14 @@ class Module { offset_ = 0; how_ = kExprInvalid; } - bool invalid() const { return how_ == kExprInvalid; } + bool isExprInvalid() const { return how_ == kExprInvalid; } + bool isExprPostfix() const { return how_ == kExprPostfix; } + + // Return the postfix expression string. This is only + // meaningful on Exprs for which isExprPostfix returns true. + // In all other cases it returns an empty string. + string getExprPostfix() const { return postfix_; } + bool operator==(const Expr& other) const { return how_ == other.how_ && ident_ == other.ident_ && diff --git a/toolkit/crashreporter/google-breakpad/src/common/moz.build b/toolkit/crashreporter/google-breakpad/src/common/moz.build index 7412aae93c2c..9c146f81aefd 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/moz.build +++ b/toolkit/crashreporter/google-breakpad/src/common/moz.build @@ -31,6 +31,8 @@ if CONFIG['OS_TARGET'] != 'WINNT': 'language.cc', 'dwarf/dwarf2diehandler.cc', 'dwarf_line_to_module.cc', + 'arm_ex_reader.cc', + 'arm_ex_to_module.cc', ] if CONFIG['OS_ARCH'] == 'Linux': diff --git a/toolkit/crashreporter/google-breakpad/src/common/unique_string.h b/toolkit/crashreporter/google-breakpad/src/common/unique_string.h index e551a750ae18..9db3d7519621 100644 --- a/toolkit/crashreporter/google-breakpad/src/common/unique_string.h +++ b/toolkit/crashreporter/google-breakpad/src/common/unique_string.h @@ -235,6 +235,27 @@ inline static const UniqueString* ustr__ZDra() { return us; } +// "pc" +inline static const UniqueString* ustr__pc() { + static const UniqueString* us = NULL; + if (!us) us = ToUniqueString("pc"); + return us; +} + +// "lr" +inline static const UniqueString* ustr__lr() { + static const UniqueString* us = NULL; + if (!us) us = ToUniqueString("lr"); + return us; +} + +// "sp" +inline static const UniqueString* ustr__sp() { + static const UniqueString* us = NULL; + if (!us) us = ToUniqueString("sp"); + return us; +} + template class UniqueStringMap { diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc index a043f9c19e25..ebaf4533e827 100644 --- a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc +++ b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc @@ -54,7 +54,7 @@ bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap ®isters, RegisterValueMap *caller_registers) const { // If there are not rules for both .ra and .cfa in effect at this address, // don't use this CFI data for stack walking. - if (cfa_rule_.invalid() || ra_rule_.invalid()) + if (cfa_rule_.isExprInvalid() || ra_rule_.isExprInvalid()) return false; RegisterValueMap working; @@ -105,10 +105,10 @@ template bool CFIFrameInfo::FindCallerRegs( string CFIFrameInfo::Serialize() const { std::ostringstream stream; - if (!cfa_rule_.invalid()) { + if (!cfa_rule_.isExprInvalid()) { stream << ".cfa: " << cfa_rule_; } - if (!ra_rule_.invalid()) { + if (!ra_rule_.isExprInvalid()) { if (static_cast(stream.tellp()) != 0) stream << " "; stream << ".ra: " << ra_rule_; From 422cdcd4f2cd0ff70ac0ad611bc67e6771be8e8d Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Thu, 25 Apr 2013 13:56:43 -0400 Subject: [PATCH 030/615] Bug 844852 - Run GTest on make check. r=ted --HG-- extra : rebase_source : dabb338ee02acf390dabf1cda8ed6d89f8857fdf --- gfx/tests/gtest/TestTiledLayerBuffer.cpp | 1 - testing/gtest/Makefile.in | 1 + testing/gtest/mozilla/GTestRunner.cpp | 29 +++++ testing/gtest/rungtests.py | 129 +++++++++++++++++++++++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 testing/gtest/rungtests.py diff --git a/gfx/tests/gtest/TestTiledLayerBuffer.cpp b/gfx/tests/gtest/TestTiledLayerBuffer.cpp index 2909fd7d3724..339558c7dddc 100644 --- a/gfx/tests/gtest/TestTiledLayerBuffer.cpp +++ b/gfx/tests/gtest/TestTiledLayerBuffer.cpp @@ -68,7 +68,6 @@ TEST(TiledLayerBuffer, TileStart) { TEST(TiledLayerBuffer, EmptyUpdate) { TestTiledLayerBuffer buffer; - nsRegion::InitStatic(); nsIntRegion validRegion(nsIntRect(0, 0, 10, 10)); buffer.TestUpdate(validRegion, validRegion); diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in index e332f819606f..f6c6d5e5da8c 100644 --- a/testing/gtest/Makefile.in +++ b/testing/gtest/Makefile.in @@ -45,6 +45,7 @@ check gtest:: ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) $(MAKE) -C $(DEPTH)/browser/app repackage endif + $(PYTHON) $(topsrcdir)/testing/gtest/rungtests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) endif endif diff --git a/testing/gtest/mozilla/GTestRunner.cpp b/testing/gtest/mozilla/GTestRunner.cpp index 863c4242058d..6fd15d6d1be1 100644 --- a/testing/gtest/mozilla/GTestRunner.cpp +++ b/testing/gtest/mozilla/GTestRunner.cpp @@ -7,6 +7,10 @@ #include "gtest/gtest.h" #include "mozilla/Attributes.h" #include "mozilla/NullPtr.h" +#ifdef MOZ_CRASHREPORTER +#include "nsICrashReporter.h" +#endif +#include "testing/TestHarness.h" #include "prenv.h" using ::testing::EmptyTestEventListener; @@ -78,6 +82,31 @@ int RunGTestFunc() PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort"); + ScopedXPCOM xpcom("AsyncPanZoomController"); + +#ifdef MOZ_CRASHREPORTER + nsCOMPtr crashreporter; + char *crashreporterStr = PR_GetEnv("MOZ_CRASHREPORTER"); + if (crashreporterStr && !strcmp(crashreporterStr, "1")) { + //TODO: move this to an even-more-common location to use in all + // C++ unittests + crashreporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1"); + if (crashreporter) { + std::cerr << "Setting up crash reporting" << std::endl; + + nsCOMPtr dirsvc = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); + nsCOMPtr cwd; + nsresult rv = dirsvc->Get(NS_OS_CURRENT_WORKING_DIR, + NS_GET_IID(nsIFile), + getter_AddRefs(cwd)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + crashreporter->SetEnabled(true); + crashreporter->SetMinidumpPath(cwd); + } + } +#endif + return RUN_ALL_TESTS(); } diff --git a/testing/gtest/rungtests.py b/testing/gtest/rungtests.py new file mode 100644 index 000000000000..803a87be90c0 --- /dev/null +++ b/testing/gtest/rungtests.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# 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/. + +from __future__ import with_statement +import sys, os, tempfile, shutil +from optparse import OptionParser +import mozprocess, mozinfo, mozlog, mozcrash +from contextlib import contextmanager + +log = mozlog.getLogger('gtests') + +class GTests(object): + # Time (seconds) to wait for test process to complete + TEST_PROC_TIMEOUT = 1200 + # Time (seconds) in which process will be killed if it produces no output. + TEST_PROC_NO_OUTPUT_TIMEOUT = 300 + + def run_gtest(self, prog, xre_path, symbols_path=None): + """ + Run a single C++ unit test program. + + Arguments: + * prog: The path to the test program to run. + * env: The environment to use for running the program. + * symbols_path: A path to a directory containing Breakpad-formatted + symbol files for producing stack traces on crash. + + Return True if the program exits with a zero status, False otherwise. + """ + self.xre_path = xre_path + env = self.build_environment() + basename = os.path.basename(prog) + log.info("Running test %s", basename) + proc = mozprocess.ProcessHandler([prog, "-unittest"], + cwd=os.getcwd(), + env=env) + #TODO: After bug 811320 is fixed, don't let .run() kill the process, + # instead use a timeout in .wait() and then kill to get a stack. + proc.run(timeout=GTests.TEST_PROC_TIMEOUT, + outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) + proc.wait() + if proc.timedOut: + log.testFail("%s | timed out after %d seconds", + basename, GTests.TEST_PROC_TIMEOUT) + return False + if mozcrash.check_for_crashes(os.getcwd(), symbols_path, + test_name=basename): + log.testFail("%s | test crashed", basename) + return False + result = proc.proc.returncode == 0 + if not result: + log.testFail("%s | test failed with return code %d", + basename, proc.proc.returncode) + return result + + def build_core_environment(self, env = {}): + """ + Add environment variables likely to be used across all platforms, including remote systems. + """ + env["MOZILLA_FIVE_HOME"] = self.xre_path + env["MOZ_XRE_DIR"] = self.xre_path + env["XPCOM_DEBUG_BREAK"] = "stack-and-abort" + env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" + env["MOZ_CRASHREPORTER"] = "1" + env["MOZ_RUN_GTEST"] = "1" + # Normally we run with GTest default output, override this to use the TBPL test format. + env["MOZ_TBPL_PARSER"] = "1" + return env + + def build_environment(self): + """ + Create and return a dictionary of all the appropriate env variables and values. + On a remote system, we overload this to set different values and are missing things like os.environ and PATH. + """ + if not os.path.isdir(self.xre_path): + raise Exception("xre_path does not exist: %s", self.xre_path) + env = dict(os.environ) + env = self.build_core_environment(env) + pathvar = "" + if mozinfo.os == "linux": + pathvar = "LD_LIBRARY_PATH" + elif mozinfo.os == "mac": + pathvar = "DYLD_LIBRARY_PATH" + elif mozinfo.os == "win": + pathvar = "PATH" + if pathvar: + if pathvar in env: + env[pathvar] = "%s%s%s" % (self.xre_path, os.pathsep, env[pathvar]) + else: + env[pathvar] = self.xre_path + return env + +class gtestOptions(OptionParser): + def __init__(self): + OptionParser.__init__(self) + self.add_option("--xre-path", + action = "store", type = "string", dest = "xre_path", + default = None, + help = "absolute path to directory containing XRE (probably xulrunner)") + self.add_option("--symbols-path", + action = "store", type = "string", dest = "symbols_path", + default = None, + help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols") + +def main(): + parser = gtestOptions() + options, args = parser.parse_args() + if not args: + print >>sys.stderr, """Usage: %s """ % sys.argv[0] + sys.exit(1) + if not options.xre_path: + print >>sys.stderr, """Error: --xre-path is required""" + sys.exit(1) + prog = os.path.abspath(args[0]) + options.xre_path = os.path.abspath(options.xre_path) + tester = GTests() + try: + result = tester.run_gtest(prog, options.xre_path, options.symbols_path) + except Exception, e: + log.error(str(e)) + result = False + sys.exit(0 if result else 1) + +if __name__ == '__main__': + main() + From 3df775367ad7687c87f757f02c0f76ae79a2f638 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Fri, 14 Jun 2013 09:46:28 +0200 Subject: [PATCH 031/615] Bug 882111 part 1 - Some js::Interpret cleanup. r=luke --- js/src/vm/Interpreter.cpp | 76 +++++++++++++++------------------------ js/src/vm/Interpreter.h | 25 ------------- 2 files changed, 28 insertions(+), 73 deletions(-) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index a9a224f43dec..f251b8106916 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -280,6 +280,9 @@ js::ValueToCallable(JSContext *cx, const Value &v, int numToSkip, MaybeConstruct return NULL; } +static JS_NEVER_INLINE bool +Interpret(JSContext *cx, StackFrame *entryFrame); + bool js::RunScript(JSContext *cx, StackFrame *fp) { @@ -342,7 +345,7 @@ js::RunScript(JSContext *cx, StackFrame *fp) } #endif - return Interpret(cx, fp) != Interpret_Error; + return Interpret(cx, fp); } /* @@ -985,13 +988,12 @@ js::IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval) return js_IteratorNext(cx, iterobj, rval); } -JS_NEVER_INLINE InterpretStatus -js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool useNewType) +static JS_NEVER_INLINE bool +Interpret(JSContext *cx, StackFrame *entryFrame) { JSAutoResolveFlags rf(cx, RESOLVE_INFER); - if (interpMode == JSINTERP_NORMAL) - gc::MaybeVerifyBarriers(cx, true); + gc::MaybeVerifyBarriers(cx, true); JS_ASSERT(!cx->compartment()->activeAnalysis); @@ -1060,8 +1062,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool script = (s); \ if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts) \ interrupts.enable(); \ - JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP, \ - script->hasAnyBreakpointsOrStepMode()); \ JS_END_MACRO /* Repoint cx->regs to a local variable for faster access. */ @@ -1128,43 +1128,28 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool /* State communicated between non-local jumps: */ bool interpReturnOK; - /* Don't call the script prologue if executing between Method and Trace JIT. */ - if (interpMode == JSINTERP_NORMAL) { - StackFrame *fp = regs.fp(); - if (!fp->isGeneratorFrame()) { - if (!fp->prologue(cx)) - goto error; - } else { - Probes::enterScript(cx, script, script->function(), fp); - } - if (cx->compartment()->debugMode()) { - JSTrapStatus status = ScriptDebugPrologue(cx, fp); - switch (status) { - case JSTRAP_CONTINUE: - break; - case JSTRAP_RETURN: - interpReturnOK = true; - goto forced_return; - case JSTRAP_THROW: - case JSTRAP_ERROR: - goto error; - default: - JS_NOT_REACHED("bad ScriptDebugPrologue status"); - } + if (!entryFrame->isGeneratorFrame()) { + if (!entryFrame->prologue(cx)) + goto error; + } else { + Probes::enterScript(cx, script, script->function(), entryFrame); + } + if (cx->compartment()->debugMode()) { + JSTrapStatus status = ScriptDebugPrologue(cx, entryFrame); + switch (status) { + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + interpReturnOK = true; + goto forced_return; + case JSTRAP_THROW: + case JSTRAP_ERROR: + goto error; + default: + JS_NOT_REACHED("bad ScriptDebugPrologue status"); } } - /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */ - if (interpMode == JSINTERP_REJOIN) - interpMode = JSINTERP_NORMAL; - - /* - * The RETHROW mode acts like a bailout mode, except that it resume an - * exception instead of resuming the script. - */ - if (interpMode == JSINTERP_RETHROW) - goto error; - /* * It is important that "op" be initialized before calling DO_OP because * it is possible for "op" to be specially assigned during the normal @@ -1240,7 +1225,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool if (script->hasAnyBreakpointsOrStepMode()) moreInterrupts = true; - if (script->hasBreakpointsAt(regs.pc) && interpMode != JSINTERP_SKIP_TRAP) { + if (script->hasBreakpointsAt(regs.pc)) { RootedValue rval(cx); JSTrapStatus status = Debugger::onTrap(cx, &rval); switch (status) { @@ -1260,8 +1245,6 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode, bool JS_ASSERT(rval.isInt32() && rval.toInt32() == op); } - interpMode = JSINTERP_NORMAL; - switchMask = moreInterrupts ? -1 : 0; switchOp = int(op); goto do_switch; @@ -3022,9 +3005,6 @@ END_CASE(JSOP_ARRAYPUSH) JS_ASSERT(&cx->regs() == ®s); JS_ASSERT(uint32_t(regs.pc - script->code) < script->length); - /* When rejoining, we must not err before finishing Interpret's prologue. */ - JS_ASSERT(interpMode != JSINTERP_REJOIN); - if (cx->isExceptionPending()) { /* Call debugger throw hooks. */ if (cx->compartment()->debugMode()) { @@ -3149,7 +3129,7 @@ END_CASE(JSOP_ARRAYPUSH) leave_on_safe_point: #endif - return interpReturnOK ? Interpret_Ok : Interpret_Error; + return interpReturnOK; } bool diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 61605bb508dd..f46b63d048ac 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -164,31 +164,6 @@ ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Va extern bool Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval); -/* Flags to toggle js::Interpret() execution. */ -enum InterpMode -{ - JSINTERP_NORMAL = 0, /* interpreter is running normally */ - JSINTERP_REJOIN = 1, /* as normal, but the frame has already started */ - JSINTERP_SKIP_TRAP = 2, /* as REJOIN, but skip trap at first opcode */ - JSINTERP_BAILOUT = 3, /* interpreter is running from an Ion bailout */ - JSINTERP_RETHROW = 4 /* as BAILOUT, but unwind all frames */ -}; - -enum InterpretStatus -{ - Interpret_Error = 0, /* interpreter had an error */ - Interpret_Ok = 1, /* interpreter executed successfully */ - Interpret_OSR = 2 /* when mode=BAILOUT and we should OSR into Ion */ -}; - -/* - * Execute the caller-initialized frame for a user-defined script or function - * pointed to by cx->fp until completion or error. - */ -extern JS_NEVER_INLINE InterpretStatus -Interpret(JSContext *cx, StackFrame *stopFp, InterpMode mode = JSINTERP_NORMAL, - bool useNewType = false); - extern bool RunScript(JSContext *cx, StackFrame *fp); From 85d4cce0e51c878ad901e088b9fbdf0447e3b251 Mon Sep 17 00:00:00 2001 From: "Nicholas D. Matsakis" Date: Thu, 6 Jun 2013 11:01:15 -0400 Subject: [PATCH 032/615] Bug 880208 - Add UnsafeGet and UnsafeGetImmutable intrinsics r=djvj --- js/src/builtin/ParallelArray.js | 37 +++++++++--------- js/src/ion/IonBuilder.cpp | 34 +++++++++++------ js/src/ion/IonBuilder.h | 18 ++++++++- js/src/ion/MCallOptimize.cpp | 31 +++++++++++++++- js/src/ion/MIR.h | 15 ++++++-- js/src/jscntxt.h | 3 ++ js/src/vm/SelfHosting.cpp | 66 +++++++++++++++++++++++++++++---- 7 files changed, 163 insertions(+), 41 deletions(-) diff --git a/js/src/builtin/ParallelArray.js b/js/src/builtin/ParallelArray.js index 98213378053a..0a2db707446f 100644 --- a/js/src/builtin/ParallelArray.js +++ b/js/src/builtin/ParallelArray.js @@ -377,7 +377,7 @@ function ParallelArrayMap(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = self.shape[0]; + var length = UnsafeGetImmutableElement(self.shape, 0); var buffer = NewDenseArray(length); parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc @@ -432,7 +432,7 @@ function ParallelArrayReduce(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = self.shape[0]; + var length = UnsafeGetImmutableElement(self.shape, 0); if (length === 0) ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY); @@ -519,7 +519,7 @@ function ParallelArrayScan(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = self.shape[0]; + var length = UnsafeGetImmutableElement(self.shape, 0); if (length === 0) ThrowError(JSMSG_PAR_ARRAY_REDUCE_EMPTY); @@ -726,7 +726,7 @@ function ParallelArrayScatter(targets, defaultValue, conflictFunc, length, mode) var self = this; if (length === undefined) - length = self.shape[0]; + length = UnsafeGetImmutableElement(self.shape, 0); // The Divide-Scatter-Vector strategy: // 1. Slice |targets| array of indices ("scatter-vector") into N @@ -977,7 +977,7 @@ function ParallelArrayFilter(func, mode) { // FIXME(bug 844887): Check |IsCallable(func)| var self = this; - var length = self.shape[0]; + var length = UnsafeGetImmutableElement(self.shape, 0); parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc if (ShouldForceSequential()) @@ -1151,6 +1151,11 @@ function ParallelArrayFlatten() { function ParallelArrayGet1(i) { if (i === undefined) return undefined; + + // We could use UnsafeGetImmutableElement here, but I am not doing + // so (for the moment) since using the default path enables + // bounds-check hoisting, which is (currently) not possible + // otherwise. return this.buffer[this.offset + i]; } @@ -1158,27 +1163,25 @@ function ParallelArrayGet1(i) { * Specialized variant of get() for two-dimensional case */ function ParallelArrayGet2(x, y) { - var xDimension = this.shape[0]; - var yDimension = this.shape[1]; - if (x === undefined) - return undefined; - if (x >= xDimension) + var xDimension = UnsafeGetImmutableElement(this.shape, 0); + var yDimension = UnsafeGetImmutableElement(this.shape, 1); + if (x === undefined || TO_INT32(x) !== x || x >= xDimension) return undefined; if (y === undefined) return NewParallelArray(ParallelArrayView, [yDimension], this.buffer, this.offset + x * yDimension); - if (y >= yDimension) + if (TO_INT32(y) !== y || y >= yDimension) return undefined; var offset = y + x * yDimension; - return this.buffer[this.offset + offset]; + return UnsafeGetImmutableElement(this.buffer, this.offset + offset); } /** * Specialized variant of get() for three-dimensional case */ function ParallelArrayGet3(x, y, z) { - var xDimension = this.shape[0]; - var yDimension = this.shape[1]; - var zDimension = this.shape[2]; + var xDimension = UnsafeGetImmutableElement(this.shape, 0); + var yDimension = UnsafeGetImmutableElement(this.shape, 1); + var zDimension = UnsafeGetImmutableElement(this.shape, 2); if (x === undefined) return undefined; if (x >= xDimension) @@ -1194,7 +1197,7 @@ function ParallelArrayGet3(x, y, z) { if (z >= zDimension) return undefined; var offset = z + y*zDimension + x * yDimension * zDimension; - return this.buffer[this.offset + offset]; + return UnsafeGetImmutableElement(this.buffer, this.offset + offset); } /** @@ -1228,7 +1231,7 @@ function ParallelArrayGetN(...coords) { /** The length property yields the outermost dimension */ function ParallelArrayLength() { - return this.shape[0]; + return UnsafeGetImmutableElement(this.shape, 0); } function ParallelArrayToString() { diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 4d8786b3b11a..4d35f622915a 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -6264,8 +6264,11 @@ IonBuilder::jsop_getelem() if (ElementAccessIsDenseNative(obj, index)) { // Don't generate a fast path if there have been bounds check failures // and this access might be on a sparse property. - if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_) - return jsop_getelem_dense(); + if (!ElementAccessHasExtraIndexedProperty(cx, obj) || !failedBoundsCheck_) { + MDefinition *id = current->pop(); + MDefinition *obj = current->pop(); + return jsop_getelem_dense(GetElem_Normal, obj, id); + } } int arrayType = TypedArray::TYPE_MAX; @@ -6330,11 +6333,8 @@ IonBuilder::jsop_getelem() } bool -IonBuilder::jsop_getelem_dense() +IonBuilder::jsop_getelem_dense(GetElemSafety safety, MDefinition *obj, MDefinition *id) { - MDefinition *id = current->pop(); - MDefinition *obj = current->pop(); - types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc); if (JSOp(*pc) == JSOP_CALLELEM && !id->mightBeType(MIRType_String) && types->noConstraints()) { @@ -6351,6 +6351,7 @@ IonBuilder::jsop_getelem_dense() // undefined values have been observed at this access site and the access // cannot hit another indexed property on the object or its prototypes. bool readOutOfBounds = + safety == GetElem_Normal && types->hasType(types::Type::UndefinedType()) && !ElementAccessHasExtraIndexedProperty(cx, obj); @@ -6387,9 +6388,6 @@ IonBuilder::jsop_getelem_dense() if (loadDouble) elements = addConvertElementsToDoubles(elements); - MInitializedLength *initLength = MInitializedLength::New(elements); - current->add(initLength); - MInstruction *load; if (!readOutOfBounds) { @@ -6397,14 +6395,28 @@ IonBuilder::jsop_getelem_dense() // in-bounds elements, and the array is packed or its holes are not // read. This is the best case: we can separate the bounds check for // hoisting. - id = addBoundsCheck(id, initLength); + switch (safety) { + case GetElem_Normal: { + MInitializedLength *initLength = MInitializedLength::New(elements); + current->add(initLength); + id = addBoundsCheck(id, initLength); + break; + } - load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble); + case GetElem_Unsafe: break; + case GetElem_UnsafeImmutable: break; + } + + bool knownImmutable = (safety == GetElem_UnsafeImmutable); + load = MLoadElement::New(elements, id, needsHoleCheck, loadDouble, + knownImmutable); current->add(load); } else { // This load may return undefined, so assume that we *can* read holes, // or that we can read out-of-bounds accesses. In this case, the bounds // check is part of the opcode. + MInitializedLength *initLength = MInitializedLength::New(elements); + current->add(initLength); load = MLoadElementHole::New(elements, id, initLength, needsHoleCheck); current->add(load); diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index e1a47e2c01da..d918f84eca56 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -41,6 +41,20 @@ class IonBuilder : public MIRGenerator SetElem_Unsafe, }; + enum GetElemSafety { + // Normal read like a[b] + GetElem_Normal, + + // Read due to UnsafeGetElement: + // - assumed to be in bounds, + GetElem_Unsafe, + + // Read due to UnsafeGetImmutableElement: + // - assumed to be in bounds, + // - assumed not to alias any stores + GetElem_UnsafeImmutable, + }; + struct DeferredEdge : public TempObject { MBasicBlock *block; @@ -391,7 +405,7 @@ class IonBuilder : public MIRGenerator bool jsop_intrinsic(HandlePropertyName name); bool jsop_bindname(PropertyName *name); bool jsop_getelem(); - bool jsop_getelem_dense(); + bool jsop_getelem_dense(GetElemSafety safety, MDefinition *object, MDefinition *index); bool jsop_getelem_typed(int arrayType); bool jsop_getelem_typed_static(bool *psucceeded); bool jsop_getelem_string(); @@ -486,6 +500,8 @@ class IonBuilder : public MIRGenerator InliningStatus inlineUnsafeSetElement(CallInfo &callInfo); bool inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base); bool inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, uint32_t base, int arrayType); + InliningStatus inlineUnsafeGetElement(CallInfo &callInfo, + GetElemSafety safety); InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo); InliningStatus inlineNewDenseArray(CallInfo &callInfo); InliningStatus inlineNewDenseArrayForSequentialExecution(CallInfo &callInfo); diff --git a/js/src/ion/MCallOptimize.cpp b/js/src/ion/MCallOptimize.cpp index e2691532e577..06cb9a79297f 100644 --- a/js/src/ion/MCallOptimize.cpp +++ b/js/src/ion/MCallOptimize.cpp @@ -90,6 +90,10 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native) // Array intrinsics. if (native == intrinsic_UnsafeSetElement) return inlineUnsafeSetElement(callInfo); + if (native == intrinsic_UnsafeGetElement) + return inlineUnsafeGetElement(callInfo, GetElem_Unsafe); + if (native == intrinsic_UnsafeGetImmutableElement) + return inlineUnsafeGetElement(callInfo, GetElem_UnsafeImmutable); if (native == intrinsic_NewDenseArray) return inlineNewDenseArray(callInfo); @@ -952,9 +956,10 @@ IonBuilder::inlineUnsafeSetElement(CallInfo &callInfo) /* Important: * * Here we inline each of the stores resulting from a call to - * %UnsafeSetElement(). It is essential that these stores occur + * UnsafeSetElement(). It is essential that these stores occur * atomically and cannot be interrupted by a stack or recursion * check. If this is not true, race conditions can occur. + * See definition of UnsafeSetElement() for more details. */ for (uint32_t base = 0; base < argc; base += 3) { @@ -1053,6 +1058,30 @@ IonBuilder::inlineUnsafeSetTypedArrayElement(CallInfo &callInfo, return true; } +IonBuilder::InliningStatus +IonBuilder::inlineUnsafeGetElement(CallInfo &callInfo, + GetElemSafety safety) +{ + JS_ASSERT(safety != GetElem_Normal); + + uint32_t argc = callInfo.argc(); + if (argc < 2 || callInfo.constructing()) + return InliningStatus_NotInlined; + const uint32_t obj = 0; + const uint32_t index = 1; + if (!ElementAccessIsDenseNative(callInfo.getArg(obj), + callInfo.getArg(index))) + return InliningStatus_NotInlined; + if (ElementAccessHasExtraIndexedProperty(cx, callInfo.getArg(obj))) + return InliningStatus_NotInlined; + callInfo.unwrapArgs(); + if (!jsop_getelem_dense(safety, + callInfo.getArg(obj), + callInfo.getArg(index))) + return InliningStatus_Error; + return InliningStatus_Inlined; +} + IonBuilder::InliningStatus IonBuilder::inlineForceSequentialOrInParallelSection(CallInfo &callInfo) { diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 4450915e2a9c..3a36021cb223 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -4510,11 +4510,13 @@ class MLoadElement { bool needsHoleCheck_; bool loadDoubles_; + bool knownImmutable_; // load of data that is known to be immutable - MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles) + MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles, bool knownImmutable) : MBinaryInstruction(elements, index), needsHoleCheck_(needsHoleCheck), - loadDoubles_(loadDoubles) + loadDoubles_(loadDoubles), + knownImmutable_(knownImmutable) { setResultType(MIRType_Value); setMovable(); @@ -4526,8 +4528,10 @@ class MLoadElement INSTRUCTION_HEADER(LoadElement) static MLoadElement *New(MDefinition *elements, MDefinition *index, - bool needsHoleCheck, bool loadDoubles) { - return new MLoadElement(elements, index, needsHoleCheck, loadDoubles); + bool needsHoleCheck, bool loadDoubles, + bool knownImmutable) { + return new MLoadElement(elements, index, needsHoleCheck, loadDoubles, + knownImmutable); } TypePolicy *typePolicy() { @@ -4549,6 +4553,9 @@ class MLoadElement return needsHoleCheck(); } AliasSet getAliasSet() const { + if (knownImmutable_) + return AliasSet::None(); + return AliasSet::Load(AliasSet::Element); } }; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 1a01b6cda11d..337eaa2bd899 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -2360,6 +2360,9 @@ JSBool intrinsic_IsCallable(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp); +JSBool intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp); +JSBool intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc, + Value *vp); JSBool intrinsic_ShouldForceSequential(JSContext *cx, unsigned argc, Value *vp); JSBool intrinsic_NewParallelArray(JSContext *cx, unsigned argc, Value *vp); diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index a3f7798046d8..20addd06ae27 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -341,15 +341,26 @@ js::intrinsic_NewDenseArray(JSContext *cx, unsigned argc, Value *vp) /* * UnsafeSetElement(arr0, idx0, elem0, ..., arrN, idxN, elemN): For * each set of (arr, idx, elem) arguments that are passed, performs - * the assignment |arr[idx] = elem|. |arr| must be either a dense array + * the assignment `arr[idx] = elem`. `arr` must be either a dense array * or a typed array. * - * If |arr| is a dense array, the index must be an int32 less than the - * initialized length of |arr|. Use |%EnsureDenseResultArrayElements| - * to ensure that the initialized length is long enough. + * If `arr` is a dense array, the index must be an int32 less than the + * initialized length of `arr`. Use `NewDenseAllocatedArray` to ensure + * that the initialized length is long enough. * - * If |arr| is a typed array, the index must be an int32 less than the - * length of |arr|. + * If `arr` is a typed array, the index must be an int32 less than the + * length of `arr`. + * + * The reason that `UnsafeSetElement` takes multiple + * array/index/element triples is not for convenience but rather for + * semantic reasons: there are a few places in the parallel code where + * correctness relies on the fact that *all of the assignments occur + * or none of them*. This occurs in operations like reduce or fold + * which mutate the same data in place. That is, we do not want to + * bail out or interrupt in between the individual assignments. To + * convey this notion, we place all the assignments together into one + * `UnsafeSetElement` call. It is preferable to use multiple calls if + * it is not important that the assignments occur all-or-nothing. */ JSBool js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) @@ -380,7 +391,6 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) } else { JS_ASSERT(idx < TypedArray::length(arrobj)); RootedValue tmp(cx, args[elemi]); - // XXX: Always non-strict. if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false)) return false; } @@ -390,6 +400,46 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp) return true; } +/* + * UnsafeGetElement(arr, idx)=elem: + * + * Loads an element from an array. Requires that `arr` be a dense + * array and `idx` be in bounds. In ion compiled code, no bounds + * check will be emitted. + */ +JSBool +js::intrinsic_UnsafeGetElement(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + const uint32_t arri = 0; + const uint32_t idxi = 1; + + JS_ASSERT(args[arri].isObject()); + JS_ASSERT(args[idxi].isInt32()); + + RootedObject arrobj(cx, &args[arri].toObject()); + uint32_t idx = args[idxi].toInt32(); + + JS_ASSERT(args[arri].toObject().isNative()); + JS_ASSERT(idx < arrobj->getDenseInitializedLength()); + args.rval().set(arrobj->getDenseElement(idx)); + return true; +} + +/* + * UnsafeGetImmutableElement(arr, idx)=elem: + * + * Same as `UnsafeGetElement(arr, idx)`, except that the array is + * known by the self-hosting code to be immutable. Therefore, ion + * compilation can reorder this load freely with respect to stores. + */ +JSBool +js::intrinsic_UnsafeGetImmutableElement(JSContext *cx, unsigned argc, Value *vp) +{ + return intrinsic_UnsafeGetElement(cx, argc, vp); +} + /* * ParallelTestsShouldPass(): Returns false if we are running in a * mode (such as --ion-eager) that is known to cause additional @@ -468,6 +518,8 @@ const JSFunctionSpec intrinsic_functions[] = { JS_FN("NewParallelArray", intrinsic_NewParallelArray, 3,0), JS_FN("NewDenseArray", intrinsic_NewDenseArray, 1,0), JS_FN("UnsafeSetElement", intrinsic_UnsafeSetElement, 3,0), + JS_FN("UnsafeGetElement", intrinsic_UnsafeGetElement, 2,0), + JS_FN("UnsafeGetImmutableElement", intrinsic_UnsafeGetImmutableElement, 2,0), JS_FN("ShouldForceSequential", intrinsic_ShouldForceSequential, 0,0), JS_FN("ParallelTestsShouldPass", intrinsic_ParallelTestsShouldPass, 0,0), From 196a0e94e43a5b4649cda54de0e750fde738cf51 Mon Sep 17 00:00:00 2001 From: Shelly Lin Date: Fri, 14 Jun 2013 15:16:41 +0800 Subject: [PATCH 033/615] Bug 882956 - Fix WebAudio stack-buffer-overflow crash. r=ehsan. --- content/media/AudioSegment.cpp | 2 +- content/media/AudioSegment.h | 6 ++++-- content/media/test/crashtests/882956.html | 15 +++++++++++++++ content/media/test/crashtests/crashtests.list | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 content/media/test/crashtests/882956.html diff --git a/content/media/AudioSegment.cpp b/content/media/AudioSegment.cpp index 7ccce0d8138d..03e6d5691b5e 100644 --- a/content/media/AudioSegment.cpp +++ b/content/media/AudioSegment.cpp @@ -171,7 +171,7 @@ AudioSegment::WriteTo(AudioStream* aOutput) if (channelData.Length() > outputChannels) { // Down-mix. DownmixAndInterleave(channelData, c.mBufferFormat, duration, - c.mVolume, channelData.Length(), buf.Elements()); + c.mVolume, outputChannels, buf.Elements()); } else { InterleaveAndConvertBuffer(channelData.Elements(), c.mBufferFormat, duration, c.mVolume, diff --git a/content/media/AudioSegment.h b/content/media/AudioSegment.h index 3ff5b70f326c..7000dc82f2bb 100644 --- a/content/media/AudioSegment.h +++ b/content/media/AudioSegment.h @@ -30,9 +30,11 @@ void InterleaveAndConvertBuffer(const void** aSourceChannels, int32_t aLength, float aVolume, int32_t aChannels, AudioDataValue* aOutput); + /** - * Down-mix audio channels, and interleave the channel data. A total of - * aOutputChannels*aDuration interleaved samples will be stored into aOutput. + * Given an array of input channels (aChannelData), downmix to aOutputChannels, + * interleave the channel data. A total of aOutputChannels*aDuration + * interleaved samples will be copied to a channel buffer in aOutput. */ void DownmixAndInterleave(const nsTArray& aChannelData, AudioSampleFormat aSourceFormat, int32_t aDuration, diff --git a/content/media/test/crashtests/882956.html b/content/media/test/crashtests/882956.html new file mode 100644 index 000000000000..ae7b441f9993 --- /dev/null +++ b/content/media/test/crashtests/882956.html @@ -0,0 +1,15 @@ + diff --git a/content/media/test/crashtests/crashtests.list b/content/media/test/crashtests/crashtests.list index 95a9a9350263..3ea3632778c4 100644 --- a/content/media/test/crashtests/crashtests.list +++ b/content/media/test/crashtests/crashtests.list @@ -46,3 +46,4 @@ load 880384.html load 880404.html load 880724.html load 881775.html +load 882956.html From fa1f6986fde6eb9e1b044c389f701a7e574b9195 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Fri, 14 Jun 2013 05:58:28 -0600 Subject: [PATCH 034/615] Bug 678037 - Enable lazy JS parsing and fix various bugs, r=waldo,evilpie,nobody. --- js/src/frontend/BytecodeCompiler.cpp | 71 ++++++++----- js/src/frontend/BytecodeEmitter.cpp | 22 +++- js/src/frontend/NameFunctions.cpp | 4 +- js/src/frontend/Parser.cpp | 84 ++++++++++----- js/src/frontend/SharedContext.h | 4 + js/src/frontend/SyntaxParseHandler.h | 11 +- js/src/frontend/TokenStream.cpp | 5 +- js/src/frontend/TokenStream.h | 8 +- js/src/ion/AsmJS.cpp | 2 +- js/src/ion/BaselineIC.cpp | 3 + js/src/ion/CodeGenerator.cpp | 4 + js/src/ion/IonBuilder.cpp | 2 + js/src/ion/ParallelArrayAnalysis.cpp | 8 +- js/src/ion/ParallelFunctions.cpp | 2 + js/src/jit-test/tests/basic/functionnames.js | 4 +- js/src/jit-test/tests/basic/lazyparse.js | 36 +++++++ .../basic/testOOMInAutoEnterCompartment.js | 9 +- js/src/jsapi.cpp | 4 +- js/src/jsapi.h | 2 +- js/src/jscompartment.cpp | 79 +++++++++++++- js/src/jsfun.cpp | 25 +++-- js/src/jsfun.h | 9 -- js/src/jsgc.cpp | 6 +- js/src/jsgc.h | 2 +- js/src/jsinferinlines.h | 32 +++--- js/src/jsscript.cpp | 93 +++++++++++++--- js/src/jsscript.h | 100 ++++++++++-------- js/src/vm/Debugger.cpp | 22 ---- 28 files changed, 447 insertions(+), 206 deletions(-) create mode 100644 js/src/jit-test/tests/basic/lazyparse.js diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 862fb8f8a7d3..215dcc6389a0 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -74,6 +74,15 @@ CheckArgumentsWithinEval(JSContext *cx, Parser &parser, Handle return true; } +inline bool +CanLazilyParse(JSContext *cx, const CompileOptions &options) +{ + return options.canLazilyParse && + options.compileAndGo && + options.sourcePolicy == CompileOptions::SAVE_SOURCE && + !cx->compartment()->debugMode(); +} + JSScript * frontend::CompileScript(JSContext *cx, HandleObject scopeChain, HandleScript evalCaller, @@ -102,7 +111,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, return NULL; if (options.filename && !ss->setFilename(cx, options.filename)) return NULL; - + JS::RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, ss)); if (!sourceObject) return NULL; @@ -120,28 +129,21 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, break; } + bool canLazilyParse = CanLazilyParse(cx, options); + Maybe > syntaxParser; - if (options.canLazilyParse) { + if (canLazilyParse) { syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false, (Parser *) NULL, (LazyScript *) NULL); } Parser parser(cx, options, chars, length, /* foldConstants = */ true, - options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL); + canLazilyParse ? &syntaxParser.ref() : NULL, NULL); parser.sct = sct; GlobalSharedContext globalsc(cx, scopeChain, StrictModeFromContext(cx)); - // Syntax parsing may cause us to restart processing of top level - // statements in the script. Use Maybe<> so that the parse context can be - // reset when this occurs. - Maybe > pc; - - pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0); - if (!pc.ref().init()) - return NULL; - bool savedCallerFun = options.compileAndGo && evalCaller && @@ -169,6 +171,15 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, if (!bce.init()) return NULL; + // Syntax parsing may cause us to restart processing of top level + // statements in the script. Use Maybe<> so that the parse context can be + // reset when this occurs. + Maybe > pc; + + pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0); + if (!pc.ref().init()) + return NULL; + /* If this is a direct call to eval, inherit the caller's strictness. */ if (evalCaller && evalCaller->strict) globalsc.strict = true; @@ -313,32 +324,34 @@ bool frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *lazy, const jschar *chars, size_t length) { - CompileOptions options(cx); + JS_ASSERT(cx->compartment() == fun->compartment()); + + CompileOptions options(cx, lazy->version()); options.setPrincipals(cx->compartment()->principals) - .setOriginPrincipals(lazy->parent()->originPrincipals) - .setVersion(lazy->parent()->getVersion()) - .setFileAndLine(lazy->parent()->filename(), lazy->lineno()) + .setOriginPrincipals(lazy->originPrincipals()) + .setFileAndLine(lazy->source()->filename(), lazy->lineno()) .setColumn(lazy->column()) - .setCompileAndGo(lazy->parent()->compileAndGo) + .setCompileAndGo(true) .setNoScriptRval(false) .setSelfHostingMode(false); Parser parser(cx, options, chars, length, /* foldConstants = */ true, NULL, lazy); - RootedObject enclosingScope(cx, lazy->parent()->function()); + RootedObject enclosingScope(cx, lazy->parentFunction()); - ParseNode *pn = parser.standaloneLazyFunction(fun, lazy->parent()->staticLevel + 1, - lazy->strict()); + ParseNode *pn = parser.standaloneLazyFunction(fun, lazy->staticLevel(), lazy->strict()); if (!pn) return false; - JS::RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, lazy->source())); - if (!sourceObject) + if (!NameFunctions(cx, pn)) return false; + JS::RootedScriptSource sourceObject(cx, lazy->sourceObject()); + JS_ASSERT(sourceObject); + Rooted script(cx, JSScript::Create(cx, enclosingScope, false, - options, lazy->parent()->staticLevel + 1, + options, lazy->staticLevel(), sourceObject, lazy->begin(), lazy->end())); if (!script) return false; @@ -347,11 +360,11 @@ frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *laz if (lazy->directlyInsideEval()) script->directlyInsideEval = true; - - bool hasGlobalScope = lazy->parent()->compileAndGo; + if (lazy->usesArgumentsAndApply()) + script->usesArgumentsAndApply = true; BytecodeEmitter bce(/* parent = */ NULL, &parser, pn->pn_funbox, script, options.forEval, - /* evalCaller = */ NullPtr(), hasGlobalScope, + /* evalCaller = */ NullPtr(), /* hasGlobalScope = */ true, options.lineno, BytecodeEmitter::LazyFunction); if (!bce.init()) return false; @@ -385,8 +398,10 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO return false; } + bool canLazilyParse = CanLazilyParse(cx, options); + Maybe > syntaxParser; - if (options.canLazilyParse) { + if (canLazilyParse) { syntaxParser.construct(cx, options, chars, length, /* foldConstants = */ false, (Parser *) NULL, (LazyScript *) NULL); @@ -395,7 +410,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO JS_ASSERT(!options.forEval); Parser parser(cx, options, chars, length, /* foldConstants = */ true, - options.canLazilyParse ? &syntaxParser.ref() : NULL, NULL); + canLazilyParse ? &syntaxParser.ref() : NULL, NULL); parser.sct = &sct; JS_ASSERT(fun); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 5a07cd3e21b8..a31cb3593d44 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1128,11 +1128,22 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn) * resolving upvar accesses within the inner function. */ if (bce->emitterMode == BytecodeEmitter::LazyFunction) { + // The only statements within a lazy function which can push lexical + // scopes are try/catch blocks. Use generic ops in this case. + for (StmtInfoBCE *stmt = bce->topStmt; stmt; stmt = stmt->down) { + switch (stmt->type) { + case STMT_TRY: + case STMT_FINALLY: + return true; + default:; + } + } + size_t hops = 0; FunctionBox *funbox = bce->sc->asFunctionBox(); if (funbox->hasExtensibleScope()) return false; - if (funbox->function()->atom() == pn->pn_atom) + if (funbox->function()->isNamedLambda() && funbox->function()->atom() == pn->pn_atom) return false; if (funbox->function()->isHeavyweight()) { hops++; @@ -4491,8 +4502,10 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) return false; if (fun->isInterpretedLazy()) { - if (!fun->lazyScript()->parent()) - fun->lazyScript()->initParent(bce->script); + if (!fun->lazyScript()->sourceObject()) { + JSFunction *parent = bce->sc->isFunctionBox() ? bce->sc->asFunctionBox()->function() : NULL; + fun->lazyScript()->setParent(parent, bce->script->sourceObject(), bce->script->originPrincipals); + } } else { SharedContext *outersc = bce->sc; @@ -4557,6 +4570,9 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) /* We measured the max scope depth when we parsed the function. */ if (!EmitFunctionScript(cx, &bce2, pn->pn_body)) return false; + + if (funbox->usesArguments && funbox->usesApply) + script->usesArgumentsAndApply = true; } } diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 109f22ce47c9..76f55000eab7 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -175,8 +175,6 @@ class NameResolver JSAtom *resolveFun(ParseNode *pn, HandleAtom prefix) { JS_ASSERT(pn != NULL && pn->isKind(PNK_FUNCTION)); RootedFunction fun(cx, pn->pn_funbox->function()); - if (nparents == 0) - return NULL; StringBuffer buf(cx); this->buf = &buf; @@ -184,7 +182,7 @@ class NameResolver /* If the function already has a name, use that */ if (fun->displayAtom() != NULL) { if (prefix == NULL) - return fun->atom(); + return fun->displayAtom(); if (!buf.append(prefix) || !buf.append("/") || !buf.append(fun->displayAtom())) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 97580b021f3f..22805ff9995c 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -419,9 +419,6 @@ Parser::Parser(JSContext *cx, const CompileOptions &options, abortedSyntaxParse(false), handler(cx, tokenStream, foldConstants, syntaxParser, lazyOuterFunction) { - // XXX bug 678037 always disable syntax parsing for now. - handler.disableSyntaxParser(); - cx->runtime()->activeCompilations++; // The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings @@ -487,6 +484,8 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu inGenexpLambda(false), useAsm(false), insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()), + usesArguments(false), + usesApply(false), funCxFlags() { JS_ASSERT(fun->isTenured()); @@ -925,6 +924,7 @@ Parser::checkFunctionArguments() dn->pn_dflags |= PND_IMPLICITARGUMENTS; if (!pc->define(context, arguments, dn, Definition::VAR)) return false; + pc->sc->asFunctionBox()->usesArguments = true; break; } } @@ -1014,11 +1014,15 @@ template <> bool Parser::checkFunctionArguments() { - if (pc->sc->asFunctionBox()->function()->hasRest()) { - if (pc->lexdeps->lookup(context->names().arguments)) { + bool hasRest = pc->sc->asFunctionBox()->function()->hasRest(); + + if (pc->lexdeps->lookup(context->names().arguments)) { + pc->sc->asFunctionBox()->usesArguments = true; + if (hasRest) { report(ParseError, false, null(), JSMSG_ARGUMENTS_AND_REST); return false; } + } else if (hasRest) { DefinitionNode maybeArgDef = pc->decls().lookupFirst(context->names().arguments); if (maybeArgDef && handler.getDefinitionKind(maybeArgDef) != Definition::ARG) { report(ParseError, false, null(), JSMSG_ARGUMENTS_AND_REST); @@ -1341,14 +1345,6 @@ Parser::leaveFunction(ParseNode *fn, HandlePropertyName funNam continue; } - /* - * If there are no uses of this placeholder (e.g., it was created - * for an identifierName that turned out to be a label), there is - * nothing left to do. - */ - if (!dn->dn_uses) - continue; - Definition *outer_dn = outerpc->decls().lookupFirst(atom); /* @@ -2046,7 +2042,7 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox *funbo size_t numFreeVariables = pc->lexdeps->count(); size_t numInnerFunctions = pc->innerFunctions.length(); - LazyScript *lazy = LazyScript::Create(context, numFreeVariables, numInnerFunctions, + LazyScript *lazy = LazyScript::Create(context, numFreeVariables, numInnerFunctions, versionNumber(), funbox->bufStart, funbox->bufEnd, funbox->startLine, funbox->startColumn); if (!lazy) @@ -2064,6 +2060,8 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox *funbo if (pc->sc->strict) lazy->setStrict(); + if (funbox->usesArguments && funbox->usesApply) + lazy->setUsesArgumentsAndApply(); PropagateTransitiveParseFlags(funbox, lazy); funbox->object->toFunction()->initLazyScript(lazy); @@ -2173,6 +2171,11 @@ Parser::functionArgsAndBody(Node pn, HandleFunction fun, *becameStrict = false; ParseContext *outerpc = pc; + // As from a full parse handler, abort if functions are defined within + // lexical scopes. + if (pc->topScopeStmt) + return abortIfSyntaxParser(); + // Create box for fun->object early to protect against last-ditch GC. FunctionBox *funbox = newFunctionBox(fun, pc, strict); if (!funbox) @@ -4099,6 +4102,7 @@ Parser::forStatement() /* Check that the left side of the 'in' or 'of' is valid. */ if (!forDecl && lhsNode != SyntaxParseHandler::NodeName && + lhsNode != SyntaxParseHandler::NodeGetProp && lhsNode != SyntaxParseHandler::NodeLValue) { JS_ALWAYS_FALSE(abortIfSyntaxParser()); @@ -4311,12 +4315,15 @@ Parser::tryStatement() return pn; } -template -typename ParseHandler::Node -Parser::withStatement() +template <> +ParseNode * +Parser::withStatement() { - if (!abortIfSyntaxParser()) + if (handler.syntaxParser) { + handler.disableSyntaxParser(); + abortedSyntaxParse = true; return null(); + } JS_ASSERT(tokenStream.isCurrentTokenType(TOK_WITH)); uint32_t begin = tokenStream.currentToken().pos.begin; @@ -4354,7 +4361,7 @@ Parser::withStatement() * to safely optimize binding globals (see bug 561923). */ for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) { - DefinitionNode defn = r.front().value().get(); + DefinitionNode defn = r.front().value().get(); DefinitionNode lexdep = handler.resolve(defn); handler.deoptimizeUsesWithin(lexdep, TokenPos::make(begin, tokenStream.currentToken().pos.begin)); @@ -4369,6 +4376,14 @@ Parser::withStatement() return pn; } +template <> +SyntaxParseHandler::Node +Parser::withStatement() +{ + JS_ALWAYS_FALSE(abortIfSyntaxParser()); + return null(); +} + #if JS_HAS_BLOCK_SCOPE template <> ParseNode * @@ -5235,8 +5250,12 @@ bool Parser::setAssignmentLhsOps(Node pn, JSOp op) { /* Full syntax checking of valid assignment LHS terms requires a parse tree. */ - if (pn != SyntaxParseHandler::NodeName && pn != SyntaxParseHandler::NodeLValue) + if (pn != SyntaxParseHandler::NodeName && + pn != SyntaxParseHandler::NodeGetProp && + pn != SyntaxParseHandler::NodeLValue) + { return abortIfSyntaxParser(); + } return checkStrictAssignment(pn); } @@ -5419,8 +5438,12 @@ Parser::checkDeleteExpression(Node *pn) // Treat deletion of non-lvalues as ambiguous, so that any error associated // with deleting a call expression is reported. - if (*pn != SyntaxParseHandler::NodeLValue && strictMode()) + if (*pn != SyntaxParseHandler::NodeGetProp && + *pn != SyntaxParseHandler::NodeLValue && + strictMode()) + { return abortIfSyntaxParser(); + } return true; } @@ -6444,10 +6467,13 @@ Parser::memberExpr(TokenKind tt, bool allowCallSyntax) } } else if (JSAtom *atom = handler.isGetProp(lhs)) { /* Select JSOP_FUNAPPLY given foo.apply(...). */ - if (atom == context->names().apply) + if (atom == context->names().apply) { handler.setOp(nextMember, JSOP_FUNAPPLY); - else if (atom == context->names().call) + if (pc->sc->isFunctionBox()) + pc->sc->asFunctionBox()->usesApply = true; + } else if (atom == context->names().call) { handler.setOp(nextMember, JSOP_FUNCALL); + } } handler.setBeginPosition(nextMember, lhs); @@ -6551,7 +6577,17 @@ template <> SyntaxParseHandler::Node Parser::newRegExp(const jschar *buf, size_t length, RegExpFlag flags) { - return SyntaxParseHandler::NodeGeneric; + // Create the regexp even when doing a syntax parse, to check the regexp's syntax. + const StableCharPtr chars(buf, length); + RegExpStatics *res = context->regExpStatics(); + + RegExpObject *reobj; + if (context->hasfp()) + reobj = RegExpObject::create(context, res, chars.get(), length, flags, &tokenStream); + else + reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream); + + return reobj ? SyntaxParseHandler::NodeGeneric : SyntaxParseHandler::NodeFailure; } template diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index ae17cf1e3a2e..3b6d02cfc322 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -210,6 +210,10 @@ class FunctionBox : public ObjectBox, public SharedContext bool useAsm:1; /* function contains "use asm" directive */ bool insideUseAsm:1; /* nested function of function of "use asm" directive */ + // Fields for use in heuristics. + bool usesArguments:1; /* contains a free use of 'arguments' */ + bool usesApply:1; /* contains an f.apply() call */ + FunctionContextFlags funCxFlags; template diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 19f411f5becc..a4e963f28318 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -32,6 +32,7 @@ class SyntaxParseHandler NodeFailure = 0, NodeGeneric, NodeName, + NodeGetProp, NodeString, NodeStringExprStatement, NodeLValue @@ -102,7 +103,11 @@ class SyntaxParseHandler return NodeGeneric; } Node newDebuggerStatement(const TokenPos &pos) { return NodeGeneric; } - Node newPropertyAccess(Node pn, PropertyName *name, uint32_t end) { return NodeLValue; } + Node newPropertyAccess(Node pn, PropertyName *name, uint32_t end) + { + lastAtom = name; + return NodeGetProp; + } Node newPropertyByValue(Node pn, Node kid, uint32_t end) { return NodeLValue; } bool addCatchBlock(Node catchList, Node letBlock, @@ -159,7 +164,9 @@ class SyntaxParseHandler PropertyName *isName(Node pn) { return (pn == NodeName) ? lastAtom->asPropertyName() : NULL; } - PropertyName *isGetProp(Node pn) { return NULL; } + PropertyName *isGetProp(Node pn) { + return (pn == NodeGetProp) ? lastAtom->asPropertyName() : NULL; + } JSAtom *isStringExprStatement(Node pn, TokenPos *pos) { if (pn == NodeStringExprStatement) { *pos = lastStringPos; diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index e658b8bbef78..6c83d6434afa 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -557,7 +557,7 @@ TokenStream::advance(size_t position) void TokenStream::tell(Position *pos) { - pos->buf = userbuf.addressOfNextRawChar(); + pos->buf = userbuf.addressOfNextRawChar(/* allowPoisoned = */ true); pos->flags = flags; pos->lineno = lineno; pos->linebase = linebase; @@ -571,7 +571,7 @@ TokenStream::tell(Position *pos) void TokenStream::seek(const Position &pos) { - userbuf.setAddressOfNextRawChar(pos.buf); + userbuf.setAddressOfNextRawChar(pos.buf, /* allowPoisoned = */ true); flags = pos.flags; lineno = pos.lineno; linebase = pos.linebase; @@ -587,6 +587,7 @@ void TokenStream::seek(const Position &pos, const TokenStream &other) { srcCoords.fill(other.srcCoords); + lastFunctionKeyword = other.lastFunctionKeyword; seek(pos); } diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index 941b6401dbe3..278a2360cc3e 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -832,14 +832,14 @@ class MOZ_STACK_CLASS TokenStream ptr--; } - const jschar *addressOfNextRawChar() const { - JS_ASSERT(ptr); /* make sure haven't been poisoned */ + const jschar *addressOfNextRawChar(bool allowPoisoned = false) const { + JS_ASSERT_IF(!allowPoisoned, ptr); /* make sure haven't been poisoned */ return ptr; } /* Use this with caution! */ - void setAddressOfNextRawChar(const jschar *a) { - JS_ASSERT(a); + void setAddressOfNextRawChar(const jschar *a, bool allowPoisoned = false) { + JS_ASSERT_IF(!allowPoisoned, a); ptr = a; } diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 378ae3f3c412..1686ac240c3c 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -6264,7 +6264,7 @@ AsmJSModule::~AsmJSModule() if (!exitDatum.fun) continue; - if (!exitDatum.fun->isInterpreted()) + if (!exitDatum.fun->hasScript()) continue; JSScript *script = exitDatum.fun->nonLazyScript(); diff --git a/js/src/ion/BaselineIC.cpp b/js/src/ion/BaselineIC.cpp index 871d92018b37..6a5fcb9f188c 100644 --- a/js/src/ion/BaselineIC.cpp +++ b/js/src/ion/BaselineIC.cpp @@ -1324,6 +1324,9 @@ ICUpdatedStub::addUpdateStubForValue(JSContext *cx, HandleScript script, HandleO return true; } + if (!obj->getType(cx)) + return false; + types::EnsureTrackPropertyTypes(cx, obj, id); if (val.isPrimitive()) { diff --git a/js/src/ion/CodeGenerator.cpp b/js/src/ion/CodeGenerator.cpp index 53e18ba9d6c7..a8b5b8df7eb4 100644 --- a/js/src/ion/CodeGenerator.cpp +++ b/js/src/ion/CodeGenerator.cpp @@ -1694,6 +1694,10 @@ CodeGenerator::visitCallKnown(LCallKnown *call) return true; } + // The calleereg is known to be a non-native function, but might point to + // a LazyScript instead of a JSScript. + masm.branchIfFunctionHasNoScript(calleereg, &uncompiled); + // Knowing that calleereg is a non-native function, load the JSScript. masm.loadPtr(Address(calleereg, JSFunction::offsetOfNativeOrScript()), objreg); diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp index 4d35f622915a..defa2286ded3 100644 --- a/js/src/ion/IonBuilder.cpp +++ b/js/src/ion/IonBuilder.cpp @@ -200,6 +200,8 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes, targets.clear(); return true; } + if (!typeObj->interpretedFunction->getOrCreateScript(cx)) + return false; DebugOnly appendOk = targets.append(typeObj->interpretedFunction); JS_ASSERT(appendOk); diff --git a/js/src/ion/ParallelArrayAnalysis.cpp b/js/src/ion/ParallelArrayAnalysis.cpp index 3a34014bda1c..84b40624a1f2 100644 --- a/js/src/ion/ParallelArrayAnalysis.cpp +++ b/js/src/ion/ParallelArrayAnalysis.cpp @@ -856,14 +856,18 @@ GetPossibleCallees(JSContext *cx, if (!rootedFun->isInterpreted()) continue; - if (rootedFun->nonLazyScript()->shouldCloneAtCallsite) { + rootedScript = rootedFun->getOrCreateScript(cx); + if (!rootedScript) + return false; + + if (rootedScript->shouldCloneAtCallsite) { rootedFun = CloneFunctionAtCallsite(cx, rootedFun, script, pc); if (!rootedFun) return false; + rootedScript = rootedFun->nonLazyScript(); } // check if this call target is already known - rootedScript = rootedFun->nonLazyScript(); if (!AddCallTarget(rootedScript, targets)) return false; } diff --git a/js/src/ion/ParallelFunctions.cpp b/js/src/ion/ParallelFunctions.cpp index c1572f07ce29..f05894ac1490 100644 --- a/js/src/ion/ParallelFunctions.cpp +++ b/js/src/ion/ParallelFunctions.cpp @@ -434,6 +434,8 @@ ion::ParCallToUncompiledScript(JSFunction *func) JSScript *script = func->nonLazyScript(); Spew(SpewBailouts, "Call to uncompiled script: %p:%s:%d", script, script->filename(), script->lineno); + } else if (func->isInterpretedLazy()) { + Spew(SpewBailouts, "Call to uncompiled lazy script"); } else if (func->isBoundFunction()) { int depth = 0; JSFunction *target = func->getBoundFunctionTarget()->toFunction(); diff --git a/js/src/jit-test/tests/basic/functionnames.js b/js/src/jit-test/tests/basic/functionnames.js index 1f89047143eb..92fbf258c634 100644 --- a/js/src/jit-test/tests/basic/functionnames.js +++ b/js/src/jit-test/tests/basic/functionnames.js @@ -36,7 +36,7 @@ var Foo = function (){ assertName(arguments.callee, 'Foo<') return function(){}; }(); -assertName(Foo, 'Foo'); +assertName(Foo, 'Foo:( + foo = evalcx("(function foo() { foo.bar() })"); + foo.bar = evalcx("(function bar() {})"); + + fatty(); +} diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 828bd264e51b..b3f120e12c56 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5289,10 +5289,10 @@ AutoFile::open(JSContext *cx, const char *filename) } -JS::CompileOptions::CompileOptions(JSContext *cx) +JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version) : principals(NULL), originPrincipals(NULL), - version(cx->findVersion()), + version(version != JSVERSION_UNKNOWN ? version : cx->findVersion()), versionSet(false), utf8(false), filename(NULL), diff --git a/js/src/jsapi.h b/js/src/jsapi.h index fb8790bdef0f..f3c62a1d825d 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3907,7 +3907,7 @@ struct JS_PUBLIC_API(CompileOptions) { SAVE_SOURCE } sourcePolicy; - explicit CompileOptions(JSContext *cx); + explicit CompileOptions(JSContext *cx, JSVersion version = JSVERSION_UNKNOWN); CompileOptions &setPrincipals(JSPrincipals *p) { principals = p; return *this; } CompileOptions &setOriginPrincipals(JSPrincipals *p) { originPrincipals = p; return *this; } CompileOptions &setVersion(JSVersion v) { version = v; versionSet = true; return *this; } diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 48b8459d7890..63074e509eed 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -603,6 +603,77 @@ JSCompartment::hasScriptsOnStack() return false; } +static bool +AddInnerLazyFunctionsFromScript(JSScript *script, AutoObjectVector &lazyFunctions) +{ + if (!script->hasObjects()) + return true; + ObjectArray *objects = script->objects(); + for (size_t i = script->innerObjectsStart(); i < objects->length; i++) { + JSObject *obj = objects->vector[i]; + if (obj->isFunction() && obj->toFunction()->isInterpretedLazy()) { + if (!lazyFunctions.append(obj)) + return false; + } + } + return true; +} + +static bool +CreateLazyScriptsForCompartment(JSContext *cx) +{ + AutoObjectVector lazyFunctions(cx); + + // Find all root lazy functions in the compartment: those which have not been + // compiled and which have a source object, indicating that their parent has + // been compiled. + for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) { + JSObject *obj = i.get(); + if (obj->compartment() == cx->compartment() && obj->isFunction()) { + JSFunction *fun = obj->toFunction(); + if (fun->isInterpretedLazy()) { + LazyScript *lazy = fun->lazyScript(); + if (lazy->sourceObject() && !lazy->maybeScript()) { + if (!lazyFunctions.append(fun)) + return false; + } + } + } + } + + // Create scripts for each lazy function, updating the list of functions to + // process with any newly exposed inner functions in created scripts. + // A function cannot be delazified until its outer script exists. + for (size_t i = 0; i < lazyFunctions.length(); i++) { + JSFunction *fun = lazyFunctions[i]->toFunction(); + + // lazyFunctions may have been populated with multiple functions for + // a lazy script. + if (!fun->isInterpretedLazy()) + continue; + + JSScript *script = fun->getOrCreateScript(cx); + if (!script) + return false; + if (!AddInnerLazyFunctionsFromScript(script, lazyFunctions)) + return false; + } + + // Repoint any clones of the original functions to their new script. + for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) { + JSObject *obj = i.get(); + if (obj->compartment() == cx->compartment() && obj->isFunction()) { + JSFunction *fun = obj->toFunction(); + if (fun->isInterpretedLazy()) { + JS_ASSERT(fun->lazyScript()->maybeScript()); + JS_ALWAYS_TRUE(fun->getOrCreateScript(cx)); + } + } + } + + return true; +} + bool JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeGC &dmgc) { @@ -626,6 +697,8 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeGC &dmgc) JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE); return false; } + if (enabledAfter && !CreateLazyScriptsForCompartment(cx)) + return false; } debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0); @@ -677,10 +750,14 @@ JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global) bool JSCompartment::addDebuggee(JSContext *cx, - js::GlobalObject *global, + GlobalObject *globalArg, AutoDebugModeGC &dmgc) { + Rooted global(cx, globalArg); + bool wasEnabled = debugMode(); + if (!wasEnabled && !CreateLazyScriptsForCompartment(cx)) + return false; if (!debuggees.put(global)) { js_ReportOutOfMemory(cx); return false; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index aa763956641e..b88955aad9dd 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -350,9 +350,11 @@ js::XDRInterpretedFunction(XDRState *xdr, HandleObject enclosingScope, Han return false; } firstword = !!fun->atom(); - flagsword = (fun->nargs << 16) | fun->flags; + script = fun->getOrCreateScript(cx); + if (!script) + return false; atom = fun->atom(); - script = fun->nonLazyScript(); + flagsword = (fun->nargs << 16) | fun->flags; } else { fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr(), JSFunction::FinalizeKind, TenuredObject); @@ -1057,9 +1059,10 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti if (cx->zone()->needsBarrier()) LazyScript::writeBarrierPre(lazy); + fun->flags &= ~INTERPRETED_LAZY; + fun->flags |= INTERPRETED; + if (JSScript *script = lazy->maybeScript()) { - fun->flags &= ~INTERPRETED_LAZY; - fun->flags |= INTERPRETED; fun->initScript(script); /* @@ -1072,10 +1075,9 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti return true; } - /* Lazily parsed script. */ - const jschar *chars = lazy->source()->chars(cx); - if (!chars) - return false; + fun->initScript(NULL); + + JS_ASSERT(lazy->source()->hasSourceData()); /* * GC must be suppressed for the remainder of the lazy parse, as any @@ -1083,9 +1085,10 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext *cx, HandleFuncti */ AutoSuppressGC suppressGC(cx); - fun->flags &= ~INTERPRETED_LAZY; - fun->flags |= INTERPRETED; - fun->initScript(NULL); + /* Lazily parsed script. */ + const jschar *chars = lazy->source()->chars(cx); + if (!chars) + return false; const jschar *lazyStart = chars + lazy->begin(); size_t lazyLength = lazy->end() - lazy->begin(); diff --git a/js/src/jsfun.h b/js/src/jsfun.h index c93557a90ea8..e5d060a0e831 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -142,7 +142,6 @@ class JSFunction : public JSObject // Can be called multiple times by the parser. void setArgCount(uint16_t nargs) { - JS_ASSERT(this->nargs == 0 || this->nargs == nargs); this->nargs = nargs; } @@ -186,13 +185,6 @@ class JSFunction : public JSObject flags |= EXPR_CLOSURE; } - void markNotLazy() { - JS_ASSERT(isInterpretedLazy()); - JS_ASSERT(hasScript()); - flags |= INTERPRETED; - flags &= ~INTERPRETED_LAZY; - } - JSAtom *atom() const { return hasGuessedAtom() ? NULL : atom_.get(); } js::PropertyName *name() const { return hasGuessedAtom() || !atom_ ? NULL : atom_->asPropertyName(); } inline void initAtom(JSAtom *atom); @@ -221,7 +213,6 @@ class JSFunction : public JSObject JS_ASSERT(cx); if (isInterpretedLazy()) { JS::RootedFunction self(cx, this); - js::MaybeCheckStackRoots(cx); if (!createScriptForLazilyInterpretedFunction(cx, self)) return NULL; JS_ASSERT(self->hasScript()); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index bb92eedcd3df..3b1e1e6e6d08 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -168,7 +168,8 @@ static const AllocKind FinalizePhaseStrings[] = { }; static const AllocKind FinalizePhaseScripts[] = { - FINALIZE_SCRIPT + FINALIZE_SCRIPT, + FINALIZE_LAZY_SCRIPT }; static const AllocKind FinalizePhaseIonCode[] = { @@ -213,7 +214,6 @@ static const AllocKind BackgroundPhaseStrings[] = { }; static const AllocKind BackgroundPhaseShapes[] = { - FINALIZE_LAZY_SCRIPT, FINALIZE_SHAPE, FINALIZE_BASE_SHAPE, FINALIZE_TYPE_OBJECT @@ -1440,7 +1440,7 @@ ArenaLists::queueScriptsForSweep(FreeOp *fop) { gcstats::AutoPhase ap(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_SCRIPT); queueForForegroundSweep(fop, FINALIZE_SCRIPT); - queueForBackgroundSweep(fop, FINALIZE_LAZY_SCRIPT); + queueForForegroundSweep(fop, FINALIZE_LAZY_SCRIPT); } void diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 4eec8386f750..8eb84af8de3f 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -204,7 +204,7 @@ IsBackgroundFinalized(AllocKind kind) false, /* FINALIZE_OBJECT16 */ true, /* FINALIZE_OBJECT16_BACKGROUND */ false, /* FINALIZE_SCRIPT */ - true, /* FINALIZE_LAZY_SCRIPT */ + false, /* FINALIZE_LAZY_SCRIPT */ true, /* FINALIZE_SHAPE */ true, /* FINALIZE_BASE_SHAPE */ true, /* FINALIZE_TYPE_OBJECT */ diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h index 80a74ecd756e..63bcbcd71344 100644 --- a/js/src/jsinferinlines.h +++ b/js/src/jsinferinlines.h @@ -734,28 +734,20 @@ UseNewTypeForClone(JSFunction *fun) * instance a singleton type and clone the underlying script. */ - JSScript *script = fun->nonLazyScript(); - - if (script->length >= 50) - return false; - - if (script->hasConsts() || script->hasObjects() || script->hasRegexps() || fun->isHeavyweight()) - return false; - - bool hasArguments = false; - bool hasApply = false; - - for (jsbytecode *pc = script->code; - pc != script->code + script->length; - pc += GetBytecodeLength(pc)) - { - if (*pc == JSOP_ARGUMENTS) - hasArguments = true; - if (*pc == JSOP_FUNAPPLY) - hasApply = true; + uint32_t begin, end; + if (fun->hasScript()) { + if (!fun->nonLazyScript()->usesArgumentsAndApply) + return false; + begin = fun->nonLazyScript()->sourceStart; + end = fun->nonLazyScript()->sourceEnd; + } else { + if (!fun->lazyScript()->usesArgumentsAndApply()) + return false; + begin = fun->lazyScript()->begin(); + end = fun->lazyScript()->end(); } - return hasArguments && hasApply; + return end - begin <= 100; } ///////////////////////////////////////////////////////////////////// diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index eb777511d0bb..fee7a6a1e76e 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -666,7 +666,10 @@ js::XDRScript(XDRState *xdr, HandleObject enclosingScope, HandleScript enc /* Code the nested function's enclosing scope. */ uint32_t funEnclosingScopeIndex = 0; if (mode == XDR_ENCODE) { - RootedObject staticScope(cx, (*objp)->toFunction()->nonLazyScript()->enclosingStaticScope()); + JSScript *innerScript = (*objp)->toFunction()->getOrCreateScript(cx); + if (!innerScript) + return false; + RootedObject staticScope(cx, innerScript->enclosingStaticScope()); StaticScopeIter ssi(cx, staticScope); if (ssi.done() || ssi.type() == StaticScopeIter::FUNCTION) { JS_ASSERT(ssi.done() == !fun); @@ -1226,16 +1229,13 @@ SourceDataCache::purge() const jschar * ScriptSource::chars(JSContext *cx) { -#ifdef USE_ZLIB - Rooted cached(cx, NULL); -#endif #ifdef JS_THREADSAFE if (!ready()) return cx->runtime()->sourceCompressorThread.currentChars(); #endif #ifdef USE_ZLIB if (compressed()) { - cached = cx->runtime()->sourceDataCache.lookup(this); + JSStableString *cached = cx->runtime()->sourceDataCache.lookup(this); if (!cached) { const size_t nbytes = sizeof(jschar) * (length_ + 1); jschar *decompressed = static_cast(cx->malloc_(nbytes)); @@ -1257,10 +1257,8 @@ ScriptSource::chars(JSContext *cx) } return cached->chars().get(); } - return data.source; -#else - return data.source; #endif + return data.source; } JSStableString * @@ -2324,8 +2322,11 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, assertSameCompartment(cx, innerFun); clone = innerFun; } else { - if (!innerFun->getOrCreateScript(cx)) - return NULL; + if (innerFun->isInterpretedLazy()) { + AutoCompartment ac(cx, innerFun); + if (!innerFun->getOrCreateScript(cx)) + return NULL; + } RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope()); StaticScopeIter ssi(cx, staticScope); RootedObject enclosingScope(cx); @@ -2771,11 +2772,14 @@ JSScript::markChildren(JSTracer *trc) void LazyScript::markChildren(JSTracer *trc) { - if (parent_) - MarkScriptUnbarriered(trc, &parent_, "lazyScriptParent"); + if (sourceObject_) + MarkObject(trc, &sourceObject_, "sourceObject"); + + if (parentFunction_) + MarkObject(trc, &parentFunction_, "parentFunction"); if (script_) - MarkScriptUnbarriered(trc, &script_, "lazyScript"); + MarkScript(trc, &script_, "realScript"); HeapPtrAtom *freeVariables = this->freeVariables(); for (size_t i = 0; i < numFreeVariables(); i++) @@ -2791,6 +2795,9 @@ LazyScript::finalize(FreeOp *fop) { if (table_) fop->free_(table_); + + if (originPrincipals_) + JS_DropPrincipals(fop->runtime(), originPrincipals_); } void @@ -2939,8 +2946,58 @@ JSScript::formalLivesInArgumentsObject(unsigned argSlot) return argsObjAliasesFormals() && !formalIsAliased(argSlot); } +LazyScript::LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions, + JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) + : script_(NULL), + parentFunction_(NULL), + sourceObject_(NULL), + table_(table), + originPrincipals_(NULL), + version_(version), + numFreeVariables_(numFreeVariables), + numInnerFunctions_(numInnerFunctions), + strict_(false), + bindingsAccessedDynamically_(false), + hasDebuggerStatement_(false), + directlyInsideEval_(false), + usesArgumentsAndApply_(false), + hasBeenCloned_(false), + begin_(begin), + end_(end), + lineno_(lineno), + column_(column) +{ + JS_ASSERT(this->version() == version); + JS_ASSERT(begin <= end); +} + +void +LazyScript::initScript(JSScript *script) +{ + JS_ASSERT(script && !script_); + script_ = script; +} + +void +LazyScript::setParent(JSFunction *parentFunction, ScriptSourceObject *sourceObject, + JSPrincipals *originPrincipals) +{ + JS_ASSERT(sourceObject && !sourceObject_ && !parentFunction_ && !originPrincipals_); + parentFunction_ = parentFunction; + sourceObject_ = sourceObject; + originPrincipals_ = originPrincipals; + if (originPrincipals) + JS_HoldPrincipals(originPrincipals); +} + +ScriptSourceObject * +LazyScript::sourceObject() const +{ + return sourceObject_ ? &sourceObject_->asScriptSource() : NULL; +} + /* static */ LazyScript * -LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions, +LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) { JS_ASSERT(begin <= end); @@ -2959,7 +3016,13 @@ LazyScript::Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFu if (!res) return NULL; - return new (res) LazyScript(table, numFreeVariables, numInnerFunctions, begin, end, lineno, column); + return new (res) LazyScript(table, numFreeVariables, numInnerFunctions, version, + begin, end, lineno, column); +} + +uint32_t LazyScript::staticLevel() const +{ + return parentFunction() ? parentFunction()->nonLazyScript()->staticLevel + 1 : 1; } void diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 173ba4c93a93..82b3232fd2e8 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -538,9 +538,12 @@ class JSScript : public js::gc::Cell bool isActiveEval:1; /* script came from eval(), and is still active */ bool isCachedEval:1; /* script came from eval(), and is in eval cache */ - /* Set for functions defined at the top level within an 'eval' script. */ + // Set for functions defined at the top level within an 'eval' script. bool directlyInsideEval:1; + // Both 'arguments' and f.apply() are used. This is likely to be a wrapper. + bool usesArgumentsAndApply:1; + /* script is attempted to be cloned anew at each callsite. This is temporarily needed for ParallelArray selfhosted code until type information can be made context sensitive. See discussion in @@ -1099,19 +1102,20 @@ class AliasedFormalIter struct SourceCompressionToken; - // Information about a script which may be (or has been) lazily compiled to // bytecode from its source. class LazyScript : public js::gc::Cell { - // Immediate parent in which the script is nested, or NULL if the parent - // has not been compiled yet. Lazy scripts are always functions within a - // global or eval script so there will be a parent. - JSScript *parent_; - // If non-NULL, the script has been compiled and this is a forwarding // pointer to the result. - JSScript *script_; + HeapPtrScript script_; + + // Immediate parent in which the script is nested, or NULL. + HeapPtrFunction parentFunction_; + + // Source code object, or NULL if the script in which this is nested has + // not been compiled yet. + HeapPtrObject sourceObject_; // Heap allocated table with any free variables or inner functions. void *table_; @@ -1120,14 +1124,20 @@ class LazyScript : public js::gc::Cell uint32_t padding; #endif - uint32_t numFreeVariables_; + // Assorted bits that should really be in ScriptSourceObject. + JSPrincipals *originPrincipals_; + uint32_t version_ : 8; + + uint32_t numFreeVariables_ : 24; uint32_t numInnerFunctions_ : 26; - bool strict_ : 1; - bool bindingsAccessedDynamically_ : 1; - bool hasDebuggerStatement_ : 1; - bool directlyInsideEval_:1; - bool hasBeenCloned_:1; + // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC. + uint32_t strict_ : 1; + uint32_t bindingsAccessedDynamically_ : 1; + uint32_t hasDebuggerStatement_ : 1; + uint32_t directlyInsideEval_:1; + uint32_t usesArgumentsAndApply_:1; + uint32_t hasBeenCloned_:1; // Source location for the script. uint32_t begin_; @@ -1135,46 +1145,33 @@ class LazyScript : public js::gc::Cell uint32_t lineno_; uint32_t column_; - LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions, - uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) - : parent_(NULL), - script_(NULL), - table_(table), - numFreeVariables_(numFreeVariables), - numInnerFunctions_(numInnerFunctions), - strict_(false), - bindingsAccessedDynamically_(false), - hasDebuggerStatement_(false), - directlyInsideEval_(false), - hasBeenCloned_(false), - begin_(begin), - end_(end), - lineno_(lineno), - column_(column) - { - JS_ASSERT(begin <= end); - } + LazyScript(void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version, + uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); public: static LazyScript *Create(JSContext *cx, uint32_t numFreeVariables, uint32_t numInnerFunctions, - uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); + JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); - void initParent(JSScript *parent) { - JS_ASSERT(parent && !parent_); - parent_ = parent; - } - JSScript *parent() const { - return parent_; - } - - void initScript(JSScript *script) { - JS_ASSERT(script && !script_); - script_ = script; - } + void initScript(JSScript *script); JSScript *maybeScript() { return script_; } + JSFunction *parentFunction() const { + return parentFunction_; + } + ScriptSourceObject *sourceObject() const; + JSPrincipals *originPrincipals() const { + return originPrincipals_; + } + JSVersion version() const { + JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1); + return (version_ == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(version_); + } + + void setParent(JSFunction *parentFunction, ScriptSourceObject *sourceObject, + JSPrincipals *originPrincipals); + uint32_t numFreeVariables() const { return numFreeVariables_; } @@ -1217,6 +1214,13 @@ class LazyScript : public js::gc::Cell directlyInsideEval_ = true; } + bool usesArgumentsAndApply() const { + return usesArgumentsAndApply_; + } + void setUsesArgumentsAndApply() { + usesArgumentsAndApply_ = true; + } + bool hasBeenCloned() const { return hasBeenCloned_; } @@ -1225,7 +1229,7 @@ class LazyScript : public js::gc::Cell } ScriptSource *source() const { - return parent()->scriptSource(); + return sourceObject()->source(); } uint32_t begin() const { return begin_; @@ -1240,6 +1244,8 @@ class LazyScript : public js::gc::Cell return column_; } + uint32_t staticLevel() const; + Zone *zone() const { return Cell::tenuredZone(); } diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index fd14b3bba038..4f239c077a39 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -229,7 +229,6 @@ class Debugger::FrameRange } }; - /*** Breakpoints *********************************************************************************/ BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc) @@ -686,7 +685,6 @@ Debugger::wrapDebuggeeValue(JSContext *cx, MutableHandleValue vp) assertSameCompartment(cx, object.get()); if (vp.isObject()) { - // Do we need this RootedObject? RootedObject obj(cx, &vp.toObject()); ObjectWeakMap::AddPtr p = objects.lookupForAdd(obj); @@ -2887,16 +2885,6 @@ DebuggerScript_getSourceMapUrl(JSContext *cx, unsigned argc, Value *vp) return true; } -static bool -EnsureFunctionHasScript(JSContext *cx, JSFunction *fun) -{ - if (fun->isInterpretedLazy()) { - AutoCompartment ac(cx, fun); - return fun->getOrCreateScript(cx); - } - return true; -} - static JSBool DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp) { @@ -2921,10 +2909,6 @@ DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp) obj = objects->vector[i]; if (obj->isFunction()) { fun = static_cast(obj.get()); - - if (!EnsureFunctionHasScript(cx, fun)) - return false; - funScript = fun->nonLazyScript(); s = dbg->wrapScript(cx, funScript); if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s))) @@ -4473,9 +4457,6 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp) result->ensureDenseInitializedLength(cx, 0, fun->nargs); if (fun->isInterpreted()) { - if (!EnsureFunctionHasScript(cx, fun)) - return false; - JS_ASSERT(fun->nargs == fun->nonLazyScript()->bindings.numArgs()); if (fun->nargs > 0) { @@ -4517,9 +4498,6 @@ DebuggerObject_getScript(JSContext *cx, unsigned argc, Value *vp) return true; } - if (!EnsureFunctionHasScript(cx, fun)) - return false; - RootedScript script(cx, fun->nonLazyScript()); RootedObject scriptObject(cx, dbg->wrapScript(cx, script)); if (!scriptObject) From bdb61b948ee7f58b8afafbc92ea7b613c82a96c4 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Fri, 14 Jun 2013 14:03:25 +0200 Subject: [PATCH 035/615] Bug 882903 - SPS breadkpad unwinder segfaults with on-demand decompression on. r=glandium. --- mozglue/linker/ElfLoader.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp index a9a6c6a125b9..955eacb42dca 100644 --- a/mozglue/linker/ElfLoader.cpp +++ b/mozglue/linker/ElfLoader.cpp @@ -208,7 +208,14 @@ LibHandle::MappableMMap(void *addr, size_t length, off_t offset) const { MOZ_ASSERT(mappable == NULL, "MappableMMap must be called after" " GetMappableLength"); - return mappable->mmap(addr, length, PROT_READ, MAP_PRIVATE, offset); + void* mapped = mappable->mmap(addr, length, PROT_READ, MAP_PRIVATE, offset); + if (mapped != MAP_FAILED) { + /* Ensure the availability of all pages within the mapping */ + for (size_t off = 0; off < length; off += PAGE_SIZE) { + mappable->ensure(reinterpret_cast(mapped) + off); + } + } + return mapped; } void From 561a2574934086d635f0930db56a75c617e48b8d Mon Sep 17 00:00:00 2001 From: Frederik Braun Date: Wed, 15 May 2013 11:30:43 +0200 Subject: [PATCH 036/615] Bug 879316 - Clean up CSP logging code. r=imelven --- ...browser_webconsole_bug_770099_violation.js | 2 +- content/base/src/CSPUtils.jsm | 56 ++++++------------- content/base/src/contentSecurityPolicy.js | 15 +++-- 3 files changed, 28 insertions(+), 45 deletions(-) diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js index 42524a7c1909..893401be63a3 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_770099_violation.js @@ -8,7 +8,7 @@ // Tests that the Web Console CSP messages are displayed const TEST_VIOLATION = "https://example.com/browser/browser/devtools/webconsole/test/test_bug_770099_violation.html"; -const CSP_VIOLATION_MSG = "CSP WARN: Directive default-src https://example.com:443 violated by http://some.example.com/test.png" +const CSP_VIOLATION_MSG = "Content Security Policy: Directive default-src https://example.com:443 violated by http://some.example.com/test.png" let hud = undefined; diff --git a/content/base/src/CSPUtils.jsm b/content/base/src/CSPUtils.jsm index dcc3afb5c112..9d17d5de7bdb 100644 --- a/content/base/src/CSPUtils.jsm +++ b/content/base/src/CSPUtils.jsm @@ -13,6 +13,9 @@ const Cu = Components.utils; const Ci = Components.interfaces; +const WARN_FLAG = Ci.nsIScriptError.warningFlag; +const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG; + Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -842,7 +845,7 @@ CSPRep.prototype = { // However, our original CSP implementation required a default src // or an allow directive. if (!defaultSrcDir && !this._specCompliant) { - this.warn(CSPLocalizer.getStr("allowOrDefaultSrcRequired")); + this.log(WARN_FLAG, CSPLocalizer.getStr("allowOrDefaultSrcRequired")); return false; } @@ -888,7 +891,9 @@ CSPRep.prototype = { }, /** - * Sends a warning message to the error console and web developer console. + * Sends a message to the error console and web developer console. + * @param aFlag + * The nsIScriptError flag constant indicating severity * @param aMsg * The message to send * @param aSource (optional) @@ -898,50 +903,25 @@ CSPRep.prototype = { * @param aLineNum (optional) * The number of the line where the error occurred */ - warn: - function cspd_warn(aMsg, aSource, aScriptLine, aLineNum) { - var textMessage = 'CSP WARN: ' + aMsg + "\n"; - + log: + function cspd_log(aFlag, aMsg, aSource, aScriptLine, aLineNum) { + var textMessage = "Content Security Policy: " + aMsg; var consoleMsg = Components.classes["@mozilla.org/scripterror;1"] .createInstance(Ci.nsIScriptError); if (this._innerWindowID) { consoleMsg.initWithWindowID(textMessage, aSource, aScriptLine, aLineNum, - 0, Ci.nsIScriptError.warningFlag, - "Content Security Policy", + 0, aFlag, + "CSP", this._innerWindowID); } else { consoleMsg.init(textMessage, aSource, aScriptLine, aLineNum, 0, - Ci.nsIScriptError.warningFlag, - "Content Security Policy"); + aFlag, + "CSP"); } Components.classes["@mozilla.org/consoleservice;1"] .getService(Ci.nsIConsoleService).logMessage(consoleMsg); }, - /** - * Sends an error message to the error console and web developer console. - * @param aMsg - * The message to send - */ - error: - function cspsd_error(aMsg) { - var textMessage = 'CSP ERROR: ' + aMsg + "\n"; - - var consoleMsg = Components.classes["@mozilla.org/scripterror;1"] - .createInstance(Ci.nsIScriptError); - if (this._innerWindowID) { - consoleMsg.initWithWindowID(textMessage, null, null, 0, 0, - Ci.nsIScriptError.errorFlag, - "Content Security Policy", - this._innerWindowID); - } - else { - consoleMsg.init(textMessage, null, null, 0, 0, - Ci.nsIScriptError.errorFlag, "Content Security Policy"); - } - Components.classes["@mozilla.org/consoleservice;1"] - .getService(Ci.nsIConsoleService).logMessage(consoleMsg); - }, }; ////////////////////////////////////////////////////////////////////// @@ -1967,17 +1947,17 @@ function innerWindowFromRequest(docRequest) { function cspError(aCSPRep, aMessage) { if (aCSPRep) { - aCSPRep.error(aMessage); + aCSPRep.log(ERROR_FLAG, aMessage); } else { - (new CSPRep()).error(aMessage); + (new CSPRep()).log(ERROR_FLAG, aMessage); } } function cspWarn(aCSPRep, aMessage) { if (aCSPRep) { - aCSPRep.warn(aMessage); + aCSPRep.log(WARN_FLAG, aMessage); } else { - (new CSPRep()).warn(aMessage); + (new CSPRep()).log(WARN_FLAG, aMessage); } } diff --git a/content/base/src/contentSecurityPolicy.js b/content/base/src/contentSecurityPolicy.js index f3054742edc1..400d408aeabc 100644 --- a/content/base/src/contentSecurityPolicy.js +++ b/content/base/src/contentSecurityPolicy.js @@ -25,6 +25,9 @@ const CSP_VIOLATION_TOPIC = "csp-on-violate-policy"; const CSP_TYPE_XMLHTTPREQUEST_SPEC_COMPLIANT = "csp_type_xmlhttprequest_spec_compliant"; const CSP_TYPE_WEBSOCKET_SPEC_COMPLIANT = "csp_type_websocket_spec_compliant"; +const WARN_FLAG = Ci.nsIScriptError.warningFlag; +const ERROR_FLAG = Ci.nsIScriptError.ERROR_FLAG; + Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/CSPUtils.jsm"); @@ -180,13 +183,13 @@ ContentSecurityPolicy.prototype = { break; case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_INLINE_SCRIPT: if (!this._policy.allowsInlineScripts) - this._asyncReportViolation('self',null,'inline script base restriction', + this._asyncReportViolation('self', null, 'inline script base restriction', 'violated base restriction: Inline Scripts will not execute', aSourceFile, aScriptSample, aLineNum); break; case Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL: if (!this._policy.allowsEvalInScripts) - this._asyncReportViolation('self',null,'eval script base restriction', + this._asyncReportViolation('self', null, 'eval script base restriction', 'violated base restriction: Code will not be created from strings', aSourceFile, aScriptSample, aLineNum); break; @@ -360,7 +363,7 @@ ContentSecurityPolicy.prototype = { } else { violationMessage = CSPLocalizer.getFormatStr("directiveViolated", [violatedDirective]); } - this._policy.warn(violationMessage, + this._policy.log(WARN_FLAG, violationMessage, (aSourceFile) ? aSourceFile : null, (aScriptSample) ? decodeURIComponent(aScriptSample) : null, (aLineNum) ? aLineNum : null); @@ -425,8 +428,8 @@ ContentSecurityPolicy.prototype = { } catch(e) { // it's possible that the URI was invalid, just log a // warning and skip over that. - this._policy.warn(CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]])); - this._policy.warn(CSPLocalizer.getFormatStr("errorWas", [e.toString()])); + this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("triedToSendReport", [uris[i]])); + this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("errorWas", [e.toString()])); } } } @@ -663,7 +666,7 @@ CSPReportRedirectSink.prototype = { // nsIChannelEventSink asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel, flags, callback) { - this._policy.warn(CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec])); + this._policy.log(WARN_FLAG, CSPLocalizer.getFormatStr("reportPostRedirect", [oldChannel.URI.asciiSpec])); // cancel the old channel so XHR failure callback happens oldChannel.cancel(Cr.NS_ERROR_ABORT); From fe47fde6abef690738bd42e65e51d8d1e12b9ee7 Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Thu, 13 Jun 2013 17:15:14 -0400 Subject: [PATCH 037/615] Bug 882817 - Fix QI implementation of HTMLTrackElement. r=bz In certain situations we were failing debug builds due to an assertion that HTMLTrackElement was not a nsIDOMNode or nsIDOMWindow when calling NS_CheckContentLoadPolicy in HTMLTrackElement::LoadResource() This patch fixes the QI of the HTMLTrackElement so that it can be queried to an nsIDOMNode correctly. --- content/html/content/src/HTMLTrackElement.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/html/content/src/HTMLTrackElement.cpp b/content/html/content/src/HTMLTrackElement.cpp index f848ae4e75ed..580b36f82ad5 100644 --- a/content/html/content/src/HTMLTrackElement.cpp +++ b/content/html/content/src/HTMLTrackElement.cpp @@ -94,7 +94,8 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED_4(HTMLTrackElement, nsGenericHTMLElement, NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTrackElement) NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement) -NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) + NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement) +NS_ELEMENT_INTERFACE_MAP_END void HTMLTrackElement::OnChannelRedirect(nsIChannel* aChannel, From a6d854705ba39f1a4dc32f28364decbba104ba61 Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Fri, 14 Jun 2013 10:39:10 -0400 Subject: [PATCH 038/615] Bug 882925 - Fix ICUnaryArith_Double stub kind. r=h4writer --- js/src/ion/BaselineIC.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/ion/BaselineIC.h b/js/src/ion/BaselineIC.h index 8f61016075cb..128283c48601 100644 --- a/js/src/ion/BaselineIC.h +++ b/js/src/ion/BaselineIC.h @@ -2717,7 +2717,7 @@ class ICUnaryArith_Double : public ICStub friend class ICStubSpace; ICUnaryArith_Double(IonCode *stubCode) - : ICStub(UnaryArith_Int32, stubCode) + : ICStub(UnaryArith_Double, stubCode) {} public: @@ -2733,7 +2733,7 @@ class ICUnaryArith_Double : public ICStub public: Compiler(JSContext *cx, JSOp op) - : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op) + : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op) {} ICStub *getStub(ICStubSpace *space) { From 42ac4f7eebc3dc020c050c0c84436dc076e6aa8f Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Fri, 14 Jun 2013 10:42:19 -0500 Subject: [PATCH 039/615] Bug 882613 - Remove reference to nsIDocShellHistory in metro front end code bug 882079 missed. r=fyan --- browser/metro/base/content/contenthandlers/Content.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/metro/base/content/contenthandlers/Content.js b/browser/metro/base/content/contenthandlers/Content.js index e7948ba921c2..53c63d184379 100644 --- a/browser/metro/base/content/contenthandlers/Content.js +++ b/browser/metro/base/content/contenthandlers/Content.js @@ -143,7 +143,7 @@ let Content = { // pages have any privilege themselves. addEventListener("click", this, false); - docShell.QueryInterface(Ci.nsIDocShellHistory).useGlobalHistory = true; + docShell.useGlobalHistory = true; }, /******************************************* From d0a02501d701dc62a420e2e08155012f06faf9f8 Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Fri, 14 Jun 2013 10:53:39 -0500 Subject: [PATCH 040/615] Bug 876562. Fix scrollport size calculation that didn't make a lot of sense. r=kats It was taking the min over two values that weren't in the same unit (the first in CSS pixels, the second in dev pixels). --- mobile/android/chrome/content/browser.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index 15b5dc5ebbb3..e93819ad3362 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -2985,8 +2985,8 @@ Tab.prototype = { // the clamping scroll-port size. let factor = Math.min(viewportWidth / screenWidth, pageWidth / screenWidth, viewportHeight / screenHeight, pageHeight / screenHeight); - let scrollPortWidth = Math.min(screenWidth * factor, pageWidth * zoom); - let scrollPortHeight = Math.min(screenHeight * factor, pageHeight * zoom); + let scrollPortWidth = screenWidth * factor; + let scrollPortHeight = screenHeight * factor; let win = this.browser.contentWindow; win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils). From 5e21d995cc9588526b9a97756bdc849eb6612279 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Wed, 5 Jun 2013 22:19:22 +0200 Subject: [PATCH 041/615] Bug 882193 - Remove nsIDocumentRegister. r=mrbkap. --- content/base/src/nsDocument.cpp | 27 --------------------- content/base/src/nsDocument.h | 5 ---- dom/interfaces/core/moz.build | 1 - dom/interfaces/core/nsIDocumentRegister.idl | 16 ------------ 4 files changed, 49 deletions(-) delete mode 100644 dom/interfaces/core/nsIDocumentRegister.idl diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 6014b96e49c6..713bd60cbaa5 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1537,7 +1537,6 @@ NS_INTERFACE_TABLE_HEAD(nsDocument) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers) - NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocumentRegister) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver) NS_INTERFACE_TABLE_END NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument) @@ -5075,32 +5074,6 @@ nsDocument::RegisterEnabled() return sPrefValue; } -NS_IMETHODIMP -nsDocument::Register(const nsAString& aName, const JS::Value& aOptions, - JSContext* aCx, uint8_t aOptionalArgc, - jsval* aConstructor /* out param */) -{ - RootedDictionary options(aCx); - if (aOptionalArgc > 0) { - JSAutoCompartment ac(aCx, GetWrapper()); - JS::Rooted opts(aCx, aOptions); - NS_ENSURE_TRUE(JS_WrapValue(aCx, opts.address()), - NS_ERROR_UNEXPECTED); - NS_ENSURE_TRUE(options.Init(aCx, opts), - NS_ERROR_UNEXPECTED); - } - - ErrorResult rv; - JSObject* object = Register(aCx, aName, options, rv); - if (rv.Failed()) { - return rv.ErrorCode(); - } - NS_ENSURE_TRUE(object, NS_ERROR_UNEXPECTED); - - *aConstructor = OBJECT_TO_JSVAL(object); - return NS_OK; -} - JSObject* nsDocument::Register(JSContext* aCx, const nsAString& aName, const ElementRegistrationOptions& aOptions, diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index fc960561824b..293abb01254a 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -60,7 +60,6 @@ #include "nsIProgressEventSink.h" #include "nsISecurityEventSink.h" #include "nsIChannelEventSink.h" -#include "nsIDocumentRegister.h" #include "imgIRequest.h" #include "mozilla/dom/DOMImplementation.h" #include "nsIDOMTouchEvent.h" @@ -505,7 +504,6 @@ class nsDocument : public nsIDocument, public nsStubMutationObserver, public nsIDOMDocumentTouch, public nsIInlineEventHandlers, - public nsIDocumentRegister, public nsIObserver { public: @@ -796,9 +794,6 @@ public: // nsIInlineEventHandlers NS_DECL_NSIINLINEEVENTHANDLERS - // nsIDocumentRegister - NS_DECL_NSIDOCUMENTREGISTER - // nsIObserver NS_DECL_NSIOBSERVER diff --git a/dom/interfaces/core/moz.build b/dom/interfaces/core/moz.build index 1c185e57de13..10f6ed014322 100644 --- a/dom/interfaces/core/moz.build +++ b/dom/interfaces/core/moz.build @@ -25,7 +25,6 @@ XPIDL_SOURCES += [ 'nsIDOMText.idl', 'nsIDOMUserDataHandler.idl', 'nsIDOMXMLDocument.idl', - 'nsIDocumentRegister.idl', 'nsIInlineEventHandlers.idl', ] diff --git a/dom/interfaces/core/nsIDocumentRegister.idl b/dom/interfaces/core/nsIDocumentRegister.idl deleted file mode 100644 index 701eb9936ba5..000000000000 --- a/dom/interfaces/core/nsIDocumentRegister.idl +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#include "nsISupports.idl" - -[scriptable, uuid(e35935bd-ebae-4e0d-93bf-efa93ab14c05)] -interface nsIDocumentRegister : nsISupports -{ - [optional_argc, - implicit_jscontext] jsval register(in DOMString name, - [optional] in jsval options) - raises(DOMException); -}; - From 583f9d98a8963825de1650f40ac60c27c1e72bc8 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Mon, 25 Mar 2013 11:36:24 +0100 Subject: [PATCH 042/615] Bug 851465 - Remove slim wrappers - stop constructing slim wrappers. r=bholley. --- dom/base/nsDOMClassInfo.cpp | 8 +- js/xpconnect/src/XPCConvert.cpp | 31 +------- js/xpconnect/src/XPCWrappedNative.cpp | 102 -------------------------- js/xpconnect/src/xpcprivate.h | 4 - xpcom/base/ErrorList.h | 7 -- 5 files changed, 4 insertions(+), 148 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index dca001c3c7f3..045612ec173c 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -5099,8 +5099,7 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *aGlobalObj, nsresult rv = WrapNativeParent(cx, globalObj, native_parent, parentObj); NS_ENSURE_SUCCESS(rv, rv); - return node->ChromeOnlyAccess() ? - NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS; + return node->ChromeOnlyAccess() ? NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK; } NS_IMETHODIMP @@ -5261,8 +5260,7 @@ nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx, if (element->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && doc->BindingManager()->GetBinding(element)) { - // Don't allow slim wrappers. - return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv; + return rv; } mozilla::css::URLValue *bindingURL; @@ -5276,7 +5274,7 @@ nsElementSH::PreCreate(nsISupports *nativeObj, JSContext *cx, element->SetFlags(NODE_ATTACH_BINDING_ON_POSTCREATE); - return rv == NS_SUCCESS_ALLOW_SLIM_WRAPPERS ? NS_OK : rv; + return rv; } NS_IMETHODIMP diff --git a/js/xpconnect/src/XPCConvert.cpp b/js/xpconnect/src/XPCConvert.cpp index 4e90d835dd5c..3ed83b60deea 100644 --- a/js/xpconnect/src/XPCConvert.cpp +++ b/js/xpconnect/src/XPCConvert.cpp @@ -819,7 +819,6 @@ XPCConvert::NativeInterface2JSObject(jsval* d, // object will create (and fill the cache) from its WrapObject call. nsWrapperCache *cache = aHelper.GetWrapperCache(); - bool tryConstructSlimWrapper = false; RootedObject flat(cx); if (cache) { flat = cache->GetWrapper(); @@ -840,39 +839,11 @@ XPCConvert::NativeInterface2JSObject(jsval* d, } } - if (!dest) { - if (!flat) { - tryConstructSlimWrapper = true; - } else if (IS_SLIM_WRAPPER_OBJECT(flat)) { - if (js::IsObjectInContextCompartment(flat, cx)) { - *d = OBJECT_TO_JSVAL(flat); - return true; - } - } - } + MOZ_ASSERT_IF(flat, !IS_SLIM_WRAPPER_OBJECT(flat)); } else { flat = nullptr; } - // If we're not handing this wrapper to an nsIXPConnectJSObjectHolder, and - // the object supports slim wrappers, try to create one here. - if (tryConstructSlimWrapper) { - RootedValue slim(cx); - if (ConstructSlimWrapper(aHelper, xpcscope, &slim)) { - *d = slim; - return true; - } - - if (JS_IsExceptionPending(cx)) - return false; - - // Even if ConstructSlimWrapper returns false it might have created a - // wrapper (while calling the PreCreate hook). In that case we need to - // fall through because we either have a slim wrapper that needs to be - // morphed or an XPCWrappedNative. - flat = cache->GetWrapper(); - } - // We can't simply construct a slim wrapper. Go ahead and create an // XPCWrappedNative for this object. At this point, |flat| could be // non-null, meaning that either we already have a wrapped native from diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index cf62f09bec81..a9a39499c50d 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -3568,105 +3568,3 @@ MorphSlimWrapper(JSContext *cx, HandleObject obj) getter_AddRefs(wn)); return NS_SUCCEEDED(rv); } - -#ifdef DEBUG_slimwrappers -static uint32_t sSlimWrappers; -#endif - -JSBool -ConstructSlimWrapper(xpcObjectHelper &aHelper, - XPCWrappedNativeScope* xpcScope, MutableHandleValue rval) -{ - AutoJSContext cx; - nsISupports *identityObj = aHelper.GetCanonical(); - nsXPCClassInfo *classInfoHelper = aHelper.GetXPCClassInfo(); - - if (!classInfoHelper) { - SLIM_LOG_NOT_CREATED(cx, identityObj, "No classinfo helper"); - return false; - } - - XPCNativeScriptableFlags flags(classInfoHelper->GetScriptableFlags()); - - NS_ASSERTION(flags.DontAskInstanceForScriptable(), - "Not supported for cached wrappers!"); - - RootedObject parent(cx, xpcScope->GetGlobalJSObject()); - if (!flags.WantPreCreate()) { - SLIM_LOG_NOT_CREATED(cx, identityObj, - "scriptable helper has no PreCreate hook"); - - return false; - } - - // PreCreate may touch dead compartments. - js::AutoMaybeTouchDeadZones agc(parent); - - RootedObject plannedParent(cx, parent); - nsresult rv = classInfoHelper->PreCreate(identityObj, cx, parent, parent.address()); - if (rv != NS_SUCCESS_ALLOW_SLIM_WRAPPERS) { - SLIM_LOG_NOT_CREATED(cx, identityObj, "PreCreate hook refused"); - - return false; - } - - if (!js::IsObjectInContextCompartment(parent, cx)) { - SLIM_LOG_NOT_CREATED(cx, identityObj, "wrong compartment"); - - return false; - } - - JSAutoCompartment ac(cx, parent); - - if (parent != plannedParent) { - XPCWrappedNativeScope *newXpcScope = GetObjectScope(parent); - if (newXpcScope != xpcScope) { - SLIM_LOG_NOT_CREATED(cx, identityObj, "crossing origins"); - - return false; - } - } - - // The PreCreate hook could have forced the creation of a wrapper, need - // to check for that here and return early. - nsWrapperCache *cache = aHelper.GetWrapperCache(); - JSObject* wrapper = cache->GetWrapper(); - if (wrapper) { - rval.setObject(*wrapper); - - return true; - } - - uint32_t interfacesBitmap = classInfoHelper->GetInterfacesBitmap(); - XPCNativeScriptableCreateInfo - sciProto(aHelper.forgetXPCClassInfo(), flags, interfacesBitmap); - - AutoMarkingWrappedNativeProtoPtr xpcproto(cx); - xpcproto = XPCWrappedNativeProto::GetNewOrUsed(xpcScope, classInfoHelper, &sciProto); - if (!xpcproto) - return false; - - XPCNativeScriptableInfo* si = xpcproto->GetScriptableInfo(); - JSClass* jsclazz = si->GetSlimJSClass(); - if (!jsclazz) - return false; - - wrapper = JS_NewObject(cx, jsclazz, xpcproto->GetJSProtoObject(), parent); - if (!wrapper) - return false; - - JS_SetPrivate(wrapper, identityObj); - SetSlimWrapperProto(wrapper, xpcproto.get()); - - // Transfer ownership to the wrapper's private. - aHelper.forgetCanonical(); - - cache->SetWrapper(wrapper); - - SLIM_LOG(("+++++ %i created slim wrapper (%p, %p, %p)\n", ++sSlimWrappers, - wrapper, p, xpcScope)); - - rval.setObject(*wrapper); - - return true; -} diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0354be0b7840..525e60e83e93 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2241,10 +2241,6 @@ private: XPCNativeScriptableInfo* mScriptableInfo; }; -class xpcObjectHelper; -extern JSBool ConstructSlimWrapper(xpcObjectHelper &aHelper, - XPCWrappedNativeScope* xpcScope, - JS::MutableHandleValue rval); extern JSBool MorphSlimWrapper(JSContext *cx, JS::HandleObject obj); /***********************************************/ diff --git a/xpcom/base/ErrorList.h b/xpcom/base/ErrorList.h index 12e02ea419d2..7ed73da0612e 100644 --- a/xpcom/base/ErrorList.h +++ b/xpcom/base/ErrorList.h @@ -599,13 +599,6 @@ * filename begins with chrome://global/) shoudl return this from their * scriptable helper's PreCreate hook. */ ERROR(NS_SUCCESS_CHROME_ACCESS_ONLY, SUCCESS(2)), - /* Classes that want slim wrappers should return - * NS_SUCCESS_ALLOW_SLIM_WRAPPERS from their scriptable helper's PreCreate - * hook. They must also force a parent for their wrapper (from the PreCreate - * hook), they must implement nsWrapperCache and their scriptable helper must - * implement nsXPCClassInfo and must return DONT_ASK_INSTANCE_FOR_SCRIPTABLE - * in the flags. */ - ERROR(NS_SUCCESS_ALLOW_SLIM_WRAPPERS, SUCCESS(3)), #undef MODULE From 6869dbc9e2f8cd7be13ab537bb9880267213025f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:24 -0700 Subject: [PATCH 043/615] Bug 880917 - Remove support for munging JS versions from JSD. r=luke A quick grep of Firebug indicates that it doesn't use this. And even if I missed it, doing so from a debugger with the current semantics is a feature we can't support going forward. --- js/jsd/idl/jsdIDebuggerService.idl | 32 +----------------------------- js/jsd/jsd_xpc.cpp | 17 ---------------- 2 files changed, 1 insertion(+), 48 deletions(-) diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index 6e47c1e42c96..618f342cae8e 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -45,7 +45,7 @@ interface jsdIActivationCallback; * Debugger service. It is not a good idea to have more than one active client * of the debugger service. */ -[scriptable, uuid(9be5b327-6818-464d-9695-f33885fd8377)] +[scriptable, uuid(029b8f0a-aa84-47eb-a60f-1a4752b7ad06)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -88,29 +88,6 @@ interface jsdIDebuggerService : nsISupports */ attribute jsdICallHook functionHook; - - /** - * VERSION_* values must be kept in sync with the JSVersion enumeration in - * jspubtd.h. - */ - - /** - * Possible values for jsdIScript::version and jsdIContext::version. - */ - const long VERSION_1_0 = 100; - const long VERSION_1_1 = 110; - const long VERSION_1_2 = 120; - const long VERSION_1_3 = 130; - const long VERSION_1_4 = 140; - const long VERSION_1_5 = 150; - const long VERSION_DEFAULT = 0; - const long VERSION_UNKNOWN = -1; - - /** - * These flags need to be kept in sync with the context flags defined in - * jsdebug.h - */ - /** * Link native frames in call stacks. */ @@ -722,13 +699,6 @@ interface jsdIContext : jsdIEphemeral */ attribute unsigned long options; - /** - * Last version set on this context. - * Scripts typically select this with the "language" attribute. - * See the VERSION_* consts on jsdIDebuggerService. - */ - attribute long version; - /** * Unique tag among all valid jsdIContext objects, useful as a hash key. */ diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 189f00ddd8c9..9e32581c8f3d 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -1693,23 +1693,6 @@ jsdContext::GetTag(uint32_t *_rval) return NS_OK; } -NS_IMETHODIMP -jsdContext::GetVersion (int32_t *_rval) -{ - ASSERT_VALID_EPHEMERAL; - *_rval = static_cast(JS_GetVersion(mJSCx)); - return NS_OK; -} - -NS_IMETHODIMP -jsdContext::SetVersion (int32_t id) -{ - ASSERT_VALID_EPHEMERAL; - JSVersion ver = static_cast(id); - JS_SetVersion(mJSCx, ver); - return NS_OK; -} - NS_IMETHODIMP jsdContext::GetGlobalObject (jsdIValue **_rval) { From c9c12ae8baf750921abe85c0f34e3a5f1a099ec6 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:25 -0700 Subject: [PATCH 044/615] Bug 880917 - Generalize JS_NewGlobalObject API to take CompartmentOptions. r=luke This will be useful for versioning, as well as JIT options and all the other stuff that eventually needs to move out of the JSContext. --- content/base/src/nsFrameMessageManager.cpp | 4 +++- content/xbl/src/nsXBLDocumentInfo.cpp | 4 +++- .../xul/document/src/nsXULPrototypeDocument.cpp | 4 +++- dom/base/nsGlobalWindow.cpp | 6 +++--- ipc/testshell/XPCShellEnvironment.cpp | 4 +++- js/src/jsapi.cpp | 16 +++++++++------- js/src/jsapi.h | 11 ++++++++++- js/src/jscompartment.cpp | 3 ++- js/src/jscompartment.h | 5 ++++- js/src/jsgc.cpp | 5 +++-- js/src/jsgc.h | 3 ++- js/src/shell/js.cpp | 5 +++-- js/xpconnect/idl/nsIXPConnect.idl | 15 ++++++++------- js/xpconnect/loader/mozJSComponentLoader.cpp | 4 +++- js/xpconnect/shell/xpcshell.cpp | 4 +++- js/xpconnect/src/XPCComponents.cpp | 8 +++++--- js/xpconnect/src/XPCJSContextStack.cpp | 4 +++- js/xpconnect/src/XPCWrappedNative.cpp | 4 ++-- js/xpconnect/src/nsXPConnect.cpp | 9 ++++----- js/xpconnect/src/xpcprivate.h | 4 ++-- netwerk/base/src/ProxyAutoConfig.cpp | 4 +++- 21 files changed, 81 insertions(+), 45 deletions(-) diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 2dadfdb345e6..9209b5ba8c3b 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1117,9 +1117,11 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope, JS_SetContextPrivate(cx, aScope); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal, - flags, JS::SystemZone, getter_AddRefs(mGlobal)); + flags, options, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index c74df251619b..96f2ac162dc9 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -284,9 +284,11 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment() // why - see bug 339647) JS_SetErrorReporter(cx, XBL_ProtoErrorReporter); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass, nsJSPrincipals::get(GetPrincipal()), - JS::SystemZone); + options); if (!mJSObject) return NS_OK; diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 2a086cff7399..ed2220b98bce 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -762,9 +762,11 @@ nsXULPDGlobalObject::EnsureScriptEnvironment() // will re-fetch the global and set it up in our language globals array. { AutoPushJSContext cx(ctxNew->GetNativeContext()); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); JS::Rooted newGlob(cx, JS_NewGlobalObject(cx, &gSharedGlobalClass, - nsJSPrincipals::get(GetPrincipal()), JS::SystemZone)); + nsJSPrincipals::get(GetPrincipal()), options)); if (!newGlob) return NS_OK; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8b43d032ad0a..72a2e7bc91a9 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2120,10 +2120,10 @@ CreateNativeGlobalForInner(JSContext* aCx, if (aNewInner->GetOuterWindow()) { top = aNewInner->GetTop(); } - JS::ZoneSpecifier zoneSpec = JS::FreshZone; + JS::CompartmentOptions options; if (top) { if (top->GetGlobalJSObject()) { - zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject()); + options.zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject()); } } @@ -2139,7 +2139,7 @@ CreateNativeGlobalForInner(JSContext* aCx, nsRefPtr jsholder; nsresult rv = xpc->InitClassesWithNewWrappedGlobal( aCx, ToSupports(aNewInner), - aPrincipal, flags, zoneSpec, getter_AddRefs(jsholder)); + aPrincipal, flags, options, getter_AddRefs(jsholder)); NS_ENSURE_SUCCESS(rv, rv); MOZ_ASSERT(jsholder); diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index e8000d8bdbb6..fc746b7140aa 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -783,11 +783,13 @@ XPCShellEnvironment::Init() return false; } + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), principal, 0, - JS::SystemZone, + options, getter_AddRefs(holder)); if (NS_FAILED(rv)) { NS_ERROR("InitClassesWithNewWrappedGlobal failed!"); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 36a7a07423b3..cd144c62aebf 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -941,7 +941,8 @@ JSRuntime::init(uint32_t maxbytes) if (!atomsZone) return false; - ScopedJSDeletePtr atomsCompartment(new_(atomsZone.get())); + JS::CompartmentOptions options; + ScopedJSDeletePtr atomsCompartment(new_(atomsZone.get(), options)); if (!atomsCompartment || !atomsCompartment->init(NULL)) return false; @@ -3427,7 +3428,8 @@ class AutoHoldZone }; JS_PUBLIC_API(JSObject *) -JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS::ZoneSpecifier zoneSpec) +JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, + const JS::CompartmentOptions &options) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -3436,18 +3438,18 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS:: JSRuntime *rt = cx->runtime(); Zone *zone; - if (zoneSpec == JS::SystemZone) + if (options.zoneSpec == JS::SystemZone) zone = rt->systemZone; - else if (zoneSpec == JS::FreshZone) + else if (options.zoneSpec == JS::FreshZone) zone = NULL; else - zone = ((JSObject *)zoneSpec)->zone(); + zone = ((JSObject *)options.zoneSpec)->zone(); - JSCompartment *compartment = NewCompartment(cx, zone, principals); + JSCompartment *compartment = NewCompartment(cx, zone, principals, options); if (!compartment) return NULL; - if (zoneSpec == JS::SystemZone) { + if (options.zoneSpec == JS::SystemZone) { rt->systemZone = compartment->zone(); rt->systemZone->isSystem = true; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index fb8790bdef0f..9328a8d5e287 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3144,11 +3144,20 @@ SameZoneAs(JSObject *obj) return ZoneSpecifier(obj); } +struct JS_PUBLIC_API(CompartmentOptions) { + ZoneSpecifier zoneSpec; + + explicit CompartmentOptions() : zoneSpec(JS::FreshZone) + {} + + CompartmentOptions &setZone(ZoneSpecifier spec) { zoneSpec = spec; return *this; } +}; + } /* namespace JS */ extern JS_PUBLIC_API(JSObject *) JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, - JS::ZoneSpecifier zoneSpec = JS::FreshZone); + const JS::CompartmentOptions &options = JS::CompartmentOptions()); extern JS_PUBLIC_API(JSObject *) JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 48b8459d7890..6192f8ba4c9f 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -30,8 +30,9 @@ using namespace js::gc; using mozilla::DebugOnly; -JSCompartment::JSCompartment(Zone *zone) +JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions()) : zone_(zone), + options_(options), rt(zone->rt), principals(NULL), isSystem(false), diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index b103b313b101..7283f07a5176 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -123,6 +123,7 @@ class DebugScopes; struct JSCompartment { JS::Zone *zone_; + JS::CompartmentOptions options_; JSRuntime *rt; JSPrincipals *principals; @@ -144,6 +145,8 @@ struct JSCompartment JS::Zone *zone() { return zone_; } const JS::Zone *zone() const { return zone_; } + JS::CompartmentOptions &options() { return options_; } + const JS::CompartmentOptions &options() const { return options_; } /* * Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the @@ -259,7 +262,7 @@ struct JSCompartment unsigned debugModeBits; // see debugMode() below public: - JSCompartment(JS::Zone *zone); + JSCompartment(JS::Zone *zone, const JS::CompartmentOptions &options); ~JSCompartment(); bool init(JSContext *cx); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index bb92eedcd3df..d978a77fb3ee 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4699,7 +4699,8 @@ AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt) } JSCompartment * -js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals) +js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals, + const JS::CompartmentOptions &options) { JSRuntime *rt = cx->runtime(); JS_AbortIfWrongThread(rt); @@ -4721,7 +4722,7 @@ js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals) zone->isSystem = principals && principals == trusted; } - ScopedJSDeletePtr compartment(cx->new_(zone)); + ScopedJSDeletePtr compartment(cx->new_(zone, options)); if (!compartment || !compartment->init(cx)) return NULL; diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 4eec8386f750..64fe87ce1cf3 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1201,7 +1201,8 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str); namespace js { JSCompartment * -NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals); +NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals, + const JS::CompartmentOptions &options); namespace gc { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 55a0a1b3c89c..823137fdacd2 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4799,8 +4799,9 @@ DestroyContext(JSContext *cx, bool withGC) static JSObject * NewGlobalObject(JSContext *cx, JSObject *sameZoneAs) { - JS::ZoneSpecifier spec = sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone; - RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, spec)); + JS::CompartmentOptions options; + options.setZone(sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone); + RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, options)); if (!glob) return NULL; diff --git a/js/xpconnect/idl/nsIXPConnect.idl b/js/xpconnect/idl/nsIXPConnect.idl index d805109cdcc1..c6c73bb73361 100644 --- a/js/xpconnect/idl/nsIXPConnect.idl +++ b/js/xpconnect/idl/nsIXPConnect.idl @@ -44,7 +44,7 @@ class nsWrapperCache; [ref] native nsCCTraversalCallbackRef(nsCycleCollectionTraversalCallback); [ptr] native nsAXPCNativeCallContextPtr(nsAXPCNativeCallContext); [ptr] native nsWrapperCachePtr(nsWrapperCache); - native ZoneSpecifier(uintptr_t); +[ref] native JSCompartmentOptions(JS::CompartmentOptions); [ref] native JSCallArgsRef(const JS::CallArgs); native JSHandleId(JS::HandleId); @@ -291,7 +291,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(2950bc62-ba03-4465-9685-a0eec9e188c2)] +[uuid(bd61342d-8a88-4f23-8d2d-1782fff02d26)] interface nsIXPConnect : nsISupports { %{ C++ @@ -318,14 +318,15 @@ interface nsIXPConnect : nsISupports * compartment. Can be null if not on the main thread. * @param aFlags one of the flags below specifying what options this * global object wants. + * @param aOptions JSAPI-specific options for the new compartment. */ nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal( - in JSContextPtr aJSContext, - in nsISupports aCOMObj, - in nsIPrincipal aPrincipal, - in uint32_t aFlags, - in ZoneSpecifier aZoneSpec); + in JSContextPtr aJSContext, + in nsISupports aCOMObj, + in nsIPrincipal aPrincipal, + in uint32_t aFlags, + in JSCompartmentOptions aOptions); const uint32_t INIT_JS_STANDARD_CLASSES = 1 << 0; // Free bit here! diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 9f84e278bf27..a3340ccc2b00 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -726,11 +726,13 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx, rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); NS_ENSURE_SUCCESS(rv, nullptr); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); rv = xpc->InitClassesWithNewWrappedGlobal(aCx, static_cast(backstagePass), mSystemPrincipal, 0, - JS::SystemZone, + options, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, nullptr); diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 3986b49b0a93..b8ffc10d9f4c 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -1634,12 +1634,14 @@ main(int argc, char **argv, char **envp) return 1; } + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), systemprincipal, 0, - JS::SystemZone, + options, getter_AddRefs(holder)); if (NS_FAILED(rv)) return 1; diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index c9c4b2b7525b..598064847c9d 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3279,10 +3279,12 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo MOZ_ASSERT(principal); } - JS::ZoneSpecifier zoneSpec = options.sameZoneAs + JS::CompartmentOptions compartmentOptions; + compartmentOptions.setZone(options.sameZoneAs ? JS::SameZoneAs(js::UncheckedUnwrap(options.sameZoneAs)) - : JS::SystemZone; - RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass, principal, zoneSpec)); + : JS::SystemZone); + RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass, + principal, compartmentOptions)); if (!sandbox) return NS_ERROR_FAILURE; diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index 142cf4ff539f..7547cb6c7961 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -167,7 +167,9 @@ XPCJSContextStack::GetSafeJSContext() JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter); - glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, JS::SystemZone); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); + glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options); if (glob) { // Make sure the context is associated with a proper compartment diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index cf62f09bec81..0152cc465761 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -285,7 +285,7 @@ FinishCreate(XPCWrappedNativeScope* Scope, nsresult XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper, nsIPrincipal *principal, bool initStandardClasses, - ZoneSpecifier zoneSpec, + JS::CompartmentOptions& aOptions, XPCWrappedNative **wrappedGlobal) { AutoJSContext cx; @@ -315,7 +315,7 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper, MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL); // Create the global. - RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, zoneSpec)); + RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, aOptions)); if (!global) return NS_ERROR_FAILURE; XPCWrappedNativeScope *scope = GetCompartmentPrivate(global)->scope; diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index ecbf68b9185c..51675194b0a3 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -981,7 +981,7 @@ namespace xpc { JSObject* CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, - JS::ZoneSpecifier zoneSpec) + JS::CompartmentOptions& aOptions) { // Make sure that Type Inference is enabled for everything non-chrome. // Sandboxes and compilation scopes are exceptions. See bug 744034. @@ -991,7 +991,7 @@ CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, MOZ_ASSERT(principal); RootedObject global(cx, - JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), zoneSpec)); + JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), aOptions)); if (!global) return nullptr; JSAutoCompartment ac(cx, global); @@ -1027,7 +1027,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsISupports *aCOMObj, nsIPrincipal * aPrincipal, uint32_t aFlags, - JS::ZoneSpecifier zoneSpec, + JS::CompartmentOptions& aOptions, nsIXPConnectJSObjectHolder **_retval) { NS_ASSERTION(aJSContext, "bad param"); @@ -1046,8 +1046,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsresult rv = XPCWrappedNative::WrapNewGlobal(helper, aPrincipal, aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES, - zoneSpec, - getter_AddRefs(wrappedGlobal)); + aOptions, getter_AddRefs(wrappedGlobal)); NS_ENSURE_SUCCESS(rv, rv); // Grab a copy of the global and enter its compartment. diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 0354be0b7840..c742c029c2cc 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2471,7 +2471,7 @@ public: static nsresult WrapNewGlobal(xpcObjectHelper &nativeHelper, nsIPrincipal *principal, bool initStandardClasses, - JS::ZoneSpecifier zoneSpec, + JS::CompartmentOptions& aOptions, XPCWrappedNative **wrappedGlobal); static nsresult @@ -3796,7 +3796,7 @@ struct SandboxOptions { JSObject * CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, - JS::ZoneSpecifier zoneSpec); + JS::CompartmentOptions& aOptions); } // Helper for creating a sandbox object to use for evaluating diff --git a/netwerk/base/src/ProxyAutoConfig.cpp b/netwerk/base/src/ProxyAutoConfig.cpp index e88e9c3e9701..26ed6fbd19b0 100644 --- a/netwerk/base/src/ProxyAutoConfig.cpp +++ b/netwerk/base/src/ProxyAutoConfig.cpp @@ -536,7 +536,9 @@ private: JSAutoRequest ar(mContext); - mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, JS::SystemZone); + JS::CompartmentOptions options; + options.setZone(JS::SystemZone); + mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options); NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY); JS_SetGlobalObject(mContext, mGlobal); From 2685398e0e805ec03cf67c38f7f02b43a76be7ba Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:25 -0700 Subject: [PATCH 045/615] Bug 880917 - Introduce an API for callers to set the version for a compartment. r=luke This has lower precedence than 'overrides' and running script, and higher precedence than the cx's version. We can migrate the API consumers who clearly want something like this, which will eventually let us remove the override mechanism. --- js/src/jsapi.h | 5 +++++ js/src/jscntxt.h | 1 + js/src/jscntxtinlines.h | 3 +++ 3 files changed, 9 insertions(+) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9328a8d5e287..9e8a748d27a7 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3146,11 +3146,16 @@ SameZoneAs(JSObject *obj) struct JS_PUBLIC_API(CompartmentOptions) { ZoneSpecifier zoneSpec; + bool hasVersion; + JSVersion version; explicit CompartmentOptions() : zoneSpec(JS::FreshZone) + , hasVersion(false) + , version(JSVERSION_UNKNOWN) {} CompartmentOptions &setZone(ZoneSpecifier spec) { zoneSpec = spec; return *this; } + CompartmentOptions &setVersion(JSVersion version_) { hasVersion = true; version = version_; return *this; } }; } /* namespace JS */ diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 1a01b6cda11d..d31ef81b1989 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1691,6 +1691,7 @@ struct JSContext : js::ContextFriendFields, * Return: * - The override version, if there is an override version. * - The newest scripted frame's version, if there is such a frame. + * - The version from the compartment. * - The default version. * * Note: if this ever shows up in a profile, just add caching! diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 103de78ad18a..d335b27a38dc 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -474,6 +474,9 @@ JSContext::findVersion() const if (JSScript *script = stack.currentScript(NULL, js::ContextStack::ALLOW_CROSS_COMPARTMENT)) return script->getVersion(); + if (compartment() && compartment()->options().hasVersion) + return compartment()->options().version; + return defaultVersion; } From ad313903289b63dccdc9f6b5c92c4ad59772dd01 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:25 -0700 Subject: [PATCH 046/615] Bug 880917 - Remove testVersion.cpp. r=luke This test coverages seems to be mostly testing functionality we're removing like overrides and version introspection. Let's just kill it. --- js/src/jsapi-tests/moz.build | 1 - js/src/jsapi-tests/testVersion.cpp | 171 ----------------------------- 2 files changed, 172 deletions(-) delete mode 100644 js/src/jsapi-tests/testVersion.cpp diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index e2aa2ccf710c..56f2681e207f 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -64,7 +64,6 @@ CPP_SOURCES += [ 'testTrap.cpp', 'testTypedArrays.cpp', 'testUTF8.cpp', - 'testVersion.cpp', 'testXDR.cpp', 'tests.cpp', ] diff --git a/js/src/jsapi-tests/testVersion.cpp b/js/src/jsapi-tests/testVersion.cpp deleted file mode 100644 index ccbb7497321d..000000000000 --- a/js/src/jsapi-tests/testVersion.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* 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/. */ - -#include "tests.h" -#include "jsscript.h" -#include "jscntxt.h" - -#include "jscntxtinlines.h" -#include "jsobjinlines.h" - -using namespace js; - -struct VersionFixture; - -/* - * Fast-native callbacks for use from JS. - * They set their results on the current fixture instance. - */ - -static VersionFixture *callbackData = NULL; - -JSBool CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp); -JSBool OverrideVersion18(JSContext *cx, unsigned argc, jsval *vp); -JSBool CaptureVersion(JSContext *cx, unsigned argc, jsval *vp); -JSBool CheckOverride(JSContext *cx, unsigned argc, jsval *vp); -JSBool EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp); - -struct VersionFixture : public JSAPITest -{ - JSVersion captured; - - virtual bool init() { - if (!JSAPITest::init()) - return false; - JS_SetOptions(cx, JS_GetOptions(cx)); - callbackData = this; - captured = JSVERSION_UNKNOWN; - JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); - return JS_DefineFunction(cx, global, "callSetVersion17", CallSetVersion17, 0, 0) && - JS_DefineFunction(cx, global, "overrideVersion18", OverrideVersion18, 0, 0) && - JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) && - JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) && - JS_DefineFunction(cx, global, "evalScriptVersion16", - EvalScriptVersion16, 0, 0); - } - - JSScript *fakeScript(const char *contents, size_t length) { - JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); - return JS_CompileScript(cx, global, contents, length, "", 1); - } - - bool checkVersionIsOverridden() { - CHECK(cx->isVersionOverridden()); - return true; - } - - bool setVersion(JSVersion version) { - CHECK(JS_GetVersion(cx) != version); - JS_SetVersion(cx, version); - return true; - } - - bool evalVersion(const jschar *chars, size_t len, JSVersion version) { - CHECK(JS_GetVersion(cx) != version); - jsval rval; - JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); - CHECK(JS_EvaluateUCScriptForPrincipalsVersion( - cx, global, NULL, chars, len, "", 0, &rval, version)); - return true; - } -}; - -/* Callbacks to throw into JS-land. */ - -JSBool -CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp) -{ - return callbackData->setVersion(JSVERSION_1_7); -} - -JSBool -OverrideVersion18(JSContext *cx, unsigned argc, jsval *vp) -{ - if (!callbackData->setVersion(JSVERSION_1_8)) - return false; - return callbackData->checkVersionIsOverridden(); -} - -JSBool -EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp) -{ - JS_ASSERT(argc == 1); - jsval *argv = JS_ARGV(cx, vp); - JS_ASSERT(JSVAL_IS_STRING(argv[0])); - JSStableString *str = JSVAL_TO_STRING(argv[0])->ensureStable(cx); - JS_ASSERT(str); - return callbackData->evalVersion(str->chars().get(), str->length(), JSVERSION_1_6); -} - -JSBool -CaptureVersion(JSContext *cx, unsigned argc, jsval *vp) -{ - callbackData->captured = JS_GetVersion(cx); - return true; -} - -JSBool -CheckOverride(JSContext *cx, unsigned argc, jsval *vp) -{ - JS_ASSERT(argc == 1); - jsval *argv = JS_ARGV(cx, vp); - JS_ASSERT(JSVAL_IS_BOOLEAN(argv[0])); - bool shouldHaveOverride = !!JSVAL_TO_BOOLEAN(argv[0]); - return shouldHaveOverride == cx->isVersionOverridden(); -} - -/* - * When re-entering the virtual machine through a *Version API the version - * is no longer forced -- it continues with its natural push/pop oriented - * version progression. This is maintained by the |AutoVersionAPI| class in - * jsapi.cpp. - */ -BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride) -{ - EXEC("overrideVersion18(); evalScriptVersion16('checkOverride(false); captureVersion()');"); - CHECK_EQUAL(captured, JSVERSION_1_6); - - /* - * Override gets propagated to default version as non-override when you leave the VM's execute - * call. - */ - CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_1_8); - CHECK(!cx->isVersionOverridden()); - return true; -} -END_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride) - -/* - * EvalScriptVersion does not propagate overrides to its caller, it - * restores things exactly as they were before the call. This is as opposed to - * the normal (no Version suffix) API which propagates overrides - * to the caller. - */ -BEGIN_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride) -{ - CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5); - EXEC( - "checkOverride(false);" - "evalScriptVersion16('overrideVersion18();');" - "checkOverride(false);" - "captureVersion();" - ); - CHECK_EQUAL(captured, JSVERSION_ECMA_5); - return true; -} -END_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride) - -BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride) -{ - CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5); - EXEC( - "checkOverride(false);" - "eval('overrideVersion18();');" - "checkOverride(true);" - "captureVersion();" - ); - CHECK_EQUAL(captured, JSVERSION_1_8); - return true; -} -END_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride) From d78fcf8d612017310b8bc4f63eaac219018ce7ec Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:25 -0700 Subject: [PATCH 047/615] Bug 880917 - Remove AutoVersionChecker. r=luke Looks like cdleary added this back in bug 595691, as an equivalence to some even-older-and-more-overly-cautious XBL code that was saving and restoring the version across XBL calls. It doesn't seem like this should be an issue anymore, and it's just a debugging aid to boot. Let's kill it. --- content/xbl/src/nsXBLProtoImpl.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/content/xbl/src/nsXBLProtoImpl.cpp b/content/xbl/src/nsXBLProtoImpl.cpp index 9d97766c2f38..db6eefebcc9f 100644 --- a/content/xbl/src/nsXBLProtoImpl.cpp +++ b/content/xbl/src/nsXBLProtoImpl.cpp @@ -21,27 +21,6 @@ using namespace mozilla; -// Checks that the version is not modified in a given scope. -class AutoVersionChecker -{ - DebugOnly const cx; - DebugOnly versionBefore; - -public: - explicit AutoVersionChecker(JSContext *aCx) : cx(aCx) { -#ifdef DEBUG - versionBefore = JS_GetVersion(cx); -#endif - } - - ~AutoVersionChecker() { -#ifdef DEBUG - JSVersion versionAfter = JS_GetVersion(cx); - NS_ABORT_IF_FALSE(versionAfter == versionBefore, "version must not change"); -#endif - } -}; - nsresult nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, nsXBLBinding* aBinding) @@ -89,7 +68,6 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, AutoPushJSContext cx(context->GetNativeContext()); JSAutoCompartment ac(cx, targetClassObject); - AutoVersionChecker avc(cx); // Walk our member list and install each one in turn. for (nsXBLProtoImplMember* curr = mMembers; @@ -229,8 +207,6 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding) MOZ_ASSERT(classObject); mClassObject = classObject; - AutoVersionChecker avc(cx); - // Now that we have a class object installed, we walk our member list and compile each of our // properties and methods in turn. for (nsXBLProtoImplMember* curr = mMembers; @@ -299,7 +275,6 @@ nsXBLProtoImpl::FindField(const nsString& aFieldName) const bool nsXBLProtoImpl::ResolveAllFields(JSContext *cx, JS::Handle obj) const { - AutoVersionChecker avc(cx); for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) { // Using OBJ_LOOKUP_PROPERTY is a pain, since what we have is a // PRUnichar* for the property name. Let's just use the public API and From dbe3fa03a5f400d4539738cf04dbef9e5ee032ee Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:26 -0700 Subject: [PATCH 048/615] Bug 880917 - Add support for "latest" as a version to evalInSandbox, and use it for sjs files. r=luke Sandboxes always default to JSVERSION_DEFAULT in the browser. But XPCShell sets up a ContextCallback that does JS_SetVersion(cx, JSVERSION_LATEST) on every context that gets created, including the ephemerial Sandbox JSContexts. Since httpd.js runs in xpcshell and evaluates SJS in a sandbox, we've (somewhat accidentally) supported JSVERSION_LATEST in SJS, which certain SJS files have taken advantage of. Let's continue to support it explicitly. --- js/xpconnect/src/XPCComponents.cpp | 7 +++++++ netwerk/test/httpserver/httpd.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 598064847c9d..32da95bfd9fd 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3822,6 +3822,13 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString& source, return NS_ERROR_INVALID_ARG; jsVersion = JS_StringToVersion(bytes.ptr()); + // Explicitly check for "latest", which we support for sandboxes but + // isn't in the set of web-exposed version strings. + if (jsVersion == JSVERSION_UNKNOWN && + !strcmp(bytes.ptr(), "latest")) + { + jsVersion = JSVERSION_LATEST; + } if (jsVersion == JSVERSION_UNKNOWN) return NS_ERROR_INVALID_ARG; } diff --git a/netwerk/test/httpserver/httpd.js b/netwerk/test/httpserver/httpd.js index 5a40cc4fa584..d16a65f8921a 100644 --- a/netwerk/test/httpserver/httpd.js +++ b/netwerk/test/httpserver/httpd.js @@ -2727,7 +2727,7 @@ ServerHandler.prototype = // getting the line number where we evaluate the SJS file. Don't // separate these two lines! var line = new Error().lineNumber; - Cu.evalInSandbox(sis.read(file.fileSize), s); + Cu.evalInSandbox(sis.read(file.fileSize), s, "latest"); } catch (e) { From 8a63d768844b1d3869b8561e9ccfbb6f6ca99867 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:26 -0700 Subject: [PATCH 049/615] Bug 880917 - Convert JS_SetVersion API consumers to per-compartment versions. r=luke --- content/base/src/nsFrameMessageManager.cpp | 4 ++-- dom/workers/RuntimeService.cpp | 4 ---- dom/workers/WorkerScope.cpp | 5 ++++- ipc/testshell/XPCShellEnvironment.cpp | 4 ++-- js/src/gdb/gdb-tests.cpp | 5 +++-- js/src/jsapi-tests/tests.cpp | 4 +++- js/src/jsapi-tests/tests.h | 1 - js/src/shell/js.cpp | 4 ++-- js/xpconnect/loader/mozJSComponentLoader.cpp | 6 ++---- js/xpconnect/shell/xpcshell.cpp | 4 ++-- js/xpconnect/src/XPCComponents.cpp | 5 ++--- netwerk/base/src/ProxyAutoConfig.cpp | 4 ++-- 12 files changed, 24 insertions(+), 26 deletions(-) diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 9209b5ba8c3b..b89240d60399 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1108,7 +1108,6 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope, nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal)); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS); - JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, ContentScriptErrorReporter); nsIXPConnect* xpc = nsContentUtils::XPConnect(); @@ -1118,7 +1117,8 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope, JS_SetContextPrivate(cx, aScope); JS::CompartmentOptions options; - options.setZone(JS::SystemZone); + options.setZone(JS::SystemZone) + .setVersion(JSVERSION_LATEST); nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal, flags, options, getter_AddRefs(mGlobal)); diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 89d0f72a1afd..fb5ad18a7bde 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -829,10 +829,6 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate) JS_SetGCZeal(workerCx, settings.gcZeal, settings.gcZealFrequency); #endif - if (aWorkerPrivate->IsChromeWorker()) { - JS_SetVersion(workerCx, JSVERSION_LATEST); - } - return workerCx; } diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 6a9bd62e26f3..00dc3d6b7a71 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -967,9 +967,12 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx) WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx); JS_ASSERT(worker); + JS::CompartmentOptions options; + if (worker->IsChromeWorker()) + options.setVersion(JSVERSION_LATEST); JS::Rooted global(aCx, JS_NewGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(), - GetWorkerPrincipal())); + GetWorkerPrincipal(), options)); if (!global) { return NULL; } diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index fc746b7140aa..8e247a29c919 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -188,7 +188,6 @@ ContextCallback(JSContext *cx, if (contextOp == JSCONTEXT_NEW) { JS_SetErrorReporter(cx, ScriptErrorReporter); - JS_SetVersion(cx, JSVERSION_LATEST); } return JS_TRUE; } @@ -784,7 +783,8 @@ XPCShellEnvironment::Init() } JS::CompartmentOptions options; - options.setZone(JS::SystemZone); + options.setZone(JS::SystemZone) + .setVersion(JSVERSION_LATEST); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), diff --git a/js/src/gdb/gdb-tests.cpp b/js/src/gdb/gdb-tests.cpp index a5ce25cf364d..8398859818c1 100644 --- a/js/src/gdb/gdb-tests.cpp +++ b/js/src/gdb/gdb-tests.cpp @@ -62,13 +62,14 @@ main (int argc, const char **argv) JS_SetNativeStackQuota(runtime, 5000000); JSContext *cx = checkPtr(JS_NewContext(runtime, 8192)); - JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); JSAutoRequest ar(cx); /* Create the global object. */ - RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL))); + JS::CompartmentOptions options; + options.setVersion(JSVERSION_LATEST); + RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL, options))); JS_SetGlobalObject(cx, global); JSAutoCompartment ac(cx, global); diff --git a/js/src/jsapi-tests/tests.cpp b/js/src/jsapi-tests/tests.cpp index 30b89be2d3b8..9267eb6b2cbc 100644 --- a/js/src/jsapi-tests/tests.cpp +++ b/js/src/jsapi-tests/tests.cpp @@ -51,7 +51,9 @@ bool JSAPITest::definePrint() JSObject * JSAPITest::createGlobal(JSPrincipals *principals) { /* Create the global object. */ - global = JS_NewGlobalObject(cx, getGlobalClass(), principals); + JS::CompartmentOptions options; + options.setVersion(JSVERSION_LATEST); + global = JS_NewGlobalObject(cx, getGlobalClass(), principals, options); if (!global) return NULL; JS_AddNamedObjectRoot(cx, &global, "test-global"); diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index c3c7e4cb8265..b2e3ed50b839 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -299,7 +299,6 @@ class JSAPITest if (!cx) return NULL; JS_SetOptions(cx, JSOPTION_VAROBJFIX); - JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, &reportError); return cx; } diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 823137fdacd2..224df8601801 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4774,7 +4774,6 @@ NewContext(JSRuntime *rt) JS_SetContextPrivate(cx, data); JS_SetErrorReporter(cx, my_ErrorReporter); - JS_SetVersion(cx, JSVERSION_LATEST); SetContextOptions(cx); if (enableTypeInference) JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE); @@ -4800,7 +4799,8 @@ static JSObject * NewGlobalObject(JSContext *cx, JSObject *sameZoneAs) { JS::CompartmentOptions options; - options.setZone(sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone); + options.setZone(sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone) + .setVersion(JSVERSION_LATEST); RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, options)); if (!glob) return NULL; diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index a3340ccc2b00..36040843005e 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -460,9 +460,6 @@ mozJSComponentLoader::ReallyInit() if (!mContext) return NS_ERROR_OUT_OF_MEMORY; - // Always use the latest js version - JS_SetVersion(mContext, JSVERSION_LATEST); - nsCOMPtr secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); if (!secman) @@ -727,7 +724,8 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx, NS_ENSURE_SUCCESS(rv, nullptr); JS::CompartmentOptions options; - options.setZone(JS::SystemZone); + options.setZone(JS::SystemZone) + .setVersion(JSVERSION_LATEST); rv = xpc->InitClassesWithNewWrappedGlobal(aCx, static_cast(backstagePass), mSystemPrincipal, diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index b8ffc10d9f4c..6be520e96d1c 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -1400,7 +1400,6 @@ ContextCallback(JSContext *cx, unsigned contextOp) if (contextOp == JSCONTEXT_NEW) { JS_SetErrorReporter(cx, my_ErrorReporter); - JS_SetVersion(cx, JSVERSION_LATEST); } return true; } @@ -1635,7 +1634,8 @@ main(int argc, char **argv, char **envp) } JS::CompartmentOptions options; - options.setZone(JS::SystemZone); + options.setZone(JS::SystemZone) + .setVersion(JSVERSION_LATEST); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 32da95bfd9fd..fe6c6d7295c0 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3913,12 +3913,11 @@ xpc_EvalInSandbox(JSContext *cx, HandleObject sandboxArg, const nsAString& sourc pusher.Push(sandcx); JSAutoCompartment ac(sandcx, sandbox); - if (jsVersion != JSVERSION_DEFAULT) - JS_SetVersion(sandcx, jsVersion); - JS::CompileOptions options(sandcx); options.setPrincipals(nsJSPrincipals::get(prin)) .setFileAndLine(filename, lineNo); + if (jsVersion != JSVERSION_DEFAULT) + options.setVersion(jsVersion); JS::RootedObject rootedSandbox(sandcx, sandbox); ok = JS::Evaluate(sandcx, rootedSandbox, options, PromiseFlatString(source).get(), source.Length(), diff --git a/netwerk/base/src/ProxyAutoConfig.cpp b/netwerk/base/src/ProxyAutoConfig.cpp index 26ed6fbd19b0..a70754d98bea 100644 --- a/netwerk/base/src/ProxyAutoConfig.cpp +++ b/netwerk/base/src/ProxyAutoConfig.cpp @@ -537,14 +537,14 @@ private: JSAutoRequest ar(mContext); JS::CompartmentOptions options; - options.setZone(JS::SystemZone); + options.setZone(JS::SystemZone) + .setVersion(JSVERSION_LATEST); mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options); NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY); JS_SetGlobalObject(mContext, mGlobal); JS_InitStandardClasses(mContext, mGlobal); - JS_SetVersion(mContext, JSVERSION_LATEST); JS_SetErrorReporter(mContext, PACErrorReporter); if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions)) From 87a3080914e4e6c52d7a8027508926550f0701c6 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:26 -0700 Subject: [PATCH 050/615] Bug 880917 - Remove XPConnect version munging test. r=luke This test calls the version() shell command, and expects it to work like an override, rather than the dumb compartment-mutator that I'm turning it into. Let's just kill the test. --- .../tests/unit/bug596580_versioned.js | 3 --- js/xpconnect/tests/unit/test_bug596580.js | 19 ------------------- js/xpconnect/tests/unit/xpcshell.ini | 1 - 3 files changed, 23 deletions(-) delete mode 100644 js/xpconnect/tests/unit/bug596580_versioned.js delete mode 100644 js/xpconnect/tests/unit/test_bug596580.js diff --git a/js/xpconnect/tests/unit/bug596580_versioned.js b/js/xpconnect/tests/unit/bug596580_versioned.js deleted file mode 100644 index cb44db7ce030..000000000000 --- a/js/xpconnect/tests/unit/bug596580_versioned.js +++ /dev/null @@ -1,3 +0,0 @@ -/* Some constructs that require a high default version number. */ -let x = 12; -function simpleGen() { yield 12; } diff --git a/js/xpconnect/tests/unit/test_bug596580.js b/js/xpconnect/tests/unit/test_bug596580.js deleted file mode 100644 index 706f0b838835..000000000000 --- a/js/xpconnect/tests/unit/test_bug596580.js +++ /dev/null @@ -1,19 +0,0 @@ -const Cc = Components.classes; -const Ci = Components.interfaces; - -function run_test() { - var file = do_get_file("bug596580_versioned.js"); - var ios = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService); - var uri = ios.newFileURI(file); - var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"] - .getService(Ci.mozIJSSubScriptLoader); - scriptLoader.loadSubScript(uri.spec); - version(150) - try { - scriptLoader.loadSubScript(uri.spec); - throw new Error("Subscript should fail to load."); - } catch (e if e instanceof SyntaxError) { - // Okay. - } -} diff --git a/js/xpconnect/tests/unit/xpcshell.ini b/js/xpconnect/tests/unit/xpcshell.ini index da728b10a280..852a08d29a35 100644 --- a/js/xpconnect/tests/unit/xpcshell.ini +++ b/js/xpconnect/tests/unit/xpcshell.ini @@ -5,7 +5,6 @@ tail = [test_bogus_files.js] [test_bug408412.js] [test_bug451678.js] -[test_bug596580.js] [test_bug604362.js] [test_bug641378.js] [test_bug677864.js] From f2b1f988a5f97f111660205a26b307c71c8f2fd4 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:26 -0700 Subject: [PATCH 051/615] Bug 880917 - Add an API to mutate the version on the compartment and use it from the shells. r=luke --- ipc/testshell/XPCShellEnvironment.cpp | 6 +++--- js/src/jsapi.cpp | 6 ++++++ js/src/jsapi.h | 9 +++++++++ js/src/shell/js.cpp | 6 ++++-- js/xpconnect/shell/xpcshell.cpp | 10 ++++++---- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 8e247a29c919..40980f5010f6 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -305,10 +305,10 @@ Version(JSContext *cx, JS::Value *vp) { JS::Value *argv = JS_ARGV(cx, vp); + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); if (argc > 0 && JSVAL_IS_INT(argv[0])) - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(argv[0]))))); - else - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); + JS_SetVersionForCompartment(js::GetContextCompartment(cx), + JSVersion(JSVAL_TO_INT(argv[0]))); return JS_TRUE; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index cd144c62aebf..6959e3284e1f 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1357,6 +1357,12 @@ JS_SetVersion(JSContext *cx, JSVersion newVersion) return oldVersionNumber; } +JS_PUBLIC_API(void) +JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version) +{ + compartment->options().setVersion(version); +} + static struct v2smap { JSVersion version; const char *string; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9e8a748d27a7..1d61f09538be 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1893,6 +1893,15 @@ JS_GetVersion(JSContext *cx); extern JS_PUBLIC_API(JSVersion) JS_SetVersion(JSContext *cx, JSVersion version); +// Mutate the version on the compartment. This is generally discouraged, but +// necessary to support the version mutation in the js and xpc shell command +// set. +// +// It would be nice to put this in jsfriendapi, but the linkage requirements +// of the shells make that impossible. +JS_PUBLIC_API(void) +JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version); + extern JS_PUBLIC_API(const char *) JS_VersionToString(JSVersion version); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 224df8601801..4fc4f0b3f53c 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -625,9 +625,10 @@ static JSBool Version(JSContext *cx, unsigned argc, jsval *vp) { CallArgs args = CallArgsFromVp(argc, vp); + JSVersion origVersion = JS_GetVersion(cx); if (args.length() == 0 || JSVAL_IS_VOID(args[0])) { /* Get version. */ - args.rval().setInt32(JS_GetVersion(cx)); + args.rval().setInt32(origVersion); } else { /* Set version. */ int32_t v = -1; @@ -642,7 +643,8 @@ Version(JSContext *cx, unsigned argc, jsval *vp) JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "version"); return false; } - args.rval().setInt32(JS_SetVersion(cx, JSVersion(v))); + JS_SetVersionForCompartment(js::GetContextCompartment(cx), JSVersion(v)); + args.rval().setInt32(origVersion); } return true; } diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 6be520e96d1c..1d4832b57557 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -489,10 +489,11 @@ Load(JSContext *cx, unsigned argc, jsval *vp) static JSBool Version(JSContext *cx, unsigned argc, jsval *vp) { + JSVersion origVersion = JS_GetVersion(cx); + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(origVersion)); if (argc > 0 && JSVAL_IS_INT(JS_ARGV(cx, vp)[0])) - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(JS_ARGV(cx, vp)[0]))))); - else - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); + JS_SetVersionForCompartment(js::GetContextCompartment(cx), + JSVersion(JSVAL_TO_INT(JS_ARGV(cx, vp)[0]))); return true; } @@ -1236,7 +1237,8 @@ ProcessArgs(JSContext *cx, JS::Handle obj, char **argv, int argc, XPC if (++i == argc) { return usage(); } - JS_SetVersion(cx, JSVersion(atoi(argv[i]))); + JS_SetVersionForCompartment(js::GetContextCompartment(cx), + JSVersion(atoi(argv[i]))); break; case 'W': reportWarnings = false; From 660f4ca00637d951db75b79d53ddd98af3ad3858 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:27 -0700 Subject: [PATCH 052/615] Bug 880917 - Remove js_RevertVersion and associated shell functionality. r=luke --- js/src/jsdbgapi.cpp | 6 ------ js/src/jsdbgapi.h | 3 --- js/src/shell/js.cpp | 13 ------------- js/src/tests/js1_8/regress/regress-384412.js | 13 ------------- 4 files changed, 35 deletions(-) diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 1132434c829b..1b5880aeeed8 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -827,12 +827,6 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure) /************************************************************************/ -JS_FRIEND_API(void) -js_RevertVersion(JSContext *cx) -{ - cx->clearVersionOverride(); -} - JS_PUBLIC_API(const JSDebugHooks *) JS_GetGlobalDebugHooks(JSRuntime *rt) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index a9db47d1cd06..f5f0245a2d72 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -427,9 +427,6 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure); /************************************************************************/ -extern JS_FRIEND_API(void) -js_RevertVersion(JSContext *cx); - extern JS_PUBLIC_API(const JSDebugHooks *) JS_GetGlobalDebugHooks(JSRuntime *rt); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 4fc4f0b3f53c..a67a6281b7ee 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -649,15 +649,6 @@ Version(JSContext *cx, unsigned argc, jsval *vp) return true; } -static JSBool -RevertVersion(JSContext *cx, unsigned argc, jsval *vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - js_RevertVersion(cx); - args.rval().setUndefined(); - return true; -} - static JSScript * GetTopScript(JSContext *cx) { @@ -3567,10 +3558,6 @@ static JSFunctionSpecWithHelp shell_functions[] = { "version([number])", " Get or force a script compilation version number."), - JS_FN_HELP("revertVersion", RevertVersion, 0, 0, -"revertVersion()", -" Revert previously set version number."), - JS_FN_HELP("options", Options, 0, 0, "options([option ...])", " Get or toggle JavaScript options."), diff --git a/js/src/tests/js1_8/regress/regress-384412.js b/js/src/tests/js1_8/regress/regress-384412.js index fa9bed6da397..92dd9bc59ab5 100644 --- a/js/src/tests/js1_8/regress/regress-384412.js +++ b/js/src/tests/js1_8/regress/regress-384412.js @@ -137,19 +137,6 @@ function test() expect(["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"] + "", ([a + b for (a in 'abc') for (b in '123')]) + ""); -/* - * Version switching - */ - if (typeof version == 'function') - { - var v = version(150); - f = new Function("return version(arguments[0])"); - revertVersion(); - expect(150, f()); - expect(150, eval("f()")); - expect(0, eval("f(0); f()")); - revertVersion(); - } print("End of Tests"); /* From fa60cdc4b6e77fa3cf4bb55213dc3b9957d4a57f Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:27 -0700 Subject: [PATCH 053/615] Bug 880917 - Remove JS_SetVersion and version override machinery. r=luke \o/ --- js/src/jsapi.cpp | 35 +++-------------------------------- js/src/jsapi.h | 3 --- js/src/jscntxt.cpp | 1 - js/src/jscntxt.h | 37 ------------------------------------- js/src/jscntxtinlines.h | 28 ---------------------------- js/src/vm/Stack.cpp | 3 --- 6 files changed, 3 insertions(+), 104 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6959e3284e1f..c96414587fbd 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -125,38 +125,26 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl /* * This class is a version-establishing barrier at the head of a VM entry or - * re-entry. It ensures that: - * - * - |newVersion| is the starting (default) version used for the context. - * - The starting version state is not an override. - * - Overrides in the VM session are not propagated to the caller. + * re-entry. It ensures that |newVersion| is the starting (default) version + * used for the context. */ class AutoVersionAPI { JSContext * const cx; JSVersion oldDefaultVersion; - bool oldHasVersionOverride; - JSVersion oldVersionOverride; JSVersion newVersion; public: AutoVersionAPI(JSContext *cx, JSVersion newVersion) : cx(cx), - oldDefaultVersion(cx->getDefaultVersion()), - oldHasVersionOverride(cx->isVersionOverridden()), - oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN) + oldDefaultVersion(cx->getDefaultVersion()) { this->newVersion = newVersion; - cx->clearVersionOverride(); cx->setDefaultVersion(newVersion); } ~AutoVersionAPI() { cx->setDefaultVersion(oldDefaultVersion); - if (oldHasVersionOverride) - cx->overrideVersion(oldVersionOverride); - else - cx->clearVersionOverride(); } /* The version that this scoped-entity establishes. */ @@ -1340,23 +1328,6 @@ JS_GetVersion(JSContext *cx) return VersionNumber(cx->findVersion()); } -JS_PUBLIC_API(JSVersion) -JS_SetVersion(JSContext *cx, JSVersion newVersion) -{ - JS_ASSERT(VersionIsKnown(newVersion)); - JS_ASSERT(!VersionHasFlags(newVersion)); - JSVersion newVersionNumber = newVersion; - - JSVersion oldVersion = cx->findVersion(); - JSVersion oldVersionNumber = VersionNumber(oldVersion); - if (oldVersionNumber == newVersionNumber) - return oldVersionNumber; /* No override actually occurs! */ - - VersionCopyFlags(&newVersion, oldVersion); - cx->maybeOverrideVersion(newVersion); - return oldVersionNumber; -} - JS_PUBLIC_API(void) JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 1d61f09538be..835d6e590985 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1890,9 +1890,6 @@ JS_ContextIterator(JSRuntime *rt, JSContext **iterp); extern JS_PUBLIC_API(JSVersion) JS_GetVersion(JSContext *cx); -extern JS_PUBLIC_API(JSVersion) -JS_SetVersion(JSContext *cx, JSVersion version); - // Mutate the version on the compartment. This is generally discouraged, but // necessary to support the version mutation in the js and xpc shell command // set. diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 982f0222ca4a..f38f1c0c2de2 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1121,7 +1121,6 @@ js_HandleExecutionInterrupt(JSContext *cx) JSContext::JSContext(JSRuntime *rt) : ContextFriendFields(rt), defaultVersion(JSVERSION_DEFAULT), - hasVersionOverride(false), throwing(false), exception(UndefinedValue()), options_(0), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index d31ef81b1989..dac82b2099e7 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1535,8 +1535,6 @@ struct JSContext : js::ContextFriendFields, private: /* See JSContext::findVersion. */ JSVersion defaultVersion; /* script compilation version */ - JSVersion versionOverride; /* supercedes defaultVersion when valid */ - bool hasVersionOverride; /* Exception state -- the exception member is a GC root by definition. */ bool throwing; /* is there a pending exception? */ @@ -1646,50 +1644,15 @@ struct JSContext : js::ContextFriendFields, inline js::RegExpStatics *regExpStatics(); public: - /* - * The default script compilation version can be set iff there is no code running. - * This typically occurs via the JSAPI right after a context is constructed. - */ - inline bool canSetDefaultVersion() const; - - /* Force a version for future script compilation. */ - inline void overrideVersion(JSVersion newVersion); - /* Set the default script compilation version. */ void setDefaultVersion(JSVersion version) { defaultVersion = version; } - void clearVersionOverride() { hasVersionOverride = false; } JSVersion getDefaultVersion() const { return defaultVersion; } - bool isVersionOverridden() const { return hasVersionOverride; } - - JSVersion getVersionOverride() const { - JS_ASSERT(isVersionOverridden()); - return versionOverride; - } - - /* - * Set the default version if possible; otherwise, force the version. - * Return whether an override occurred. - */ - inline bool maybeOverrideVersion(JSVersion newVersion); - - /* - * If there is no code on the stack, turn the override version into the - * default version. - */ - void maybeMigrateVersionOverride() { - JS_ASSERT(stack.empty()); - if (JS_UNLIKELY(isVersionOverridden())) { - defaultVersion = versionOverride; - clearVersionOverride(); - } - } /* * Return: - * - The override version, if there is an override version. * - The newest scripted frame's version, if there is such a frame. * - The version from the compartment. * - The default version. diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index d335b27a38dc..b3ad936ec3ef 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -468,9 +468,6 @@ CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, un inline JSVersion JSContext::findVersion() const { - if (hasVersionOverride) - return versionOverride; - if (JSScript *script = stack.currentScript(NULL, js::ContextStack::ALLOW_CROSS_COMPARTMENT)) return script->getVersion(); @@ -480,31 +477,6 @@ JSContext::findVersion() const return defaultVersion; } -inline bool -JSContext::canSetDefaultVersion() const -{ - return !stack.hasfp() && !hasVersionOverride; -} - -inline void -JSContext::overrideVersion(JSVersion newVersion) -{ - JS_ASSERT(!canSetDefaultVersion()); - versionOverride = newVersion; - hasVersionOverride = true; -} - -inline bool -JSContext::maybeOverrideVersion(JSVersion newVersion) -{ - if (canSetDefaultVersion()) { - setDefaultVersion(newVersion); - return false; - } - overrideVersion(newVersion); - return true; -} - inline js::LifoAlloc & JSContext::analysisLifoAlloc() { diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index fc5c77484ee2..12ee830d83b5 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -833,9 +833,6 @@ ContextStack::popSegment() { space().seg_ = seg_->prevInMemory(); seg_ = seg_->prevInContext(); - - if (!seg_) - cx_->maybeMigrateVersionOverride(); } bool From 0d5781f0c936d6eba9bc8ac9dedca6ff7e5645ac Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:27 -0700 Subject: [PATCH 054/615] Bug 880917 - Hoist defaultVersion into the runtime and remove it from the JSContext. r=luke --- js/src/jsapi.cpp | 23 ++++++++++++----------- js/src/jscntxt.cpp | 3 --- js/src/jscntxt.h | 15 ++++++--------- js/src/jscntxtinlines.h | 2 +- 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c96414587fbd..68cc99e78043 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -126,25 +126,25 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl /* * This class is a version-establishing barrier at the head of a VM entry or * re-entry. It ensures that |newVersion| is the starting (default) version - * used for the context. + * used for the runtime. */ class AutoVersionAPI { - JSContext * const cx; + JSRuntime * const rt; JSVersion oldDefaultVersion; JSVersion newVersion; public: - AutoVersionAPI(JSContext *cx, JSVersion newVersion) - : cx(cx), - oldDefaultVersion(cx->getDefaultVersion()) + AutoVersionAPI(JSRuntime *rt, JSVersion newVersion) + : rt(rt), + oldDefaultVersion(rt->defaultVersion()) { this->newVersion = newVersion; - cx->setDefaultVersion(newVersion); + rt->setDefaultVersion(newVersion); } ~AutoVersionAPI() { - cx->setDefaultVersion(oldDefaultVersion); + rt->setDefaultVersion(oldDefaultVersion); } /* The version that this scoped-entity establishes. */ @@ -723,6 +723,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) numCompartments(0), localeCallbacks(NULL), defaultLocale(NULL), + defaultVersion_(JSVERSION_DEFAULT), #ifdef JS_THREADSAFE ownerThread_(NULL), #endif @@ -5293,7 +5294,7 @@ JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, { Maybe mava; if (options.versionSet) { - mava.construct(cx, options.version); + mava.construct(cx->runtime(), options.version); // AutoVersionAPI propagates some compilation flags through. options.version = mava.ref().version(); } @@ -5452,7 +5453,7 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options, { Maybe mava; if (options.versionSet) { - mava.construct(cx, options.version); + mava.construct(cx->runtime(), options.version); // AutoVersionAPI propagates some compilation flags through. options.version = mava.ref().version(); } @@ -5631,7 +5632,7 @@ JS_ExecuteScriptVersion(JSContext *cx, JSObject *objArg, JSScript *script, jsval JSVersion version) { RootedObject obj(cx, objArg); - AutoVersionAPI ava(cx, version); + AutoVersionAPI ava(cx->runtime(), version); return JS_ExecuteScript(cx, obj, script, rval); } @@ -5643,7 +5644,7 @@ JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options, { Maybe mava; if (options.versionSet) { - mava.construct(cx, options.version); + mava.construct(cx->runtime(), options.version); // AutoVersionAPI propagates some compilation flags through. options.version = mava.ref().version(); } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index f38f1c0c2de2..0eb73c280cbe 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -280,8 +280,6 @@ js::NewContext(JSRuntime *rt, size_t stackChunkSize) if (!cx) return NULL; - JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); - if (!cx->cycleDetectorSet.init()) { js_delete(cx); return NULL; @@ -1120,7 +1118,6 @@ js_HandleExecutionInterrupt(JSContext *cx) JSContext::JSContext(JSRuntime *rt) : ContextFriendFields(rt), - defaultVersion(JSVERSION_DEFAULT), throwing(false), exception(UndefinedValue()), options_(0), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index dac82b2099e7..5b129c902a95 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -719,6 +719,9 @@ struct JSRuntime : public JS::shadow::Runtime, /* Default locale for Internationalization API */ char *defaultLocale; + /* Default JSVersion. */ + JSVersion defaultVersion_; + /* See comment for JS_AbortIfWrongThread in jsapi.h. */ #ifdef JS_THREADSAFE public: @@ -828,6 +831,9 @@ struct JSRuntime : public JS::shadow::Runtime, /* Gets current default locale. String remains owned by context. */ const char *getDefaultLocale(); + JSVersion defaultVersion() { return defaultVersion_; } + void setDefaultVersion(JSVersion v) { defaultVersion_ = v; } + /* Base address of the native stack for the current thread. */ uintptr_t nativeStackBase; @@ -1533,9 +1539,6 @@ struct JSContext : js::ContextFriendFields, js::PerThreadData &mainThread() { return runtime()->mainThread; } private: - /* See JSContext::findVersion. */ - JSVersion defaultVersion; /* script compilation version */ - /* Exception state -- the exception member is a GC root by definition. */ bool throwing; /* is there a pending exception? */ js::Value exception; /* most-recently-thrown exception */ @@ -1644,12 +1647,6 @@ struct JSContext : js::ContextFriendFields, inline js::RegExpStatics *regExpStatics(); public: - /* Set the default script compilation version. */ - void setDefaultVersion(JSVersion version) { - defaultVersion = version; - } - - JSVersion getDefaultVersion() const { return defaultVersion; } /* * Return: diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index b3ad936ec3ef..84d83bf0b09a 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -474,7 +474,7 @@ JSContext::findVersion() const if (compartment() && compartment()->options().hasVersion) return compartment()->options().version; - return defaultVersion; + return runtime()->defaultVersion(); } inline js::LifoAlloc & From a9dcb76cf3e46d3f58f3e48b4e4d3e3571324165 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 13 Jun 2013 10:09:28 -0700 Subject: [PATCH 055/615] Bug 880917 - Remove AutoVersionAPI. r=luke This doesn't do anything anymore. The compile options should generally carry the right version through, with the exception of eval, which will end up using the version of the running script anyway. --- js/src/jsapi.cpp | 51 ------------------------------------------------ 1 file changed, 51 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 68cc99e78043..7ae077659c4f 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -122,35 +122,6 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl return false; } - -/* - * This class is a version-establishing barrier at the head of a VM entry or - * re-entry. It ensures that |newVersion| is the starting (default) version - * used for the runtime. - */ -class AutoVersionAPI -{ - JSRuntime * const rt; - JSVersion oldDefaultVersion; - JSVersion newVersion; - - public: - AutoVersionAPI(JSRuntime *rt, JSVersion newVersion) - : rt(rt), - oldDefaultVersion(rt->defaultVersion()) - { - this->newVersion = newVersion; - rt->setDefaultVersion(newVersion); - } - - ~AutoVersionAPI() { - rt->setDefaultVersion(oldDefaultVersion); - } - - /* The version that this scoped-entity establishes. */ - JSVersion version() const { return newVersion; } -}; - #ifdef HAVE_VA_LIST_AS_ARRAY #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap)) #else @@ -5292,13 +5263,6 @@ JSScript * JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, const jschar *chars, size_t length) { - Maybe mava; - if (options.versionSet) { - mava.construct(cx->runtime(), options.version); - // AutoVersionAPI propagates some compilation flags through. - options.version = mava.ref().version(); - } - JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -5451,13 +5415,6 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options, const char *name, unsigned nargs, const char **argnames, const jschar *chars, size_t length) { - Maybe mava; - if (options.versionSet) { - mava.construct(cx->runtime(), options.version); - // AutoVersionAPI propagates some compilation flags through. - options.version = mava.ref().version(); - } - JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -5632,7 +5589,6 @@ JS_ExecuteScriptVersion(JSContext *cx, JSObject *objArg, JSScript *script, jsval JSVersion version) { RootedObject obj(cx, objArg); - AutoVersionAPI ava(cx->runtime(), version); return JS_ExecuteScript(cx, obj, script, rval); } @@ -5642,13 +5598,6 @@ extern JS_PUBLIC_API(bool) JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options, const jschar *chars, size_t length, jsval *rval) { - Maybe mava; - if (options.versionSet) { - mava.construct(cx->runtime(), options.version); - // AutoVersionAPI propagates some compilation flags through. - options.version = mava.ref().version(); - } - JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); From 3cd31353c3a1f94b31fa1042a1d9391824fae95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Thu, 13 Jun 2013 19:18:53 +0200 Subject: [PATCH 056/615] Bug 882188 - Popup notifications in background windows should only ask for attention if they'll open automatically upon gaining focus. r=gavin --- toolkit/modules/PopupNotifications.jsm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toolkit/modules/PopupNotifications.jsm b/toolkit/modules/PopupNotifications.jsm index 8264c46c479b..a417accc9d59 100644 --- a/toolkit/modules/PopupNotifications.jsm +++ b/toolkit/modules/PopupNotifications.jsm @@ -264,7 +264,8 @@ PopupNotifications.prototype = { // tell the user that there's a notification waiting in that window. // At some point we might want to do something about background tabs here // too. - if (browser == this.tabbrowser.selectedBrowser) + if (!notification.dismissed && + browser == this.tabbrowser.selectedBrowser) this.window.getAttention(); // Notify observers that we're not showing the popup (useful for testing) From 96ffa33fa3502ba6ba49c30d00483c6798231af4 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Jun 2013 10:23:21 -0700 Subject: [PATCH 057/615] Bug 875917 - Add braces to an if which has braces on its else. r=sstangl --- js/src/ion/x86/CodeGenerator-x86.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/ion/x86/CodeGenerator-x86.cpp b/js/src/ion/x86/CodeGenerator-x86.cpp index 6e0bdb7980bf..004a09f2ae3b 100644 --- a/js/src/ion/x86/CodeGenerator-x86.cpp +++ b/js/src/ion/x86/CodeGenerator-x86.cpp @@ -503,9 +503,9 @@ CodeGeneratorX86::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins) bool CodeGeneratorX86::visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds *ool) { - if (ool->dest().isFloat()) + if (ool->dest().isFloat()) { masm.movsd(&js_NaN, ool->dest().fpu()); - else { + } else { Register destReg = ool->dest().gpr(); masm.xorl(destReg, destReg); } From ad23189c5adee48ee35ec1a8a71a7438d42fdaed Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 13 Jun 2013 10:23:30 -0700 Subject: [PATCH 058/615] Bug 875910 - Trim trailing whitespace. r=sstangl --- js/src/assembler/assembler/X86Assembler.h | 112 +++++++++++----------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/js/src/assembler/assembler/X86Assembler.h b/js/src/assembler/assembler/X86Assembler.h index 97f6977a7ecb..cb4f8c19632c 100644 --- a/js/src/assembler/assembler/X86Assembler.h +++ b/js/src/assembler/assembler/X86Assembler.h @@ -251,7 +251,7 @@ private: OP_HLT = 0xF4, OP_GROUP3_EbIb = 0xF6, OP_GROUP3_Ev = 0xF7, - OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. + OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. OP_GROUP5_Ev = 0xFF } OneByteOpcodeID; @@ -298,7 +298,7 @@ private: typedef enum { ESCAPE_PTEST = 0x38, ESCAPE_PINSRD = 0x3A, - ESCAPE_ROUNDSD = 0x3A + ESCAPE_ROUNDSD = 0x3A } ThreeByteEscape; TwoByteOpcodeID jccRel32(Condition cond) @@ -342,7 +342,7 @@ private: GROUP11_MOV = 0 } GroupOpcodeID; - + class X86InstructionFormatter; public: @@ -371,7 +371,7 @@ public: private: int m_offset; }; - + class JmpDst { friend class X86Assembler; friend class X86InstructionFormatter; @@ -821,7 +821,7 @@ public: m_formatter.immediate32(imm); } } - + void subl_im(int imm, int offset, RegisterID base) { spew("subl $0x%x, %s0x%x(%s)", @@ -957,7 +957,7 @@ public: spew("sarl %%cl, %s", nameIReg(4, dst)); m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); } - + void shrl_i8r(int imm, RegisterID dst) { spew("shrl $%d, %s", imm, nameIReg(4, dst)); @@ -968,7 +968,7 @@ public: m_formatter.immediate8(imm); } } - + void shrl_CLr(RegisterID dst) { spew("shrl %%cl, %s", nameIReg(4, dst)); @@ -1056,7 +1056,7 @@ public: void idivl_r(RegisterID divisor) { - spew("idivl %s", + spew("idivl %s", nameIReg(4, divisor)); m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, divisor); } @@ -1072,21 +1072,21 @@ public: void cmpl_rr(RegisterID src, RegisterID dst) { - spew("cmpl %s, %s", + spew("cmpl %s, %s", nameIReg(4, src), nameIReg(4, dst)); m_formatter.oneByteOp(OP_CMP_EvGv, src, dst); } void cmpl_rm(RegisterID src, int offset, RegisterID base) { - spew("cmpl %s, %s0x%x(%s)", + spew("cmpl %s, %s0x%x(%s)", nameIReg(4, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base)); m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset); } void cmpl_mr(int offset, RegisterID base, RegisterID src) { - spew("cmpl %s0x%x(%s), %s", + spew("cmpl %s0x%x(%s), %s", PRETTY_PRINT_OFFSET(offset), nameIReg(4, base), nameIReg(src)); m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset); } @@ -1114,7 +1114,7 @@ public: m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); m_formatter.immediate32(imm); } - + void cmpl_im(int imm, int offset, RegisterID base) { spew("cmpl $0x%x, %s0x%x(%s)", @@ -1127,13 +1127,13 @@ public: m_formatter.immediate32(imm); } } - + void cmpb_im(int imm, int offset, RegisterID base) { m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset); m_formatter.immediate8(imm); } - + void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) { m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset); @@ -1279,7 +1279,7 @@ public: nameIReg(1,src), nameIReg(1,dst)); m_formatter.oneByteOp(OP_TEST_EbGb, src, dst); } - + void testl_i32r(int imm, RegisterID dst) { #if WTF_CPU_X86_64 @@ -1304,13 +1304,13 @@ public: m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); m_formatter.immediate32(imm); } - + void testb_im(int imm, int offset, RegisterID base) { m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset); m_formatter.immediate8(imm); } - + void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) { m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset); @@ -1358,7 +1358,7 @@ public: m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset); m_formatter.immediate32(imm); } -#endif +#endif void testw_rr(RegisterID src, RegisterID dst) { @@ -1366,7 +1366,7 @@ public: m_formatter.prefix(PRE_OPERAND_SIZE); m_formatter.oneByteOp(OP_TEST_EvGv, src, dst); } - + void testb_i8r(int imm, RegisterID dst) { spew("testb $0x%x, %s", @@ -1444,7 +1444,7 @@ public: m_formatter.prefix(PRE_OPERAND_SIZE); m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset); } - + void movw_rm_disp32(RegisterID src, int offset, RegisterID base) { spew("movw %s, %s0x%x(%s)", @@ -1452,7 +1452,7 @@ public: m_formatter.prefix(PRE_OPERAND_SIZE); m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset); } - + void movl_rm(RegisterID src, int offset, RegisterID base) { spew("movl %s, %s0x%x(%s)", @@ -1468,7 +1468,7 @@ public: void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale) { - spew("movw %s, %d(%s,%s,%d)", + spew("movw %s, %d(%s,%s,%d)", nameIReg(2, src), offset, nameIReg(base), nameIReg(index), 1<(m_formatter.data()); setRel32(code + from.m_offset, code + to.m_offset); } - + static void linkJump(void* code, JmpSrc from, void* to) { ASSERT(from.m_offset != -1); @@ -2754,7 +2754,7 @@ public: intptr_t offset = reinterpret_cast(to) - reinterpret_cast(from); return (offset == static_cast(offset)); } - + static void relinkCall(void* from, void* to) { staticSpew("##relinkCall ((from=%p)) ((to=%p))", @@ -2788,7 +2788,7 @@ public: #endif *reinterpret_cast(where) = static_cast(OP_LEA); } - + static void repatchLEAToLoadPtr(void* where) { staticSpew("##repatchLEAToLoadPtr ((where=%p))", @@ -2813,29 +2813,29 @@ public: return reinterpret_cast(reinterpret_cast(code) + jump.m_offset); } - + static void* getRelocatedAddress(void* code, JmpDst destination) { ASSERT(destination.m_offset != -1); return reinterpret_cast(reinterpret_cast(code) + destination.m_offset); } - + static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) { return dst.m_offset - src.m_offset; } - + static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) { return dst.m_offset - src.m_offset; } - + static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) { return dst.m_offset - src.m_offset; } - + void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool **poolp, CodeKind kind) { return m_formatter.executableAllocAndCopy(allocator, poolp, kind); @@ -3342,7 +3342,7 @@ private: // Used for operations with byte operands - use byteRegRequiresRex() to check register operands, // regRequiresRex() to check other registers (i.e. address base & index). - // + // // NB: WebKit's use of emitRexIf() is limited such that the reqRequiresRex() checks are // not needed. SpiderMonkey extends oneByteOp8 functionality such that r, x, and b can // all be used. @@ -3423,7 +3423,7 @@ private: } } } - + void memoryModRM_disp32(int reg, RegisterID base, int offset) { // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. @@ -3440,7 +3440,7 @@ private: m_buffer.putIntUnchecked(offset); } } - + void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset) { ASSERT(index != noIndex); From 5e38907e9d5f8bdd9605114be92d93a23a36d5ab Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 12 Jun 2013 17:58:59 -0700 Subject: [PATCH 059/615] Bug 882482 - Do not use the store buffer off the main thread; r=nmatsakis --HG-- extra : rebase_source : c557b8d5c27bfc55f86cae2898fc5744fc74214f --- js/src/gc/StoreBuffer.cpp | 7 +++++++ js/src/gc/StoreBuffer.h | 8 ++++++++ js/src/jsobjinlines.h | 10 +++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/js/src/gc/StoreBuffer.cpp b/js/src/gc/StoreBuffer.cpp index 5e95b8f79380..0378d836027c 100644 --- a/js/src/gc/StoreBuffer.cpp +++ b/js/src/gc/StoreBuffer.cpp @@ -10,6 +10,7 @@ #include "gc/Barrier-inl.h" #include "gc/StoreBuffer.h" +#include "vm/ForkJoin.h" #include "vm/ObjectImpl-inl.h" using namespace js; @@ -473,6 +474,12 @@ StoreBuffer::releaseVerificationData() edgeSet.finish(); } +bool +StoreBuffer::inParallelSection() const +{ + return InParallelSection(); +} + JS_PUBLIC_API(void) JS::HeapCellPostBarrier(js::gc::Cell **cellp) { diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 9b25e6dbefb8..b720e24b1c73 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -181,6 +181,8 @@ class StoreBuffer /* Add one item to the buffer. */ void put(const T &v) { + JS_ASSERT(!owner->inParallelSection()); + /* Check if we have been enabled. */ if (!pos) return; @@ -229,6 +231,7 @@ class StoreBuffer /* Record a removal from the buffer. */ void unput(const T &v) { + JS_ASSERT(!this->owner->inParallelSection()); MonoTypeBuffer::put(v.tagged()); } }; @@ -261,6 +264,8 @@ class StoreBuffer template void put(const T &t) { + JS_ASSERT(!owner->inParallelSection()); + /* Check if we have been enabled. */ if (!pos) return; @@ -493,6 +498,9 @@ class StoreBuffer void releaseVerificationData(); bool containsEdgeAt(void *loc) const; + /* We cannot call InParallelSection directly because of a circular dependency. */ + bool inParallelSection() const; + /* For use by our owned buffers and for testing. */ void setAboutToOverflow(); void setOverflowed(); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 888b1843d06d..404c26f06bd7 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -656,13 +656,13 @@ JSObject::parExtendDenseElements(js::Allocator *alloc, js::Value *v, uint32_t ex js::HeapSlot *sp = elements + initializedLength; if (v) { - for (uint32_t i = 0; i < extra; i++) - sp[i].init(runtime(), this, js::HeapSlot::Element, initializedLength+i, v[i]); - } else { for (uint32_t i = 0; i < extra; i++) { - sp[i].init(runtime(), this, js::HeapSlot::Element, - initializedLength + i, js::MagicValue(JS_ELEMENTS_HOLE)); + JS_ASSERT_IF(v[i].isMarkable(), static_cast(v[i].toGCThing())->isTenured()); + *sp[i].unsafeGet() = v[i]; } + } else { + for (uint32_t i = 0; i < extra; i++) + *sp[i].unsafeGet() = js::MagicValue(JS_ELEMENTS_HOLE); } header->initializedLength = requiredCapacity; if (header->length < requiredCapacity) From 1f8d40499c98253a66d6893d17f03d2ca70adfcd Mon Sep 17 00:00:00 2001 From: Steve Workman Date: Thu, 13 Jun 2013 10:42:48 -0700 Subject: [PATCH 060/615] Bug 497003 - Support delivery of OnDataAvailable off the main thread r=bz r=jduell --- netwerk/base/public/moz.build | 2 + netwerk/base/public/nsIInputStreamPump.idl | 7 +- .../public/nsIThreadRetargetableRequest.idl | 34 ++++ .../nsIThreadRetargetableStreamListener.idl | 34 ++++ netwerk/base/public/nsStreamListenerWrapper.h | 3 + netwerk/base/src/nsInputStreamPump.cpp | 71 +++++++- netwerk/base/src/nsInputStreamPump.h | 6 +- netwerk/base/src/nsStreamListenerTee.cpp | 22 ++- netwerk/base/src/nsStreamListenerTee.h | 3 + netwerk/base/src/nsStreamListenerWrapper.cpp | 18 +- netwerk/protocol/http/nsHttpChannel.cpp | 155 +++++++++++++++++- netwerk/protocol/http/nsHttpChannel.h | 8 + netwerk/test/httpserver/httpd.js | 5 +- netwerk/test/mochitests/Makefile.in | 21 +++ netwerk/test/mochitests/moz.build | 7 + netwerk/test/mochitests/partial_content.sjs | 133 +++++++++++++++ .../test_partially_cached_content.html | 78 +++++++++ netwerk/test/moz.build | 2 +- 18 files changed, 586 insertions(+), 23 deletions(-) create mode 100644 netwerk/base/public/nsIThreadRetargetableRequest.idl create mode 100644 netwerk/base/public/nsIThreadRetargetableStreamListener.idl create mode 100644 netwerk/test/mochitests/Makefile.in create mode 100644 netwerk/test/mochitests/moz.build create mode 100644 netwerk/test/mochitests/partial_content.sjs create mode 100644 netwerk/test/mochitests/test_partially_cached_content.html diff --git a/netwerk/base/public/moz.build b/netwerk/base/public/moz.build index 767670975a4f..cfc90acab7b9 100644 --- a/netwerk/base/public/moz.build +++ b/netwerk/base/public/moz.build @@ -95,6 +95,8 @@ XPIDL_SOURCES += [ 'nsIStrictTransportSecurityService.idl', 'nsISyncStreamListener.idl', 'nsISystemProxySettings.idl', + 'nsIThreadRetargetableRequest.idl', + 'nsIThreadRetargetableStreamListener.idl', 'nsITimedChannel.idl', 'nsITraceableChannel.idl', 'nsITransport.idl', diff --git a/netwerk/base/public/nsIInputStreamPump.idl b/netwerk/base/public/nsIInputStreamPump.idl index 823fac5d86d6..83c29cdbb5b5 100644 --- a/netwerk/base/public/nsIInputStreamPump.idl +++ b/netwerk/base/public/nsIInputStreamPump.idl @@ -11,10 +11,11 @@ interface nsIStreamListener; * nsIInputStreamPump * * This interface provides a means to configure and use a input stream pump - * instance. The input stream pump will asynchronously read from a input - * stream, and push data to a nsIStreamListener instance. It utilizes the + * instance. The input stream pump will asynchronously read from an input + * stream, and push data to an nsIStreamListener instance. It utilizes the * current thread's nsIEventTarget in order to make reading from the stream - * asynchronous. + * asynchronous. A different thread can be used if the pump also implements + * nsIThreadRetargetableRequest. * * If the given stream supports nsIAsyncInputStream, then the stream pump will * call the stream's AsyncWait method to drive the stream listener. Otherwise, diff --git a/netwerk/base/public/nsIThreadRetargetableRequest.idl b/netwerk/base/public/nsIThreadRetargetableRequest.idl new file mode 100644 index 000000000000..a36291b07ad2 --- /dev/null +++ b/netwerk/base/public/nsIThreadRetargetableRequest.idl @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsISupports.idl" +#include "nsIEventTarget.idl" + +/** + * nsIThreadRetargetableRequest + * + * Should be implemented by requests that support retargeting delivery of + * OnDataAvailable and OnStopRequest off the main thread. + */ +[uuid(27b84c48-5a73-4ba4-a8a4-8b5e649a145e)] +interface nsIThreadRetargetableRequest : nsISupports +{ + /** + * Called to retarget delivery of OnDataAvailable and OnStopRequest to + * another thread. Should only be called within the context of OnStartRequest + * on the main thread. + * + * @param aNewTarget New event target, e.g. thread or threadpool. + * + * Note: no return value is given. If the retargeting cannot be handled, + * normal delivery to the main thread will continue. As such, listeners + * should be ready to deal with OnDataAvailable and OnStopRequest on + * either the main thread or the new target thread. + */ + void retargetDeliveryTo(in nsIEventTarget aNewTarget); +}; + + diff --git a/netwerk/base/public/nsIThreadRetargetableStreamListener.idl b/netwerk/base/public/nsIThreadRetargetableStreamListener.idl new file mode 100644 index 000000000000..4f1f9fa17046 --- /dev/null +++ b/netwerk/base/public/nsIThreadRetargetableStreamListener.idl @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "nsISupports.idl" + +/** + * nsIThreadRetargetableListener + * + * To be used by classes which implement nsIStreamListener and whose + * OnDataAvailable and OnStopRequest may be retargeted for delivery off the + * main thread. + */ +[uuid(fb2304b8-f82f-4433-af68-d874a2ebbdc1)] +interface nsIThreadRetargetableStreamListener : nsISupports +{ + /** + * Checks this listener and any next listeners it may have to verify that + * they can receive OnDataAvailable and OnStopRequest off the main thread. + * It is the responsibility of the implementing class to decide on the + * criteria to determine if retargeted delivery of these methods is + * possible, but it must check any and all nsIStreamListener objects that + * might be called in the listener chain. + * + * An exception should be thrown if a listener in the chain does not + * support retargeted delivery, i.e. if the next listener does not implement + * nsIThreadRetargetableStreamListener, or a call to its checkListenerChain() + * fails. + */ + void checkListenerChain(); +}; + diff --git a/netwerk/base/public/nsStreamListenerWrapper.h b/netwerk/base/public/nsStreamListenerWrapper.h index 38957d43aa1e..af9bd2bcedca 100644 --- a/netwerk/base/public/nsStreamListenerWrapper.h +++ b/netwerk/base/public/nsStreamListenerWrapper.h @@ -8,11 +8,13 @@ #include "nsCOMPtr.h" #include "nsIStreamListener.h" #include "nsIRequestObserver.h" +#include "nsIThreadRetargetableStreamListener.h" #include "mozilla/Attributes.h" // Wrapper class to make replacement of nsHttpChannel's listener // from JavaScript possible. It is workaround for bug 433711 and 682305. class nsStreamListenerWrapper MOZ_FINAL : public nsIStreamListener + , public nsIThreadRetargetableStreamListener { public: nsStreamListenerWrapper(nsIStreamListener *listener) @@ -24,6 +26,7 @@ public: NS_DECL_ISUPPORTS NS_FORWARD_NSIREQUESTOBSERVER(mListener->) NS_FORWARD_NSISTREAMLISTENER(mListener->) + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER private: ~nsStreamListenerWrapper() {} diff --git a/netwerk/base/src/nsInputStreamPump.cpp b/netwerk/base/src/nsInputStreamPump.cpp index aff5fb79a5dd..deafbadee7aa 100644 --- a/netwerk/base/src/nsInputStreamPump.cpp +++ b/netwerk/base/src/nsInputStreamPump.cpp @@ -11,10 +11,13 @@ #include "nsIInterfaceRequestorUtils.h" #include "nsISeekableStream.h" #include "nsITransport.h" +#include "nsIThreadRetargetableStreamListener.h" +#include "nsStreamUtils.h" #include "nsNetUtil.h" #include "nsThreadUtils.h" #include "nsCOMPtr.h" #include "prlog.h" +#include "nsPrintfCString.h" #include "GeckoProfiler.h" #include @@ -41,6 +44,7 @@ nsInputStreamPump::nsInputStreamPump() , mLoadFlags(LOAD_NORMAL) , mWaiting(false) , mCloseWhenDone(false) + , mRetargeting(false) { #if defined(PR_LOGGING) if (!gStreamPumpLog) @@ -119,14 +123,18 @@ nsresult nsInputStreamPump::EnsureWaiting() { // no need to worry about multiple threads... an input stream pump lives - // on only one thread. - + // on only one thread at a time. + MOZ_ASSERT(mAsyncStream); if (!mWaiting) { + MOZ_ASSERT(mTargetThread); nsresult rv = mAsyncStream->AsyncWait(this, 0, 0, mTargetThread); if (NS_FAILED(rv)) { NS_ERROR("AsyncWait failed"); return rv; } + // Any retargeting during STATE_START or START_TRANSFER is complete + // after the call to AsyncWait; next callback wil be on mTargetThread. + mRetargeting = false; mWaiting = true; } return NS_OK; @@ -139,8 +147,9 @@ nsInputStreamPump::EnsureWaiting() // although this class can only be accessed from one thread at a time, we do // allow its ownership to move from thread to thread, assuming the consumer // understands the limitations of this. -NS_IMPL_THREADSAFE_ISUPPORTS3(nsInputStreamPump, +NS_IMPL_THREADSAFE_ISUPPORTS4(nsInputStreamPump, nsIRequest, + nsIThreadRetargetableRequest, nsIInputStreamCallback, nsIInputStreamPump) @@ -380,15 +389,30 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream) return NS_ERROR_UNEXPECTED; } - if (mState == nextState && !mSuspendCount) { - NS_ASSERTION(mState == STATE_TRANSFER, "unexpected state"); - NS_ASSERTION(NS_SUCCEEDED(mStatus), "unexpected status"); + bool stillTransferring = (mState == STATE_TRANSFER && + nextState == STATE_TRANSFER); + if (stillTransferring) { + NS_ASSERTION(NS_SUCCEEDED(mStatus), + "Should not have failed status for ongoing transfer"); + } else { + NS_ASSERTION(mState != nextState, + "Only OnStateTransfer can be called more than once."); + } + if (mRetargeting) { + NS_ASSERTION(mState != STATE_STOP, + "Retargeting should not happen during OnStateStop."); + } + // Wait asynchronously if there is still data to transfer, or if + // delivery of data has been requested on another thread. + if (!mSuspendCount && (stillTransferring || mRetargeting)) { + mState = nextState; mWaiting = false; mStatus = EnsureWaiting(); if (NS_SUCCEEDED(mStatus)) break; + // Failure to start asynchronous wait: stop transfer. nextState = STATE_STOP; } @@ -551,6 +575,7 @@ nsInputStreamPump::OnStateStop() mAsyncStream = 0; mTargetThread = 0; mIsPending = false; + mRetargeting = false; mListener->OnStopRequest(this, mListenerContext, mStatus); mListener = 0; @@ -561,3 +586,37 @@ nsInputStreamPump::OnStateStop() return STATE_IDLE; } + +//----------------------------------------------------------------------------- +// nsIThreadRetargetableRequest +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsInputStreamPump::RetargetDeliveryTo(nsIEventTarget* aNewTarget) +{ + NS_ENSURE_ARG(aNewTarget); + if (aNewTarget == mTargetThread) { + NS_WARNING("Retargeting delivery to same thread"); + return NS_OK; + } + NS_ENSURE_TRUE(mState == STATE_START || mState == STATE_TRANSFER, + NS_ERROR_UNEXPECTED); + + // Ensure that |mListener| and any subsequent listeners can be retargeted + // to another thread. + nsresult rv = NS_OK; + nsCOMPtr retargetableListener = + do_QueryInterface(mListener, &rv); + if (NS_SUCCEEDED(rv) && retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + if (NS_SUCCEEDED(rv)) { + mTargetThread = aNewTarget; + mRetargeting = true; + } + } + LOG(("nsInputStreamPump::RetargetDeliveryTo [this=%x aNewTarget=%p] " + "%s listener [%p] rv[%x]", + this, aNewTarget, (mTargetThread == aNewTarget ? "success" : "failure"), + (nsIStreamListener*)mListener, rv)); + return rv; +} diff --git a/netwerk/base/src/nsInputStreamPump.h b/netwerk/base/src/nsInputStreamPump.h index ee72b0b8c0e0..c9c2e440ea8c 100644 --- a/netwerk/base/src/nsInputStreamPump.h +++ b/netwerk/base/src/nsInputStreamPump.h @@ -15,17 +15,20 @@ #include "nsIProgressEventSink.h" #include "nsIAsyncInputStream.h" #include "nsIThread.h" +#include "nsIThreadRetargetableRequest.h" #include "nsCOMPtr.h" #include "mozilla/Attributes.h" class nsInputStreamPump MOZ_FINAL : public nsIInputStreamPump , public nsIInputStreamCallback + , public nsIThreadRetargetableRequest { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST NS_DECL_NSIINPUTSTREAMPUMP NS_DECL_NSIINPUTSTREAMCALLBACK + NS_DECL_NSITHREADRETARGETABLEREQUEST nsInputStreamPump(); ~nsInputStreamPump(); @@ -71,7 +74,7 @@ protected: nsCOMPtr mLoadGroup; nsCOMPtr mListener; nsCOMPtr mListenerContext; - nsCOMPtr mTargetThread; + nsCOMPtr mTargetThread; nsCOMPtr mStream; nsCOMPtr mAsyncStream; uint64_t mStreamOffset; @@ -84,6 +87,7 @@ protected: bool mIsPending; bool mWaiting; // true if waiting on async source bool mCloseWhenDone; + bool mRetargeting; }; #endif // !nsInputStreamChannel_h__ diff --git a/netwerk/base/src/nsStreamListenerTee.cpp b/netwerk/base/src/nsStreamListenerTee.cpp index 51d7b47d16b0..6834f0f8e77c 100644 --- a/netwerk/base/src/nsStreamListenerTee.cpp +++ b/netwerk/base/src/nsStreamListenerTee.cpp @@ -5,10 +5,11 @@ #include "nsStreamListenerTee.h" #include "nsProxyRelease.h" -NS_IMPL_ISUPPORTS3(nsStreamListenerTee, - nsIStreamListener, - nsIRequestObserver, - nsIStreamListenerTee) +NS_IMPL_THREADSAFE_ISUPPORTS4(nsStreamListenerTee, + nsIStreamListener, + nsIRequestObserver, + nsIStreamListenerTee, + nsIThreadRetargetableStreamListener) NS_IMETHODIMP nsStreamListenerTee::OnStartRequest(nsIRequest *request, @@ -92,6 +93,19 @@ nsStreamListenerTee::OnDataAvailable(nsIRequest *request, return mListener->OnDataAvailable(request, context, tee, offset, count); } +NS_IMETHODIMP +nsStreamListenerTee::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!"); + nsresult rv = NS_OK; + nsCOMPtr retargetableListener = + do_QueryInterface(mListener, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } + return rv; +} + NS_IMETHODIMP nsStreamListenerTee::Init(nsIStreamListener *listener, nsIOutputStream *sink, diff --git a/netwerk/base/src/nsStreamListenerTee.h b/netwerk/base/src/nsStreamListenerTee.h index 133aba33fe05..601f3b5e9ad9 100644 --- a/netwerk/base/src/nsStreamListenerTee.h +++ b/netwerk/base/src/nsStreamListenerTee.h @@ -6,17 +6,20 @@ #define nsStreamListenerTee_h__ #include "nsIStreamListenerTee.h" +#include "nsIThreadRetargetableStreamListener.h" #include "nsIInputStreamTee.h" #include "nsIOutputStream.h" #include "nsCOMPtr.h" #include "nsIEventTarget.h" class nsStreamListenerTee : public nsIStreamListenerTee + , public nsIThreadRetargetableStreamListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER NS_DECL_NSISTREAMLISTENERTEE nsStreamListenerTee() { } diff --git a/netwerk/base/src/nsStreamListenerWrapper.cpp b/netwerk/base/src/nsStreamListenerWrapper.cpp index 0b2cd7b3dc7c..ada9a1d4890e 100644 --- a/netwerk/base/src/nsStreamListenerWrapper.cpp +++ b/netwerk/base/src/nsStreamListenerWrapper.cpp @@ -3,8 +3,22 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsStreamListenerWrapper.h" +#include "nsThreadUtils.h" -NS_IMPL_ISUPPORTS2(nsStreamListenerWrapper, +NS_IMPL_ISUPPORTS3(nsStreamListenerWrapper, nsIStreamListener, - nsIRequestObserver) + nsIRequestObserver, + nsIThreadRetargetableStreamListener) +NS_IMETHODIMP +nsStreamListenerWrapper::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!"); + nsresult rv = NS_OK; + nsCOMPtr retargetableListener = + do_QueryInterface(mListener, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } + return rv; +} diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 9d31f08bad11..a3a6cc5b7be1 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -29,6 +29,7 @@ #include "nsIRedirectResultListener.h" #include "mozilla/TimeStamp.h" #include "nsError.h" +#include "nsPrintfCString.h" #include "nsAlgorithm.h" #include "GeckoProfiler.h" #include "nsIConsoleService.h" @@ -4252,6 +4253,8 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel) NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel) NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback) NS_INTERFACE_MAP_ENTRY(nsITimedChannel) + NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest) + NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener) NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel) //----------------------------------------------------------------------------- @@ -4943,6 +4946,42 @@ nsHttpChannel::ContinueOnStartRequest3(nsresult result) return CallOnStartRequest(); } +class OnStopRequestCleanupEvent : public nsRunnable +{ +public: + OnStopRequestCleanupEvent(nsHttpChannel *aHttpChannel, + nsresult aStatus) + : mHttpChannel(aHttpChannel) + , mStatus(aStatus) + { + MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread"); + NS_ASSERTION(aHttpChannel, "aHttpChannel should not be null"); + } + + NS_IMETHOD Run() + { + MOZ_ASSERT(NS_IsMainThread(), "Should run on main thread"); + if (mHttpChannel) { + mHttpChannel->OnStopRequestCleanup(mStatus); + } + return NS_OK; + } +private: + nsRefPtr mHttpChannel; + nsresult mStatus; +}; + +nsresult +nsHttpChannel::OnStopRequestCleanup(nsresult aStatus) +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread"); + if (mLoadGroup) { + mLoadGroup->RemoveRequest(this, nullptr, aStatus); + } + ReleaseListeners(); + return NS_OK; +} + NS_IMETHODIMP nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status) { @@ -5072,14 +5111,17 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st if (mOfflineCacheEntry) CloseOfflineCacheEntry(); - if (mLoadGroup) - mLoadGroup->RemoveRequest(this, nullptr, status); + if (NS_IsMainThread()) { + OnStopRequestCleanup(status); + } else { + nsresult rv = NS_DispatchToMainThread( + new OnStopRequestCleanupEvent(this, status)); + NS_ENSURE_SUCCESS(rv, rv); + } // We don't need this info anymore CleanRedirectCacheChainIfNecessary(); - ReleaseListeners(); - return NS_OK; } @@ -5087,6 +5129,37 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult st // nsHttpChannel::nsIStreamListener //----------------------------------------------------------------------------- +class OnTransportStatusAsyncEvent : public nsRunnable +{ +public: + OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink, + nsresult aTransportStatus, + uint64_t aProgress, + uint64_t aProgressMax) + : mEventSink(aEventSink) + , mTransportStatus(aTransportStatus) + , mProgress(aProgress) + , mProgressMax(aProgressMax) + { + MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread"); + } + + NS_IMETHOD Run() + { + MOZ_ASSERT(NS_IsMainThread(), "Should run on main thread"); + if (mEventSink) { + mEventSink->OnTransportStatus(nullptr, mTransportStatus, + mProgress, mProgressMax); + } + return NS_OK; + } +private: + nsCOMPtr mEventSink; + nsresult mTransportStatus; + uint64_t mProgress; + uint64_t mProgressMax; +}; + NS_IMETHODIMP nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, nsIInputStream *input, @@ -5131,7 +5204,14 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, uint64_t progress = mLogicalOffset + uint64_t(count); MOZ_ASSERT(progress <= progressMax, "unexpected progress values"); - OnTransportStatus(nullptr, transportStatus, progress, progressMax); + if (NS_IsMainThread()) { + OnTransportStatus(nullptr, transportStatus, progress, progressMax); + } else { + nsresult rv = NS_DispatchToMainThread( + new OnTransportStatusAsyncEvent(this, transportStatus, + progress, progressMax)); + NS_ENSURE_SUCCESS(rv, rv); + } // // we have to manually keep the logical offset of the stream up-to-date. @@ -5155,6 +5235,71 @@ nsHttpChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt, return NS_ERROR_ABORT; } +//----------------------------------------------------------------------------- +// nsHttpChannel::nsIThreadRetargetableRequest +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsHttpChannel::RetargetDeliveryTo(nsIEventTarget* aNewTarget) +{ + MOZ_ASSERT(NS_IsMainThread(), "Should be called on main thread only"); + + NS_ENSURE_ARG(aNewTarget); + if (aNewTarget == NS_GetCurrentThread()) { + NS_WARNING("Retargeting delivery to same thread"); + return NS_OK; + } + NS_ENSURE_TRUE(mTransactionPump || mCachePump, NS_ERROR_NOT_AVAILABLE); + + nsresult rv = NS_OK; + // If both cache pump and transaction pump exist, we're probably dealing + // with partially cached content. So, we must be able to retarget both. + nsCOMPtr retargetableCachePump; + nsCOMPtr retargetableTransactionPump; + if (mCachePump) { + // Direct call to QueryInterface to avoid multiple inheritance issues. + rv = mCachePump->QueryInterface(NS_GET_IID(nsIThreadRetargetableRequest), + getter_AddRefs(retargetableCachePump)); + // nsInputStreamPump should implement this interface. + MOZ_ASSERT(retargetableCachePump); + rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget); + } + if (NS_SUCCEEDED(rv) && mTransactionPump) { + // Direct call to QueryInterface to avoid multiple inheritance issues. + rv = mTransactionPump->QueryInterface(NS_GET_IID(nsIThreadRetargetableRequest), + getter_AddRefs(retargetableTransactionPump)); + // nsInputStreamPump should implement this interface. + MOZ_ASSERT(retargetableTransactionPump); + rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget); + + // If retarget fails for transaction pump, we must restore mCachePump. + if (NS_FAILED(rv) && retargetableCachePump) { + nsCOMPtr mainThread; + rv = NS_GetMainThread(getter_AddRefs(mainThread)); + NS_ENSURE_SUCCESS(rv, rv); + rv = retargetableCachePump->RetargetDeliveryTo(mainThread); + } + } + return rv; +} + +//----------------------------------------------------------------------------- +// nsHttpChannel::nsThreadRetargetableStreamListener +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsHttpChannel::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!"); + nsresult rv = NS_OK; + nsCOMPtr retargetableListener = + do_QueryInterface(mListener, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } + return rv; +} + //----------------------------------------------------------------------------- // nsHttpChannel::nsITransportEventSink //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index 3fd347bb06f6..be1838f53fd2 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -28,6 +28,8 @@ #include "nsIAsyncVerifyRedirectCallback.h" #include "nsITimedChannel.h" #include "nsIFile.h" +#include "nsIThreadRetargetableRequest.h" +#include "nsIThreadRetargetableStreamListener.h" #include "nsDNSPrefetch.h" #include "TimingStruct.h" #include "AutoClose.h" @@ -54,11 +56,14 @@ class nsHttpChannel : public HttpBaseChannel , public nsIApplicationCacheChannel , public nsIAsyncVerifyRedirectCallback , public nsITimedChannel + , public nsIThreadRetargetableRequest + , public nsIThreadRetargetableStreamListener { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER NS_DECL_NSICACHEINFOCHANNEL NS_DECL_NSICACHINGCHANNEL NS_DECL_NSICACHELISTENER @@ -69,6 +74,7 @@ public: NS_DECL_NSIAPPLICATIONCACHECHANNEL NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK NS_DECL_NSITIMEDCHANNEL + NS_DECL_NSITHREADRETARGETABLEREQUEST // nsIHttpAuthenticableChannel. We can't use // NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and @@ -150,6 +156,8 @@ public: /* internal necko use only */ OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker(); + nsresult OnStopRequestCleanup(nsresult aStatus); + private: typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result); diff --git a/netwerk/test/httpserver/httpd.js b/netwerk/test/httpserver/httpd.js index d16a65f8921a..fc9bbeb11f00 100644 --- a/netwerk/test/httpserver/httpd.js +++ b/netwerk/test/httpserver/httpd.js @@ -3974,7 +3974,10 @@ Response.prototype = var avail = bodyStream ? bodyStream.available() : 0; // XXX assumes stream will always report the full amount of data available - headers.setHeader("Content-Length", "" + avail, false); + // Set "Content-Length" if not already set by request handler. + if (!headers.hasHeader("Content-Length")) { + headers.setHeader("Content-Length", "" + avail, false); + } } diff --git a/netwerk/test/mochitests/Makefile.in b/netwerk/test/mochitests/Makefile.in new file mode 100644 index 000000000000..e1dd425ddb42 --- /dev/null +++ b/netwerk/test/mochitests/Makefile.in @@ -0,0 +1,21 @@ +# -*- Mode: Makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- +# vim: set ts=8 sts=2 et sw=2 tw=80: +# 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@ +relativesrcdir = @relativesrcdir@ +FAIL_ON_WARNINGS := 1 + +include $(DEPTH)/config/autoconf.mk + +MOCHITEST_FILES = \ + partial_content.sjs \ + test_partially_cached_content.html \ + $(NULL) + +include $(topsrcdir)/config/rules.mk diff --git a/netwerk/test/mochitests/moz.build b/netwerk/test/mochitests/moz.build new file mode 100644 index 000000000000..a6f020189e93 --- /dev/null +++ b/netwerk/test/mochitests/moz.build @@ -0,0 +1,7 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +MODULE = 'test_necko' diff --git a/netwerk/test/mochitests/partial_content.sjs b/netwerk/test/mochitests/partial_content.sjs new file mode 100644 index 000000000000..39fc44ede52b --- /dev/null +++ b/netwerk/test/mochitests/partial_content.sjs @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +// HTTP Version from request, used for response. +var gHttpVersion; + +/* Debug and Error wrapper functions for dump(). + */ +function ERR(response, responseCode, responseCodeStr, msg) +{ + // Dump to console log and send to client in response. + dump("SERVER ERROR: " + msg + "\n"); + response.setStatusLine(gHttpVersion, responseCode, responseCodeStr); + response.write(msg); +} + +function DBG(msg) +{ + // Dump to console only. + dump("SERVER DEBUG: " + msg + "\n"); +} + +/* Delivers content in parts to test partially cached content: requires two + * requests for the same resource. + * + * First call will respond with partial content, but a 200 header and + * Content-Length equal to the full content length. No Range or If-Range + * headers are allowed in the request. + * + * Second call will require Range and If-Range in the request headers, and + * will respond with the range requested. + */ +function handleRequest(request, response) +{ + // Set http version for error responses. + gHttpVersion = request.httpVersion; + + // All responses, inc. errors, are text/html. + response.setHeader("Content-Type", "text/html; charset=UTF-8", false); + + // Get state var to determine if this is the first or second request. + var expectedRequestType; + if (getState("expectedRequestType") === "") { + DBG("First call: Should be requesting full content."); + expectedRequestType = "fullRequest"; + // Set state var for second request. + setState("expectedRequestType", "partialRequest"); + } else if (getState("expectedRequestType") === "partialRequest") { + DBG("Second call: Should be requesting undelivered content."); + expectedRequestType = "partialRequest"; + // Reset state var for first request. + setState("expectedRequestType", ""); + } else { + ERR(response, 500, "Internal Server Error", + "Invalid expectedRequestType \"" + expectedRequestType + "\"in " + + "server state db."); + return; + } + + // Look for Range and If-Range + var range = request.hasHeader("Range") ? request.getHeader("Range") : ""; + var ifRange = request.hasHeader("If-Range") ? request.getHeader("If-Range") : ""; + + if (expectedRequestType === "fullRequest") { + // Should not have Range or If-Range in first request. + if (range && range.length > 0) { + ERR(response, 400, "Bad Request", + "Should not receive \"Range: " + range + "\" for first, full request."); + return; + } + if (ifRange && ifRange.length > 0) { + ERR(response, 400, "Bad Request", + "Should not receive \"Range: " + range + "\" for first, full request."); + return; + } + } else if (expectedRequestType === "partialRequest") { + // Range AND If-Range should both be present in second request. + if (!range) { + ERR(response, 400, "Bad Request", + "Should receive \"Range: \" for second, partial request."); + return; + } + if (!ifRange) { + ERR(response, 400, "Bad Request", + "Should receive \"If-Range: \" for second, partial request."); + return; + } + } else { + // Somewhat redundant, but a check for errors in this test code. + ERR(response, 500, "Internal Server Error", + "expectedRequestType not set correctly: \"" + expectedRequestType + "\""); + return; + } + + // Prepare content in two parts for responses. + var partialContent = "

" + + "First response

"; + var remainderContent = "

Second response

" + + ""; + var totalLength = partialContent.length + remainderContent.length; + + DBG("totalLength: " + totalLength); + + // Prepare common headers for the two responses. + response.setHeader("ETag", "abcd0123", false); + response.setHeader("Accept-Ranges", "bytes", false); + + // Prepare specific headers and content for first and second responses. + if (expectedRequestType === "fullRequest") { + DBG("First response: Sending partial content with a full header"); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.write(partialContent, partialContent.length); + // Set Content-Length to full length of resource. + response.setHeader("Content-Length", "" + totalLength, false); + } else if (expectedRequestType === "partialRequest") { + DBG("Second response: Sending remaining content with a range header"); + response.setStatusLine(request.httpVersion, 206, "Partial Content"); + response.setHeader("Content-Range", "bytes " + partialContent.length + "-" + + (totalLength - 1) + "/" + totalLength); + response.write(remainderContent); + // Set Content-Length to length of bytes transmitted. + response.setHeader("Content-Length", "" + remainderContent.length, false); + } else { + // Somewhat redundant, but a check for errors in this test code. + ERR(response, 500, "Internal Server Error", + "Something very bad happened here: expectedRequestType is invalid " + + "towards the end of handleRequest! - \"" + expectedRequestType + "\""); + return; + } +} diff --git a/netwerk/test/mochitests/test_partially_cached_content.html b/netwerk/test/mochitests/test_partially_cached_content.html new file mode 100644 index 000000000000..0c4ed80bba6d --- /dev/null +++ b/netwerk/test/mochitests/test_partially_cached_content.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 497003: support sending OnDataAvailable() to other threads + + + + +

Mozilla Bug 497003: support sending OnDataAvailable() to other threads

+

+ +
+
+
+ + diff --git a/netwerk/test/moz.build b/netwerk/test/moz.build index 1a9a164b938a..5fa67702c16e 100644 --- a/netwerk/test/moz.build +++ b/netwerk/test/moz.build @@ -4,7 +4,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -TEST_DIRS += ['httpserver', 'browser'] +TEST_DIRS += ['httpserver', 'browser', 'mochitests'] MODULE = 'test_necko' From 895826d5ede12526c69a53f7b9640831f3eae5b4 Mon Sep 17 00:00:00 2001 From: Steve Workman Date: Thu, 13 Jun 2013 10:42:48 -0700 Subject: [PATCH 061/615] Bug 497003 - Support delivery of OnDataAvailable on the HTML5 parser thread r=hsivonen r=bholley r=bz --- netwerk/base/src/nsStreamListenerTee.cpp | 10 +++ parser/html/nsHtml5StreamParser.cpp | 110 ++++++++++++++++++----- parser/html/nsHtml5StreamParser.h | 13 ++- parser/html/nsHtml5TreeOpExecutor.h | 1 - uriloader/base/nsURILoader.cpp | 61 ++++++++++--- xpcom/glue/nsProxyRelease.h | 2 + 6 files changed, 160 insertions(+), 37 deletions(-) diff --git a/netwerk/base/src/nsStreamListenerTee.cpp b/netwerk/base/src/nsStreamListenerTee.cpp index 6834f0f8e77c..625cd75efa71 100644 --- a/netwerk/base/src/nsStreamListenerTee.cpp +++ b/netwerk/base/src/nsStreamListenerTee.cpp @@ -103,6 +103,16 @@ nsStreamListenerTee::CheckListenerChain() if (retargetableListener) { rv = retargetableListener->CheckListenerChain(); } + if (NS_FAILED(rv)) { + return rv; + } + if (!mObserver) { + return rv; + } + retargetableListener = do_QueryInterface(mObserver, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } return rv; } diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index 13400c66a68c..6f00f1c85bff 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -26,6 +26,8 @@ #include "nsINestedURI.h" #include "nsCharsetSource.h" #include "nsIWyciwygChannel.h" +#include "nsIThreadRetargetableRequest.h" +#include "nsPrintfCString.h" #include "mozilla/dom/EncodingUtils.h" @@ -73,9 +75,10 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsHtml5StreamParser) NS_IMPL_CYCLE_COLLECTING_RELEASE(nsHtml5StreamParser) NS_INTERFACE_TABLE_HEAD(nsHtml5StreamParser) - NS_INTERFACE_TABLE2(nsHtml5StreamParser, + NS_INTERFACE_TABLE3(nsHtml5StreamParser, nsIStreamListener, - nsICharsetDetectionObserver) + nsICharsetDetectionObserver, + nsIThreadRetargetableStreamListener) NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHtml5StreamParser) NS_INTERFACE_MAP_END @@ -926,6 +929,14 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) mReparseForbidden = true; mFeedChardet = false; // can't restart anyway } + + // Attempt to retarget delivery of data (via OnDataAvailable) to the parser + // thread, rather than through the main thread. + nsCOMPtr threadRetargetableRequest = + do_QueryInterface(mRequest); + if (threadRetargetableRequest) { + threadRetargetableRequest->RetargetDeliveryTo(mThread); + } } if (mCharsetSource == kCharsetFromParentFrame) { @@ -960,6 +971,22 @@ nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) return NS_OK; } +NS_IMETHODIMP +nsHtml5StreamParser::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!"); + if (!mObserver) { + return NS_OK; + } + nsresult rv; + nsCOMPtr retargetable = + do_QueryInterface(mObserver, &rv); + if (NS_SUCCEEDED(rv) && retargetable) { + rv = retargetable->CheckListenerChain(); + } + return rv; +} + void nsHtml5StreamParser::DoStopRequest() { @@ -1013,19 +1040,24 @@ nsHtml5StreamParser::OnStopRequest(nsIRequest* aRequest, nsresult status) { NS_ASSERTION(mRequest == aRequest, "Got Stop on wrong stream."); - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread() || IsParserThread(), "Wrong thread!"); if (mObserver) { mObserver->OnStopRequest(aRequest, aContext, status); } - nsCOMPtr stopper = new nsHtml5RequestStopper(this); - if (NS_FAILED(mThread->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) { - NS_WARNING("Dispatching StopRequest event failed."); + if (NS_IsMainThread()) { + nsCOMPtr stopper = new nsHtml5RequestStopper(this); + if (NS_FAILED(mThread->Dispatch(stopper, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Dispatching StopRequest event failed."); + } + } else { + mozilla::MutexAutoLock autoLock(mTokenizerMutex); + DoStopRequest(); } return NS_OK; } void -nsHtml5StreamParser::DoDataAvailable(uint8_t* aBuffer, uint32_t aLength) +nsHtml5StreamParser::DoDataAvailable(const uint8_t* aBuffer, uint32_t aLength) { NS_ASSERTION(IsParserThread(), "Wrong thread!"); NS_PRECONDITION(STREAM_BEING_READ == mStreamState, @@ -1110,24 +1142,58 @@ nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest, NS_ASSERTION(mRequest == aRequest, "Got data on wrong stream."); uint32_t totalRead; - const mozilla::fallible_t fallible = mozilla::fallible_t(); - nsAutoArrayPtr data(new (fallible) uint8_t[aLength]); - if (!data) { - return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + // Main thread to parser thread dispatch requires copying to buffer first. + if (NS_IsMainThread()) { + const mozilla::fallible_t fallible = mozilla::fallible_t(); + nsAutoArrayPtr data(new (fallible) uint8_t[aLength]); + if (!data) { + return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + } + rv = aInStream->Read(reinterpret_cast(data.get()), + aLength, &totalRead); + NS_ENSURE_SUCCESS(rv, rv); + NS_ASSERTION(totalRead <= aLength, "Read more bytes than were available?"); + + nsCOMPtr dataAvailable = new nsHtml5DataAvailable(this, + data.forget(), + totalRead); + if (NS_FAILED(mThread->Dispatch(dataAvailable, nsIThread::DISPATCH_NORMAL))) { + NS_WARNING("Dispatching DataAvailable event failed."); + } + return rv; + } else { + NS_ASSERTION(IsParserThread(), "Wrong thread!"); + mozilla::MutexAutoLock autoLock(mTokenizerMutex); + + // Read directly from response buffer. + rv = aInStream->ReadSegments(CopySegmentsToParser, this, aLength, + &totalRead); + if (NS_FAILED(rv)) { + NS_WARNING("Failed reading response data to parser"); + return rv; + } + return NS_OK; } - rv = aInStream->Read(reinterpret_cast(data.get()), - aLength, &totalRead); - NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(totalRead <= aLength, "Read more bytes than were available?"); - nsCOMPtr dataAvailable = new nsHtml5DataAvailable(this, - data.forget(), - totalRead); - if (NS_FAILED(mThread->Dispatch(dataAvailable, nsIThread::DISPATCH_NORMAL))) { - NS_WARNING("Dispatching DataAvailable event failed."); - } - return rv; } +/* static */ +NS_METHOD +nsHtml5StreamParser::CopySegmentsToParser(nsIInputStream *aInStream, + void *aClosure, + const char *aFromSegment, + uint32_t aToOffset, + uint32_t aCount, + uint32_t *aWriteCount) +{ + nsHtml5StreamParser* parser = static_cast(aClosure); + + parser->DoDataAvailable((const uint8_t*)aFromSegment, aCount); + // Assume DoDataAvailable consumed all available bytes. + *aWriteCount = aCount; + return NS_OK; +} + + bool nsHtml5StreamParser::PreferredForInternalEncodingDecl(nsACString& aEncoding) { diff --git a/parser/html/nsHtml5StreamParser.h b/parser/html/nsHtml5StreamParser.h index a0776de5c626..c7dc36981531 100644 --- a/parser/html/nsHtml5StreamParser.h +++ b/parser/html/nsHtml5StreamParser.h @@ -20,6 +20,7 @@ #include "nsHtml5Speculation.h" #include "nsITimer.h" #include "nsICharsetDetector.h" +#include "nsIThreadRetargetableStreamListener.h" class nsHtml5Parser; @@ -101,6 +102,7 @@ enum eHtml5StreamState { }; class nsHtml5StreamParser : public nsIStreamListener, + public nsIThreadRetargetableStreamListener, public nsICharsetDetectionObserver { friend class nsHtml5RequestStopper; @@ -125,6 +127,8 @@ class nsHtml5StreamParser : public nsIStreamListener, NS_DECL_NSIREQUESTOBSERVER // nsIStreamListener methods: NS_DECL_NSISTREAMLISTENER + // nsIThreadRetargetableStreamListener methods: + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER // nsICharsetDetectionObserver /** @@ -239,7 +243,14 @@ class nsHtml5StreamParser : public nsIStreamListener, void DoStopRequest(); - void DoDataAvailable(uint8_t* aBuffer, uint32_t aLength); + void DoDataAvailable(const uint8_t* aBuffer, uint32_t aLength); + + static NS_METHOD CopySegmentsToParser(nsIInputStream *aInStream, + void *aClosure, + const char *aFromSegment, + uint32_t aToOffset, + uint32_t aCount, + uint32_t *aWriteCount); bool IsTerminatedOrInterrupted() { mozilla::MutexAutoLock autoLock(mTerminatedMutex); diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index c01d802901b6..dce1a088d6e2 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -228,7 +228,6 @@ class nsHtml5TreeOpExecutor : public nsContentSink, * value if broken. */ inline nsresult IsBroken() { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); return mBroken; } diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp index a03930dcb48f..ebbbf7f16a74 100644 --- a/uriloader/base/nsURILoader.cpp +++ b/uriloader/base/nsURILoader.cpp @@ -6,6 +6,7 @@ #include "nsURILoader.h" #include "nsAutoPtr.h" +#include "nsProxyRelease.h" #include "nsIURIContentListener.h" #include "nsIContentHandler.h" #include "nsILoadGroup.h" @@ -30,10 +31,12 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeOwner.h" +#include "nsIThreadRetargetableStreamListener.h" #include "nsXPIDLString.h" #include "nsString.h" #include "nsNetUtil.h" +#include "nsThreadUtils.h" #include "nsReadableUtils.h" #include "nsError.h" @@ -63,6 +66,7 @@ PRLogModuleInfo* nsURILoader::mLog = nullptr; * (or aborted). */ class nsDocumentOpenInfo MOZ_FINAL : public nsIStreamListener + , public nsIThreadRetargetableStreamListener { public: // Needed for nsCOMPtr to work right... Don't call this! @@ -110,6 +114,8 @@ public: // nsIStreamListener methods: NS_DECL_NSISTREAMLISTENER + // nsIThreadRetargetableStreamListener + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER protected: ~nsDocumentOpenInfo(); @@ -124,7 +130,7 @@ protected: * The stream listener to forward nsIStreamListener notifications * to. This is set once the load is dispatched. */ - nsCOMPtr m_targetStreamListener; + nsMainThreadPtrHandle m_targetStreamListener; /** * A pointer to the entity that originated the load. We depend on getting @@ -159,6 +165,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocumentOpenInfo) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener) NS_INTERFACE_MAP_END_THREADSAFE nsDocumentOpenInfo::nsDocumentOpenInfo() @@ -266,6 +273,22 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStartRequest(nsIRequest *request, nsISupport return rv; } +NS_IMETHODIMP +nsDocumentOpenInfo::CheckListenerChain() +{ + NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread!"); + nsresult rv = NS_OK; + nsCOMPtr retargetableListener = + do_QueryInterface(m_targetStreamListener, &rv); + if (retargetableListener) { + rv = retargetableListener->CheckListenerChain(); + } + LOG(("[0x%p] nsDocumentOpenInfo::CheckListenerChain %s listener %p rv %x", + this, (NS_SUCCEEDED(rv) ? "success" : "failure"), + (nsIStreamListener*)m_targetStreamListener, rv)); + return rv; +} + NS_IMETHODIMP nsDocumentOpenInfo::OnDataAvailable(nsIRequest *request, nsISupports * aCtxt, nsIInputStream * inStr, @@ -288,7 +311,7 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStopRequest(nsIRequest *request, nsISupports if ( m_targetStreamListener) { - nsCOMPtr listener(m_targetStreamListener); + nsMainThreadPtrHandle listener = m_targetStreamListener; // If this is a multipart stream, we could get another // OnStartRequest after this... reset state. @@ -514,11 +537,15 @@ nsresult nsDocumentOpenInfo::DispatchContent(nsIRequest *request, nsISupports * aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_GUESS_FROM_EXT)); } + nsCOMPtr listener; rv = helperAppService->DoContent(mContentType, request, m_originalContext, false, - getter_AddRefs(m_targetStreamListener)); + getter_AddRefs(listener)); + // Passing false here to allow off main thread use. + m_targetStreamListener + = new nsMainThreadPtrHolder(listener, false); if (NS_FAILED(rv)) { request->SetLoadFlags(loadFlags); m_targetStreamListener = nullptr; @@ -558,7 +585,7 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request, // stream is split up into multiple destination streams. This // intermediate instance is used to target these "decoded" streams... // - nsCOMPtr nextLink = + nsRefPtr nextLink = new nsDocumentOpenInfo(m_originalContext, mFlags, mURILoader); if (!nextLink) return NS_ERROR_OUT_OF_MEMORY; @@ -581,11 +608,16 @@ nsDocumentOpenInfo::ConvertData(nsIRequest *request, // stream converter and sets the output end of the stream converter to // nextLink. As we pump data into m_targetStreamListener the stream // converter will convert it and pass the converted data to nextLink. - return StreamConvService->AsyncConvertData(PromiseFlatCString(aSrcContentType).get(), - PromiseFlatCString(aOutContentType).get(), - nextLink, - request, - getter_AddRefs(m_targetStreamListener)); + nsCOMPtr listener; + rv = StreamConvService->AsyncConvertData(PromiseFlatCString(aSrcContentType).get(), + PromiseFlatCString(aOutContentType).get(), + nextLink, + request, + getter_AddRefs(listener)); + // Passing false here to allow off main thread use. + m_targetStreamListener + = new nsMainThreadPtrHolder(listener, false); + return rv; } bool @@ -630,7 +662,7 @@ nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener, // m_targetStreamListener is now the input end of the converter, and we can // just pump the data in there, if it exists. If it does not, we need to // try other nsIURIContentListeners. - return m_targetStreamListener != nullptr; + return m_targetStreamListener.get() != nullptr; } // At this point, aListener wants data of type mContentType. Let 'em have @@ -652,12 +684,15 @@ nsDocumentOpenInfo::TryContentListener(nsIURIContentListener* aListener, bool abort = false; bool isPreferred = (mFlags & nsIURILoader::IS_CONTENT_PREFERRED) != 0; + nsCOMPtr listener; nsresult rv = aListener->DoContent(mContentType.get(), isPreferred, aChannel, - getter_AddRefs(m_targetStreamListener), + getter_AddRefs(listener), &abort); - + // Passing false here to allow off main thread use. + m_targetStreamListener + = new nsMainThreadPtrHolder(listener, false); if (NS_FAILED(rv)) { LOG_ERROR((" DoContent failed")); @@ -812,7 +847,7 @@ nsresult nsURILoader::OpenChannel(nsIChannel* channel, // we need to create a DocumentOpenInfo object which will go ahead and open // the url and discover the content type.... - nsCOMPtr loader = + nsRefPtr loader = new nsDocumentOpenInfo(aWindowContext, aFlags, this); if (!loader) return NS_ERROR_OUT_OF_MEMORY; diff --git a/xpcom/glue/nsProxyRelease.h b/xpcom/glue/nsProxyRelease.h index b1ce72fe2661..3ba9faab256f 100644 --- a/xpcom/glue/nsProxyRelease.h +++ b/xpcom/glue/nsProxyRelease.h @@ -203,6 +203,8 @@ class nsMainThreadPtrHandle operator T*() { return get(); } T* operator->() { return get(); } + operator bool() { return get(); } + // These are safe to call on other threads with appropriate external locking. bool operator==(const nsMainThreadPtrHandle& aOther) const { if (!mPtr || !aOther.mPtr) From 93ef95a3386c917f5116de2ce95eb31d228e84fd Mon Sep 17 00:00:00 2001 From: Henrik Skupin Date: Thu, 13 Jun 2013 19:43:45 +0200 Subject: [PATCH 062/615] Bug 881658 - Fix handling of error and event callbacks in current WebRTC Mochitests. r=jsmith --HG-- extra : rebase_source : 1d98e4ce4f339f757f60b98e49ab2e28a8e5912f --- dom/media/tests/mochitest/head.js | 42 ++- .../tests/mochitest/mediaStreamPlayback.js | 9 +- dom/media/tests/mochitest/pc.js | 280 +++++++++++------- .../mochitest/test_dataChannel_noOffer.html | 2 +- .../test_getUserMedia_basicAudio.html | 4 +- .../test_getUserMedia_basicVideo.html | 4 +- .../test_getUserMedia_basicVideoAudio.html | 4 +- .../test_getUserMedia_gumWithinGum.html | 8 +- .../test_getUserMedia_playAudioTwice.html | 6 +- ...test_getUserMedia_playVideoAudioTwice.html | 6 +- .../test_getUserMedia_playVideoTwice.html | 6 +- .../test_getUserMedia_stopAudioStream.html | 4 +- ...edia_stopAudioStreamWithFollowupAudio.html | 8 +- ...est_getUserMedia_stopVideoAudioStream.html | 4 +- ...ideoAudioStreamWithFollowupVideoAudio.html | 8 +- .../test_getUserMedia_stopVideoStream.html | 4 +- ...edia_stopVideoStreamWithFollowupVideo.html | 8 +- .../test_peerConnection_errorCallbacks.html | 14 +- .../test_peerConnection_throwInCallbacks.html | 22 +- 19 files changed, 263 insertions(+), 180 deletions(-) diff --git a/dom/media/tests/mochitest/head.js b/dom/media/tests/mochitest/head.js index 2099790644be..23172d33bb6d 100644 --- a/dom/media/tests/mochitest/head.js +++ b/dom/media/tests/mochitest/head.js @@ -122,7 +122,7 @@ function runTest(aCallback) { aCallback(); } catch (err) { - unexpectedCallbackAndFinish(new Error)(err); + unexpectedCallbackAndFinish()(err); } }); } @@ -170,35 +170,45 @@ function checkMediaStreamTracks(constraints, mediaStream) { * while running the tests. The generated function kills off the test as well * gracefully. * - * @param {Error} error - * A new Error object, generated at the callback site, from which a - * filename and line number can be extracted for diagnostic purposes + * @param {String} [message] + * An optional message to show if no object gets passed into the + * generated callback method. */ -function unexpectedCallbackAndFinish(error) { +function unexpectedCallbackAndFinish(message) { + var stack = new Error().stack.split("\n"); + stack.shift(); // Don't include this instantiation frame + /** * @param {object} aObj * The object fired back from the callback */ - return function(aObj) { - var where = error.fileName + ":" + error.lineNumber; + return function (aObj) { if (aObj && aObj.name && aObj.message) { - ok(false, "Unexpected callback/event from " + where + " with name = '" + - aObj.name + "', message = '" + aObj.message + "'"); + ok(false, "Unexpected callback for '" + aObj.name + "' with message = '" + + aObj.message + "' at " + JSON.stringify(stack)); } else { - ok(false, "Unexpected callback/event from " + where + " with " + aObj); + ok(false, "Unexpected callback with message = '" + message + + "' at: " + JSON.stringify(stack)); } SimpleTest.finish(); } } /** - * Generates a callback function suitable for putting int a success - * callback in circumstances where success is unexpected. The callback, - * if activated, will kill off the test gracefully. + * Generates a callback function fired only for unexpected events happening. + * + * @param {String} description + Description of the object for which the event has been fired + * @param {String} eventName + Name of the unexpected event */ +function unexpectedEventAndFinish(message, eventName) { + var stack = new Error().stack.split("\n"); + stack.shift(); // Don't include this instantiation frame -function unexpectedSuccessCallbackAndFinish(error, reason) { - return function() { - unexpectedCallbackAndFinish(error)(message); + return function () { + ok(false, "Unexpected event '" + eventName + "' fired with message = '" + + message + "' at: " + JSON.stringify(stack)); + SimpleTest.finish(); } } diff --git a/dom/media/tests/mochitest/mediaStreamPlayback.js b/dom/media/tests/mochitest/mediaStreamPlayback.js index 52778cf7976b..bd76ea9f557e 100644 --- a/dom/media/tests/mochitest/mediaStreamPlayback.js +++ b/dom/media/tests/mochitest/mediaStreamPlayback.js @@ -121,8 +121,7 @@ MediaStreamPlayback.prototype = { if (!timeUpdateFired) { self.mediaElement.removeEventListener('timeupdate', timeUpdateCallback, false); - ok(false, "timeUpdate event never fired"); - onError(); + onError("timeUpdate event never fired"); } }, TIMEOUT_LENGTH); }; @@ -141,8 +140,7 @@ MediaStreamPlayback.prototype = { if (!canPlayThroughFired) { self.mediaElement.removeEventListener('canplaythrough', canPlayThroughCallback, false); - ok(false, "canplaythrough event never fired"); - onError(); + onError("canplaythrough event never fired"); } }, TIMEOUT_LENGTH); }, @@ -237,8 +235,7 @@ LocalMediaStreamPlayback.prototype = Object.create(MediaStreamPlayback.prototype // If ended doesn't fire in enough time, then we fail the test setTimeout(function() { if (!endedFired) { - ok(false, "ended event never fired"); - onError(); + onError("ended event never fired"); } }, TIMEOUT_LENGTH); } diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index 78d17471812d..38f60862bf35 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -249,16 +249,19 @@ var commandsPeerConnection = [ [ 'PC_CHECK_INITIAL_SIGNALINGSTATE', function (test) { - is(test.pcLocal.signalingState,"stable", "Initial local signalingState is stable"); - is(test.pcRemote.signalingState,"stable", "Initial remote signalingState is stable"); + is(test.pcLocal.signalingState, "stable", + "Initial local signalingState is 'stable'"); + is(test.pcRemote.signalingState, "stable", + "Initial remote signalingState is 'stable'"); test.next(); } ], [ 'PC_LOCAL_CREATE_OFFER', function (test) { - test.pcLocal.createOffer(function () { - is(test.pcLocal.signalingState, "stable", "Local create offer does not change signaling state"); + test.createOffer(test.pcLocal, function () { + is(test.pcLocal.signalingState, "stable", + "Local create offer does not change signaling state"); test.next(); }); } @@ -266,24 +269,29 @@ var commandsPeerConnection = [ [ 'PC_LOCAL_SET_LOCAL_DESCRIPTION', function (test) { - test.expectStateChange(test.pcLocal, "have-local-offer", test); - test.pcLocal.setLocalDescription(test.pcLocal._last_offer, - test.checkStateInCallback(test.pcLocal, "have-local-offer", test)); + test.setLocalDescription(test.pcLocal, test.pcLocal._last_offer, function () { + is(test.pcLocal.signalingState, "have-local-offer", + "signalingState after local setLocalDescription is 'have-local-offer'"); + test.next(); + }); } ], [ 'PC_REMOTE_SET_REMOTE_DESCRIPTION', function (test) { - test.expectStateChange(test.pcRemote, "have-remote-offer", test); - test.pcRemote.setRemoteDescription(test.pcLocal._last_offer, - test.checkStateInCallback(test.pcRemote, "have-remote-offer", test)); + test.setRemoteDescription(test.pcRemote, test.pcLocal._last_offer, function () { + is(test.pcRemote.signalingState, "have-remote-offer", + "signalingState after remote setRemoteDescription is 'have-remote-offer'"); + test.next(); + }); } ], [ 'PC_REMOTE_CREATE_ANSWER', function (test) { - test.pcRemote.createAnswer(function () { - is(test.pcRemote.signalingState, "have-remote-offer", "Remote create offer does not change signaling state"); + test.createAnswer(test.pcRemote, function () { + is(test.pcRemote.signalingState, "have-remote-offer", + "Remote createAnswer does not change signaling state"); test.next(); }); } @@ -291,17 +299,21 @@ var commandsPeerConnection = [ [ 'PC_LOCAL_SET_REMOTE_DESCRIPTION', function (test) { - test.expectStateChange(test.pcLocal, "stable", test); - test.pcLocal.setRemoteDescription(test.pcRemote._last_answer, - test.checkStateInCallback(test.pcLocal, "stable", test)); + test.setRemoteDescription(test.pcLocal, test.pcRemote._last_answer, function () { + is(test.pcLocal.signalingState, "stable", + "signalingState after local setRemoteDescription is 'stable'"); + test.next(); + }); } ], [ 'PC_REMOTE_SET_LOCAL_DESCRIPTION', function (test) { - test.expectStateChange(test.pcRemote, "stable", test); - test.pcRemote.setLocalDescription(test.pcRemote._last_answer, - test.checkStateInCallback(test.pcRemote, "stable", test)); + test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, function () { + is(test.pcRemote.signalingState, "stable", + "signalingState after remote setLocalDescription is 'stable'"); + test.next(); + }); } ], [ @@ -356,6 +368,73 @@ PeerConnectionTest.prototype.next = function PCT_next() { this.chain.executeNext(); }; +/** + * Creates an answer for the specified peer connection instance + * and automatically handles the failure case. + * + * @param {PeerConnectionWrapper} peer + * The peer connection wrapper to run the command on + * @param {function} onSuccess + * Callback to execute if the offer was created successfully + */ +PeerConnectionTest.prototype.createAnswer = +function PCT_createAnswer(peer, onSuccess) { + peer.createAnswer(function (answer) { + onSuccess(answer); + }); +}; + +/** + * Creates an offer for the specified peer connection instance + * and automatically handles the failure case. + * + * @param {PeerConnectionWrapper} peer + * The peer connection wrapper to run the command on + * @param {function} onSuccess + * Callback to execute if the offer was created successfully + */ +PeerConnectionTest.prototype.createOffer = +function PCT_createOffer(peer, onSuccess) { + peer.createOffer(function (offer) { + onSuccess(offer); + }); +}; + +/** + * Sets the local description for the specified peer connection instance + * and automatically handles the failure case. + * + * @param {PeerConnectionWrapper} peer + The peer connection wrapper to run the command on + * @param {mozRTCSessionDescription} desc + * Session description for the local description request + * @param {function} onSuccess + * Callback to execute if the local description was set successfully + */ +PeerConnectionTest.prototype.setLocalDescription = +function PCT_setLocalDescription(peer, desc, onSuccess) { + var eventFired = false; + var stateChanged = false; + + function check_next_test() { + if (eventFired && stateChanged) { + onSuccess(); + } + } + + peer.onsignalingstatechange = function () { + info(peer + ": 'onsignalingstatechange' event registered for async check"); + + eventFired = true; + check_next_test(); + }; + + peer.setLocalDescription(desc, function () { + stateChanged = true; + check_next_test(); + }); +}; + /** * Sets the media constraints for both peer connection instances. * @@ -379,6 +458,41 @@ function PCT_setOfferConstraints(constraints) { this.pcLocal.offerConstraints = constraints; }; +/** + * Sets the remote description for the specified peer connection instance + * and automatically handles the failure case. + * + * @param {PeerConnectionWrapper} peer + The peer connection wrapper to run the command on + * @param {mozRTCSessionDescription} desc + * Session description for the remote description request + * @param {function} onSuccess + * Callback to execute if the local description was set successfully + */ +PeerConnectionTest.prototype.setRemoteDescription = +function PCT_setRemoteDescription(peer, desc, onSuccess) { + var eventFired = false; + var stateChanged = false; + + function check_next_test() { + if (eventFired && stateChanged) { + onSuccess(); + } + } + + peer.onsignalingstatechange = function () { + info(peer + ": 'onsignalingstatechange' event registered for async check"); + + eventFired = true; + check_next_test(); + }; + + peer.setRemoteDescription(desc, function () { + stateChanged = true; + check_next_test(); + }); +}; + /** * Start running the tests as assigned to the command chain. */ @@ -404,64 +518,6 @@ PeerConnectionTest.prototype.teardown = function PCT_teardown() { SimpleTest.finish(); }; -/** - * Sets up the "onsignalingstatechange" handler for the indicated peerconnection - * as a one-shot test. If the test.commandSuccess flag is set when the event - * happens, then the next test in the command chain is triggered. After - * running, this sets the event handler so that it will fail the test if - * it fires again before we expect it. This is intended to be used in - * conjunction with checkStateInCallback, below. - * - * @param {pcw} PeerConnectionWrapper - * The peer connection to expect a state change on - * @param {state} string - * The state that we expect to change to - * @param {test} PeerConnectionTest - * The test strucure currently in use. - */ -PeerConnectionTest.prototype.expectStateChange = -function PCT_expectStateChange(pcw, state, test) { - pcw.signalingChangeEvent = false; - pcw._pc.onsignalingstatechange = function() { - pcw._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error); - is(pcw._pc.signalingState, state, pcw.label + ": State is " + state + " in onsignalingstatechange"); - pcw.signalingChangeEvent = true; - if (pcw.commandSuccess) { - test.next(); - } else { - info("Waiting for success callback..."); - } - }; -} - -/** - * Returns a function, suitable for use as a success callback, that - * checks the signaling state of the PC; and, if the signalingstatechange - * event has already fired, moves on to the next test case. This is - * intended to be used in conjunction with expectStateChange, above. - * - * @param {pcw} PeerConnectionWrapper - * The peer connection to expect a state change on - * @param {state} string - * The state that we expect to change to - * @param {test} PeerConnectionTest - * The test strucure currently in use. - */ - -PeerConnectionTest.prototype.checkStateInCallback = -function PCT_checkStateInCallback(pcw, state, test) { - pcw.commandSuccess = false; - return function() { - pcw.commandSuccess = true; - is(pcw.signalingState, state, pcw.label + ": State is " + state + " in success callback"); - if (pcw.signalingChangeEvent) { - test.next(); - } else { - info("Waiting for signalingstatechange event..."); - } - }; -} - /** * This class handles acts as a wrapper around a PeerConnection instance. @@ -480,17 +536,36 @@ function PeerConnectionWrapper(label, configuration) { this.offerConstraints = {}; this.streams = [ ]; - info("Creating new PeerConnectionWrapper: " + this.label); + info("Creating new PeerConnectionWrapper: " + this); this._pc = new mozRTCPeerConnection(this.configuration); + /** + * Setup callback handlers + */ + + this.onsignalingstatechange = unexpectedEventAndFinish(this, 'onsignalingstatechange'); + + var self = this; this._pc.onaddstream = function (event) { // Bug 834835: Assume type is video until we get get{Audio,Video}Tracks. self.attachMedia(event.stream, 'video', 'remote'); }; - // Make sure no signaling state changes are fired until we expect them to - this._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error); + /** + * Callback for native peer connection 'onsignalingstatechange' events. If no + * custom handler has been specified via 'this.onsignalingstatechange', a + * failure will be raised if an event of this type is caught. + * + * @param {Object} aEvent + * Event data which includes the newly created data channel + */ + this._pc.onsignalingstatechange = function (aEvent) { + info(self + ": 'onsignalingstatechange' event fired"); + + self.onsignalingstatechange(); + self.onsignalingstatechange = unexpectedEventAndFinish(self, 'onsignalingstatechange'); + } } PeerConnectionWrapper.prototype = { @@ -593,7 +668,7 @@ PeerConnectionWrapper.prototype = { self.attachMedia(stream, type, 'local'); _getAllUserMedia(constraintsList, index + 1); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); } else { onSuccess(); } @@ -616,7 +691,7 @@ PeerConnectionWrapper.prototype = { info("Got offer: " + JSON.stringify(offer)); self._last_offer = offer; onSuccess(offer); - }, unexpectedCallbackAndFinish(new Error), this.offerConstraints); + }, unexpectedCallbackAndFinish(), this.offerConstraints); }, /** @@ -629,10 +704,10 @@ PeerConnectionWrapper.prototype = { var self = this; this._pc.createAnswer(function (answer) { - info('Got answer for ' + self.label + ': ' + JSON.stringify(answer)); + info(self + ": Got answer: " + JSON.stringify(answer)); self._last_answer = answer; onSuccess(answer); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }, /** @@ -646,9 +721,9 @@ PeerConnectionWrapper.prototype = { setLocalDescription : function PCW_setLocalDescription(desc, onSuccess) { var self = this; this._pc.setLocalDescription(desc, function () { - info("Successfully set the local description for " + self.label); + info(self + ": Successfully set the local description"); onSuccess(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }, /** @@ -663,9 +738,9 @@ PeerConnectionWrapper.prototype = { setLocalDescriptionAndFail : function PCW_setLocalDescriptionAndFail(desc, onFailure) { var self = this; this._pc.setLocalDescription(desc, - unexpectedSuccessCallbackAndFinish(new Error, "setLocalDescription should have failed."), + unexpectedCallbackAndFinish("setLocalDescription should have failed."), function (err) { - info("As expected, failed to set the local description for " + self.label); + info(self + ": As expected, failed to set the local description"); onFailure(err); }); }, @@ -681,9 +756,9 @@ PeerConnectionWrapper.prototype = { setRemoteDescription : function PCW_setRemoteDescription(desc, onSuccess) { var self = this; this._pc.setRemoteDescription(desc, function () { - info("Successfully set remote description for " + self.label); + info(self + ": Successfully set remote description"); onSuccess(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }, /** @@ -698,9 +773,9 @@ PeerConnectionWrapper.prototype = { setRemoteDescriptionAndFail : function PCW_setRemoteDescriptionAndFail(desc, onFailure) { var self = this; this._pc.setRemoteDescription(desc, - unexpectedSuccessCallbackAndFinish(new Error, "setRemoteDescription should have failed."), + unexpectedCallbackAndFinish("setRemoteDescription should have failed."), function (err) { - info("As expected, failed to set the remote description for " + self.label); + info(self + ": As expected, failed to set the remote description"); onFailure(err); }); }, @@ -717,9 +792,9 @@ PeerConnectionWrapper.prototype = { var self = this; this._pc.addIceCandidate(candidate, function () { - info("Successfully added an ICE candidate to " + self.label); + info(self + ": Successfully added an ICE candidate"); onSuccess(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }, /** @@ -735,9 +810,9 @@ PeerConnectionWrapper.prototype = { var self = this; this._pc.addIceCandidate(candidate, - unexpectedSuccessCallbackAndFinish(new Error, "addIceCandidate should have failed."), + unexpectedCallbackAndFinish("addIceCandidate should have failed."), function (err) { - info("As expected, failed to add an ICE candidate to " + self.label); + info(self + ": As expected, failed to add an ICE candidate"); onFailure(err); }) ; }, @@ -750,11 +825,11 @@ PeerConnectionWrapper.prototype = { */ checkMedia : function PCW_checkMedia(constraintsRemote) { is(this._pc.localStreams.length, this.constraints.length, - this.label + ' has ' + this.constraints.length + ' local streams'); + this + ' has ' + this.constraints.length + ' local streams'); // TODO: change this when multiple incoming streams are allowed. is(this._pc.remoteStreams.length, 1, - this.label + ' has ' + 1 + ' remote streams'); + this + ' has ' + 1 + ' remote streams'); }, /** @@ -765,9 +840,16 @@ PeerConnectionWrapper.prototype = { // we should not fail. try { this._pc.close(); - info(this.label + ": Closed connection."); + info(this + ": Closed connection."); } catch (e) { - info(this.label + ": Failure in closing connection - " + e.message); + info(this + ": Failure in closing connection - " + e.message); } + }, + + /** + * Returns the string representation of the object + */ + toString : function PCW_toString() { + return "PeerConnectionWrapper (" + this.label + ")"; } }; diff --git a/dom/media/tests/mochitest/test_dataChannel_noOffer.html b/dom/media/tests/mochitest/test_dataChannel_noOffer.html index 884dcf4d0e26..0bcb2650f485 100644 --- a/dom/media/tests/mochitest/test_dataChannel_noOffer.html +++ b/dom/media/tests/mochitest/test_dataChannel_noOffer.html @@ -24,7 +24,7 @@ "m=application is not contained in the SDP"); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error), options); + }, unexpectedCallbackAndFinish(), options); }, true); diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html b/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html index ad3e40a61edc..2293d9b2d27a 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicAudio.html @@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534 playback.playMedia(false, function () { aStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html b/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html index 5d633d81ea3b..057d7a153057 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicVideo.html @@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534 playback.playMedia(false, function () { aStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html b/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html index b240846ce208..729d3f30b7ac 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html +++ b/dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html @@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534 playback.playMedia(false, function () { aStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_gumWithinGum.html b/dom/media/tests/mochitest/test_getUserMedia_gumWithinGum.html index 2e2ece04c454..af6886085434 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_gumWithinGum.html +++ b/dom/media/tests/mochitest/test_getUserMedia_gumWithinGum.html @@ -42,13 +42,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 audioStream.stop(); videoStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html b/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html index 00bb99b1460f..05d8824fdde3 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html +++ b/dom/media/tests/mochitest/test_getUserMedia_playAudioTwice.html @@ -34,11 +34,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 audioStreamPlayback.playMedia(true, function() { audioStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html b/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html index d6952431ed9e..e3712c2fd7ab 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html +++ b/dom/media/tests/mochitest/test_getUserMedia_playVideoAudioTwice.html @@ -33,11 +33,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 streamPlayback.playMedia(true, function() { stream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html b/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html index 6eeb0ae02e5f..c332f8b779d7 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html +++ b/dom/media/tests/mochitest/test_getUserMedia_playVideoTwice.html @@ -34,11 +34,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 videoStreamPlayback.playMedia(true, function() { videoStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopAudioStream.html b/dom/media/tests/mochitest/test_getUserMedia_stopAudioStream.html index 17d7572b35ea..ba076b83e569 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopAudioStream.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopAudioStream.html @@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 var audioStreamPlayback = new LocalMediaStreamPlayback(testAudio, stream); audioStreamPlayback.playMediaWithStreamStop(false, SimpleTest.finish, - unexpectedCallbackAndFinish(new Error)); - }, unexpectedCallbackAndFinish(new Error)); + unexpectedCallbackAndFinish()); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopAudioStreamWithFollowupAudio.html b/dom/media/tests/mochitest/test_getUserMedia_stopAudioStreamWithFollowupAudio.html index 83661782e5cf..336ddc7bdb63 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopAudioStreamWithFollowupAudio.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopAudioStreamWithFollowupAudio.html @@ -37,13 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 streamPlayback.playMedia(false, function() { secondStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html b/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html index 7bd165487fbb..92d86862e384 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStream.html @@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream); streamPlayback.playMediaWithStreamStop(false, SimpleTest.finish, - unexpectedCallbackAndFinish(new Error)); - }, unexpectedCallbackAndFinish(new Error)); + unexpectedCallbackAndFinish()); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html b/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html index 639ed56b0337..68e8d491053f 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html @@ -37,13 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 streamPlayback.playMedia(false, function() { secondStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopVideoStream.html b/dom/media/tests/mochitest/test_getUserMedia_stopVideoStream.html index a712757b5c6f..779a75127832 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopVideoStream.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopVideoStream.html @@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 var videoStreamPlayback = new LocalMediaStreamPlayback(testVideo, stream); videoStreamPlayback.playMediaWithStreamStop(false, SimpleTest.finish, - unexpectedCallbackAndFinish(new Error)); - }, unexpectedCallbackAndFinish(new Error)); + unexpectedCallbackAndFinish()); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_getUserMedia_stopVideoStreamWithFollowupVideo.html b/dom/media/tests/mochitest/test_getUserMedia_stopVideoStreamWithFollowupVideo.html index 3929cc95df2e..3b8953fff019 100644 --- a/dom/media/tests/mochitest/test_getUserMedia_stopVideoStreamWithFollowupVideo.html +++ b/dom/media/tests/mochitest/test_getUserMedia_stopVideoStreamWithFollowupVideo.html @@ -38,13 +38,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109 streamPlayback.playMedia(false, function() { secondStream.stop(); SimpleTest.finish(); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); - }, unexpectedCallbackAndFinish(new Error)); + }, unexpectedCallbackAndFinish()); }); diff --git a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html index 435159246e77..6c0e0239d03c 100644 --- a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html +++ b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html @@ -22,16 +22,10 @@ } }; - function successCallback(message) { - return function () { - unexpectedCallbackAndFinish(new Error)(message); - } - }; - function testCreateAnswerError() { var pc = new mozRTCPeerConnection(); info ("Testing createAnswer error callback"); - pc.createAnswer(successCallback("createAnswer before offer should fail"), + pc.createAnswer(unexpectedCallbackAndFinish("createAnswer before offer should fail"), errorCallback(testSetLocalDescriptionError)); }; @@ -40,7 +34,7 @@ info ("Testing setLocalDescription error callback"); pc.setLocalDescription(new mozRTCSessionDescription({ sdp: "Picklechips!", type: "offer" }), - successCallback("setLocalDescription with nonsense SDP should fail"), + unexpectedCallbackAndFinish("setLocalDescription with nonsense SDP should fail"), errorCallback(testSetRemoteDescriptionError)); }; @@ -49,7 +43,7 @@ info ("Testing setRemoteDescription error callback"); pc.setRemoteDescription(new mozRTCSessionDescription({ sdp: "Who?", type: "offer" }), - successCallback("setRemoteDescription with nonsense SDP should fail"), + unexpectedCallbackAndFinish("setRemoteDescription with nonsense SDP should fail"), errorCallback(testAddIceCandidateError)); }; @@ -59,7 +53,7 @@ pc.addIceCandidate(new mozRTCIceCandidate({ candidate: "Pony Lords, jump!", sdpMid: "whee", sdpMLineIndex: 1 }), - successCallback("addIceCandidate with nonsense candidate should fail"), + unexpectedCallbackAndFinish("addIceCandidate with nonsense candidate should fail"), errorCallback(SimpleTest.finish)); }; diff --git a/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html b/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html index b4572d49bdbd..a6563567c2d9 100644 --- a/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html +++ b/dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html @@ -18,7 +18,7 @@ let oldOnError = window.onerror; window.onerror = function (errorMsg, url, lineNumber) { if (errorMsg.indexOf("Expected") == -1) { - getFail(new Error)(errorMsg); + getFail()(errorMsg); } error_count += 1; info("onerror " + error_count + ": " + errorMsg); @@ -36,7 +36,7 @@ // Test failure callbacks (limited to 1 for now) pc0 = new mozRTCPeerConnection(); - pc0.createOffer(getFail(new Error), function(err) { + pc0.createOffer(getFail(), function(err) { pc1 = new mozRTCPeerConnection(); pc2 = new mozRTCPeerConnection(); @@ -50,18 +50,18 @@ pc2.setLocalDescription(answer, function() { pc1.setRemoteDescription(answer, function() { throw new Error("Expected"); - }, getFail(new Error)); + }, getFail()); throw new Error("Expected"); - }, getFail(new Error)); + }, getFail()); throw new Error("Expected"); - }, getFail(new Error)); + }, getFail()); throw new Error("Expected"); - }, getFail(new Error)); + }, getFail()); throw new Error("Expected"); - }, getFail(new Error)); + }, getFail()); throw new Error("Expected"); - }, getFail(new Error)); - }, getFail(new Error)); + }, getFail()); + }, getFail()); throw new Error("Expected"); }); }); @@ -72,10 +72,10 @@ SimpleTest.finish(); } - function getFail(where) { + function getFail() { return function (err) { window.onerror = oldOnError; - unexpectedCallbackAndFinish(where)(err); + unexpectedCallbackAndFinish()(err); }; } From 02cc20a17e45477a542e2fad5caadc03d541c545 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 13 Jun 2013 11:47:09 -0700 Subject: [PATCH 063/615] Bug 882514: Don't try to enable Ion on functions with no script; r=h4writer --- js/src/ion/AsmJS.cpp | 8 +++++--- js/src/jit-test/tests/asm.js/testFFI.js | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 43f198fd04f3..56ddd4bc59fe 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -5231,9 +5231,11 @@ GenerateEntries(ModuleCompiler &m) } static inline bool -TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv) { - - JSScript *script = exitDatum->fun->nonLazyScript(); +TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv) +{ + JSScript *script = exitDatum->fun->maybeNonLazyScript(); + if (!script) + return true; // Test if the function is Ion compiled if (!script->hasIonScript()) diff --git a/js/src/jit-test/tests/asm.js/testFFI.js b/js/src/jit-test/tests/asm.js/testFFI.js index ad76c523697d..1b929c4a1ef7 100644 --- a/js/src/jit-test/tests/asm.js/testFFI.js +++ b/js/src/jit-test/tests/asm.js/testFFI.js @@ -19,7 +19,7 @@ function addN() { sum += arguments[i]; return sum; } -var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN }; +var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN, identity: x => x }; assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { incc() } return f'); assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; return (i + inc)|0 } return f'); @@ -90,3 +90,5 @@ var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function g assertThrowsValue(function() { f(0,2.4) }, 2.4+4); assertThrowsValue(function() { f(1,2.4) }, 2.4+8); assertThrowsValue(function() { f(8,2.4) }, 2.4+36); + +assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var identity=imp.identity; function g(x) { x=+x; return +identity(x) } return g'), null, imp)(13.37), 13.37); From e09fdfc7e4e52974e11deb8ad03800eb0be83693 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Thu, 13 Jun 2013 11:53:13 -0700 Subject: [PATCH 064/615] Bug 845668 Part 0: Remove nsFrameLoader::mChildHost r=jdm --- content/base/src/nsFrameLoader.cpp | 2 -- content/base/src/nsFrameLoader.h | 1 - 2 files changed, 3 deletions(-) diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index c63724cadd78..74968abeff73 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2049,8 +2049,6 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr browserDOMWin; rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin)); mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin); - - mChildHost = static_cast(mRemoteBrowser->Manager()); } return true; } diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 669631edf87f..64255ec03b07 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -434,7 +434,6 @@ private: bool mVisible : 1; // XXX leaking - nsCOMPtr mChildHost; RenderFrameParent* mCurrentRemoteFrame; TabParent* mRemoteBrowser; From a3d61db2546c2160a457a09015f402bd473d874c Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 13 Jun 2013 11:54:25 -0700 Subject: [PATCH 065/615] Bug 878501: Forbid variable declarations without var keyword in asm.js; r=luke --- js/src/ion/AsmJS.cpp | 8 ++++++-- js/src/jit-test/tests/asm.js/testBasic.js | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 56ddd4bc59fe..82a7c8c9ef2e 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -3085,8 +3085,12 @@ CheckModuleExports(ModuleCompiler &m, ParseNode *fn, ParseNode **stmtIter) { ParseNode *returnNode = SkipEmptyStatements(*stmtIter); - if (!returnNode || !returnNode->isKind(PNK_RETURN)) - return m.fail(fn, "asm.js module must end with a return export statement"); + if (!returnNode || !returnNode->isKind(PNK_RETURN)) { + if (returnNode && NextNode(returnNode) != NULL) + return m.fail(returnNode, "invalid asm.js statement"); + else + return m.fail(fn, "asm.js module must end with a return export statement"); + } ParseNode *returnExpr = UnaryKid(returnNode); diff --git a/js/src/jit-test/tests/asm.js/testBasic.js b/js/src/jit-test/tests/asm.js/testBasic.js index 7d6a5dd49a61..0daa2379fd93 100644 --- a/js/src/jit-test/tests/asm.js/testBasic.js +++ b/js/src/jit-test/tests/asm.js/testBasic.js @@ -23,6 +23,7 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f(x,y){x=x|0;y=y|0; return (x+y) assertAsmTypeFail('a', USE_ASM + 'function a(){} return a'); assertAsmTypeFail('a','b','c', USE_ASM + 'var c'); assertAsmTypeFail('a','b','c', USE_ASM + 'var c=0'); +assertAsmTypeFail(USE_ASM + 'c=0;return {}'); assertAsmTypeFail('x','x', USE_ASM + 'function a(){} return a'); assertAsmTypeFail('x','y','x', USE_ASM + 'function a(){} return a'); assertEq(asmLink(asmCompile('x', USE_ASM + 'function a(){} return a'))(), undefined); From 4bfd3df72c17d7d9ec2b9363ad79f35c180f4613 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 13 Jun 2013 15:19:50 -0400 Subject: [PATCH 066/615] Backed out 13 changesets (bug 880917) for Android and B2G test bustage on a CLOSED TREE. Backed out changeset 71c1ce2cb0a4 (bug 880917) Backed out changeset cd240e19560f (bug 880917) Backed out changeset 93509a0001b5 (bug 880917) Backed out changeset fdbba20e4647 (bug 880917) Backed out changeset d82060172367 (bug 880917) Backed out changeset 709f0b699489 (bug 880917) Backed out changeset 421bdbccfa7c (bug 880917) Backed out changeset 962c656c7452 (bug 880917) Backed out changeset 888a5690ccdf (bug 880917) Backed out changeset 57228f5fcd87 (bug 880917) Backed out changeset ce8c3e14c234 (bug 880917) Backed out changeset 08fe7b777450 (bug 880917) Backed out changeset 5192a9233d83 (bug 880917) --- content/base/src/nsFrameMessageManager.cpp | 6 +- content/xbl/src/nsXBLDocumentInfo.cpp | 4 +- content/xbl/src/nsXBLProtoImpl.cpp | 25 +++ .../document/src/nsXULPrototypeDocument.cpp | 4 +- dom/base/nsGlobalWindow.cpp | 6 +- dom/workers/RuntimeService.cpp | 4 + dom/workers/WorkerScope.cpp | 5 +- ipc/testshell/XPCShellEnvironment.cpp | 12 +- js/jsd/idl/jsdIDebuggerService.idl | 32 +++- js/jsd/jsd_xpc.cpp | 17 ++ js/src/gdb/gdb-tests.cpp | 5 +- js/src/jsapi-tests/moz.build | 1 + js/src/jsapi-tests/testVersion.cpp | 171 ++++++++++++++++++ js/src/jsapi-tests/tests.cpp | 4 +- js/src/jsapi-tests/tests.h | 1 + js/src/jsapi.cpp | 97 ++++++++-- js/src/jsapi.h | 26 +-- js/src/jscntxt.cpp | 4 + js/src/jscntxt.h | 53 +++++- js/src/jscntxtinlines.h | 31 +++- js/src/jscompartment.cpp | 3 +- js/src/jscompartment.h | 5 +- js/src/jsdbgapi.cpp | 6 + js/src/jsdbgapi.h | 3 + js/src/jsgc.cpp | 5 +- js/src/jsgc.h | 3 +- js/src/shell/js.cpp | 26 ++- js/src/tests/js1_8/regress/regress-384412.js | 13 ++ js/src/vm/Stack.cpp | 3 + js/xpconnect/idl/nsIXPConnect.idl | 15 +- js/xpconnect/loader/mozJSComponentLoader.cpp | 8 +- js/xpconnect/shell/xpcshell.cpp | 16 +- js/xpconnect/src/XPCComponents.cpp | 20 +- js/xpconnect/src/XPCJSContextStack.cpp | 4 +- js/xpconnect/src/XPCWrappedNative.cpp | 4 +- js/xpconnect/src/nsXPConnect.cpp | 9 +- js/xpconnect/src/xpcprivate.h | 4 +- .../tests/unit/bug596580_versioned.js | 3 + js/xpconnect/tests/unit/test_bug596580.js | 19 ++ js/xpconnect/tests/unit/xpcshell.ini | 1 + netwerk/base/src/ProxyAutoConfig.cpp | 6 +- netwerk/test/httpserver/httpd.js | 2 +- 42 files changed, 538 insertions(+), 148 deletions(-) create mode 100644 js/src/jsapi-tests/testVersion.cpp create mode 100644 js/xpconnect/tests/unit/bug596580_versioned.js create mode 100644 js/xpconnect/tests/unit/test_bug596580.js diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index b89240d60399..2dadfdb345e6 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1108,6 +1108,7 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope, nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal)); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS); + JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, ContentScriptErrorReporter); nsIXPConnect* xpc = nsContentUtils::XPConnect(); @@ -1116,12 +1117,9 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope, JS_SetContextPrivate(cx, aScope); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone) - .setVersion(JSVERSION_LATEST); nsresult rv = xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal, - flags, options, getter_AddRefs(mGlobal)); + flags, JS::SystemZone, getter_AddRefs(mGlobal)); NS_ENSURE_SUCCESS(rv, false); diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index 96f2ac162dc9..c74df251619b 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -284,11 +284,9 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment() // why - see bug 339647) JS_SetErrorReporter(cx, XBL_ProtoErrorReporter); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone); mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass, nsJSPrincipals::get(GetPrincipal()), - options); + JS::SystemZone); if (!mJSObject) return NS_OK; diff --git a/content/xbl/src/nsXBLProtoImpl.cpp b/content/xbl/src/nsXBLProtoImpl.cpp index db6eefebcc9f..9d97766c2f38 100644 --- a/content/xbl/src/nsXBLProtoImpl.cpp +++ b/content/xbl/src/nsXBLProtoImpl.cpp @@ -21,6 +21,27 @@ using namespace mozilla; +// Checks that the version is not modified in a given scope. +class AutoVersionChecker +{ + DebugOnly const cx; + DebugOnly versionBefore; + +public: + explicit AutoVersionChecker(JSContext *aCx) : cx(aCx) { +#ifdef DEBUG + versionBefore = JS_GetVersion(cx); +#endif + } + + ~AutoVersionChecker() { +#ifdef DEBUG + JSVersion versionAfter = JS_GetVersion(cx); + NS_ABORT_IF_FALSE(versionAfter == versionBefore, "version must not change"); +#endif + } +}; + nsresult nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, nsXBLBinding* aBinding) @@ -68,6 +89,7 @@ nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aPrototypeBinding, AutoPushJSContext cx(context->GetNativeContext()); JSAutoCompartment ac(cx, targetClassObject); + AutoVersionChecker avc(cx); // Walk our member list and install each one in turn. for (nsXBLProtoImplMember* curr = mMembers; @@ -207,6 +229,8 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding) MOZ_ASSERT(classObject); mClassObject = classObject; + AutoVersionChecker avc(cx); + // Now that we have a class object installed, we walk our member list and compile each of our // properties and methods in turn. for (nsXBLProtoImplMember* curr = mMembers; @@ -275,6 +299,7 @@ nsXBLProtoImpl::FindField(const nsString& aFieldName) const bool nsXBLProtoImpl::ResolveAllFields(JSContext *cx, JS::Handle obj) const { + AutoVersionChecker avc(cx); for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) { // Using OBJ_LOOKUP_PROPERTY is a pain, since what we have is a // PRUnichar* for the property name. Let's just use the public API and diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index ed2220b98bce..2a086cff7399 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -762,11 +762,9 @@ nsXULPDGlobalObject::EnsureScriptEnvironment() // will re-fetch the global and set it up in our language globals array. { AutoPushJSContext cx(ctxNew->GetNativeContext()); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone); JS::Rooted newGlob(cx, JS_NewGlobalObject(cx, &gSharedGlobalClass, - nsJSPrincipals::get(GetPrincipal()), options)); + nsJSPrincipals::get(GetPrincipal()), JS::SystemZone)); if (!newGlob) return NS_OK; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 72a2e7bc91a9..8b43d032ad0a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2120,10 +2120,10 @@ CreateNativeGlobalForInner(JSContext* aCx, if (aNewInner->GetOuterWindow()) { top = aNewInner->GetTop(); } - JS::CompartmentOptions options; + JS::ZoneSpecifier zoneSpec = JS::FreshZone; if (top) { if (top->GetGlobalJSObject()) { - options.zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject()); + zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject()); } } @@ -2139,7 +2139,7 @@ CreateNativeGlobalForInner(JSContext* aCx, nsRefPtr jsholder; nsresult rv = xpc->InitClassesWithNewWrappedGlobal( aCx, ToSupports(aNewInner), - aPrincipal, flags, options, getter_AddRefs(jsholder)); + aPrincipal, flags, zoneSpec, getter_AddRefs(jsholder)); NS_ENSURE_SUCCESS(rv, rv); MOZ_ASSERT(jsholder); diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index fb5ad18a7bde..89d0f72a1afd 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -829,6 +829,10 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate) JS_SetGCZeal(workerCx, settings.gcZeal, settings.gcZealFrequency); #endif + if (aWorkerPrivate->IsChromeWorker()) { + JS_SetVersion(workerCx, JSVERSION_LATEST); + } + return workerCx; } diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 00dc3d6b7a71..6a9bd62e26f3 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -967,12 +967,9 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx) WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx); JS_ASSERT(worker); - JS::CompartmentOptions options; - if (worker->IsChromeWorker()) - options.setVersion(JSVERSION_LATEST); JS::Rooted global(aCx, JS_NewGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(), - GetWorkerPrincipal(), options)); + GetWorkerPrincipal())); if (!global) { return NULL; } diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 40980f5010f6..e8000d8bdbb6 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -188,6 +188,7 @@ ContextCallback(JSContext *cx, if (contextOp == JSCONTEXT_NEW) { JS_SetErrorReporter(cx, ScriptErrorReporter); + JS_SetVersion(cx, JSVERSION_LATEST); } return JS_TRUE; } @@ -305,10 +306,10 @@ Version(JSContext *cx, JS::Value *vp) { JS::Value *argv = JS_ARGV(cx, vp); - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); if (argc > 0 && JSVAL_IS_INT(argv[0])) - JS_SetVersionForCompartment(js::GetContextCompartment(cx), - JSVersion(JSVAL_TO_INT(argv[0]))); + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(argv[0]))))); + else + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); return JS_TRUE; } @@ -782,14 +783,11 @@ XPCShellEnvironment::Init() return false; } - JS::CompartmentOptions options; - options.setZone(JS::SystemZone) - .setVersion(JSVERSION_LATEST); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), principal, 0, - options, + JS::SystemZone, getter_AddRefs(holder)); if (NS_FAILED(rv)) { NS_ERROR("InitClassesWithNewWrappedGlobal failed!"); diff --git a/js/jsd/idl/jsdIDebuggerService.idl b/js/jsd/idl/jsdIDebuggerService.idl index 618f342cae8e..6e47c1e42c96 100644 --- a/js/jsd/idl/jsdIDebuggerService.idl +++ b/js/jsd/idl/jsdIDebuggerService.idl @@ -45,7 +45,7 @@ interface jsdIActivationCallback; * Debugger service. It is not a good idea to have more than one active client * of the debugger service. */ -[scriptable, uuid(029b8f0a-aa84-47eb-a60f-1a4752b7ad06)] +[scriptable, uuid(9be5b327-6818-464d-9695-f33885fd8377)] interface jsdIDebuggerService : nsISupports { /** Internal use only. */ @@ -88,6 +88,29 @@ interface jsdIDebuggerService : nsISupports */ attribute jsdICallHook functionHook; + + /** + * VERSION_* values must be kept in sync with the JSVersion enumeration in + * jspubtd.h. + */ + + /** + * Possible values for jsdIScript::version and jsdIContext::version. + */ + const long VERSION_1_0 = 100; + const long VERSION_1_1 = 110; + const long VERSION_1_2 = 120; + const long VERSION_1_3 = 130; + const long VERSION_1_4 = 140; + const long VERSION_1_5 = 150; + const long VERSION_DEFAULT = 0; + const long VERSION_UNKNOWN = -1; + + /** + * These flags need to be kept in sync with the context flags defined in + * jsdebug.h + */ + /** * Link native frames in call stacks. */ @@ -699,6 +722,13 @@ interface jsdIContext : jsdIEphemeral */ attribute unsigned long options; + /** + * Last version set on this context. + * Scripts typically select this with the "language" attribute. + * See the VERSION_* consts on jsdIDebuggerService. + */ + attribute long version; + /** * Unique tag among all valid jsdIContext objects, useful as a hash key. */ diff --git a/js/jsd/jsd_xpc.cpp b/js/jsd/jsd_xpc.cpp index 9e32581c8f3d..189f00ddd8c9 100644 --- a/js/jsd/jsd_xpc.cpp +++ b/js/jsd/jsd_xpc.cpp @@ -1693,6 +1693,23 @@ jsdContext::GetTag(uint32_t *_rval) return NS_OK; } +NS_IMETHODIMP +jsdContext::GetVersion (int32_t *_rval) +{ + ASSERT_VALID_EPHEMERAL; + *_rval = static_cast(JS_GetVersion(mJSCx)); + return NS_OK; +} + +NS_IMETHODIMP +jsdContext::SetVersion (int32_t id) +{ + ASSERT_VALID_EPHEMERAL; + JSVersion ver = static_cast(id); + JS_SetVersion(mJSCx, ver); + return NS_OK; +} + NS_IMETHODIMP jsdContext::GetGlobalObject (jsdIValue **_rval) { diff --git a/js/src/gdb/gdb-tests.cpp b/js/src/gdb/gdb-tests.cpp index 8398859818c1..a5ce25cf364d 100644 --- a/js/src/gdb/gdb-tests.cpp +++ b/js/src/gdb/gdb-tests.cpp @@ -62,14 +62,13 @@ main (int argc, const char **argv) JS_SetNativeStackQuota(runtime, 5000000); JSContext *cx = checkPtr(JS_NewContext(runtime, 8192)); + JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, reportError); JSAutoRequest ar(cx); /* Create the global object. */ - JS::CompartmentOptions options; - options.setVersion(JSVERSION_LATEST); - RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL, options))); + RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL))); JS_SetGlobalObject(cx, global); JSAutoCompartment ac(cx, global); diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index 56f2681e207f..e2aa2ccf710c 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -64,6 +64,7 @@ CPP_SOURCES += [ 'testTrap.cpp', 'testTypedArrays.cpp', 'testUTF8.cpp', + 'testVersion.cpp', 'testXDR.cpp', 'tests.cpp', ] diff --git a/js/src/jsapi-tests/testVersion.cpp b/js/src/jsapi-tests/testVersion.cpp new file mode 100644 index 000000000000..ccbb7497321d --- /dev/null +++ b/js/src/jsapi-tests/testVersion.cpp @@ -0,0 +1,171 @@ +/* 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/. */ + +#include "tests.h" +#include "jsscript.h" +#include "jscntxt.h" + +#include "jscntxtinlines.h" +#include "jsobjinlines.h" + +using namespace js; + +struct VersionFixture; + +/* + * Fast-native callbacks for use from JS. + * They set their results on the current fixture instance. + */ + +static VersionFixture *callbackData = NULL; + +JSBool CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp); +JSBool OverrideVersion18(JSContext *cx, unsigned argc, jsval *vp); +JSBool CaptureVersion(JSContext *cx, unsigned argc, jsval *vp); +JSBool CheckOverride(JSContext *cx, unsigned argc, jsval *vp); +JSBool EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp); + +struct VersionFixture : public JSAPITest +{ + JSVersion captured; + + virtual bool init() { + if (!JSAPITest::init()) + return false; + JS_SetOptions(cx, JS_GetOptions(cx)); + callbackData = this; + captured = JSVERSION_UNKNOWN; + JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); + return JS_DefineFunction(cx, global, "callSetVersion17", CallSetVersion17, 0, 0) && + JS_DefineFunction(cx, global, "overrideVersion18", OverrideVersion18, 0, 0) && + JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) && + JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) && + JS_DefineFunction(cx, global, "evalScriptVersion16", + EvalScriptVersion16, 0, 0); + } + + JSScript *fakeScript(const char *contents, size_t length) { + JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); + return JS_CompileScript(cx, global, contents, length, "", 1); + } + + bool checkVersionIsOverridden() { + CHECK(cx->isVersionOverridden()); + return true; + } + + bool setVersion(JSVersion version) { + CHECK(JS_GetVersion(cx) != version); + JS_SetVersion(cx, version); + return true; + } + + bool evalVersion(const jschar *chars, size_t len, JSVersion version) { + CHECK(JS_GetVersion(cx) != version); + jsval rval; + JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx)); + CHECK(JS_EvaluateUCScriptForPrincipalsVersion( + cx, global, NULL, chars, len, "", 0, &rval, version)); + return true; + } +}; + +/* Callbacks to throw into JS-land. */ + +JSBool +CallSetVersion17(JSContext *cx, unsigned argc, jsval *vp) +{ + return callbackData->setVersion(JSVERSION_1_7); +} + +JSBool +OverrideVersion18(JSContext *cx, unsigned argc, jsval *vp) +{ + if (!callbackData->setVersion(JSVERSION_1_8)) + return false; + return callbackData->checkVersionIsOverridden(); +} + +JSBool +EvalScriptVersion16(JSContext *cx, unsigned argc, jsval *vp) +{ + JS_ASSERT(argc == 1); + jsval *argv = JS_ARGV(cx, vp); + JS_ASSERT(JSVAL_IS_STRING(argv[0])); + JSStableString *str = JSVAL_TO_STRING(argv[0])->ensureStable(cx); + JS_ASSERT(str); + return callbackData->evalVersion(str->chars().get(), str->length(), JSVERSION_1_6); +} + +JSBool +CaptureVersion(JSContext *cx, unsigned argc, jsval *vp) +{ + callbackData->captured = JS_GetVersion(cx); + return true; +} + +JSBool +CheckOverride(JSContext *cx, unsigned argc, jsval *vp) +{ + JS_ASSERT(argc == 1); + jsval *argv = JS_ARGV(cx, vp); + JS_ASSERT(JSVAL_IS_BOOLEAN(argv[0])); + bool shouldHaveOverride = !!JSVAL_TO_BOOLEAN(argv[0]); + return shouldHaveOverride == cx->isVersionOverridden(); +} + +/* + * When re-entering the virtual machine through a *Version API the version + * is no longer forced -- it continues with its natural push/pop oriented + * version progression. This is maintained by the |AutoVersionAPI| class in + * jsapi.cpp. + */ +BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride) +{ + EXEC("overrideVersion18(); evalScriptVersion16('checkOverride(false); captureVersion()');"); + CHECK_EQUAL(captured, JSVERSION_1_6); + + /* + * Override gets propagated to default version as non-override when you leave the VM's execute + * call. + */ + CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_1_8); + CHECK(!cx->isVersionOverridden()); + return true; +} +END_FIXTURE_TEST(VersionFixture, testVersion_EntryLosesOverride) + +/* + * EvalScriptVersion does not propagate overrides to its caller, it + * restores things exactly as they were before the call. This is as opposed to + * the normal (no Version suffix) API which propagates overrides + * to the caller. + */ +BEGIN_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride) +{ + CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5); + EXEC( + "checkOverride(false);" + "evalScriptVersion16('overrideVersion18();');" + "checkOverride(false);" + "captureVersion();" + ); + CHECK_EQUAL(captured, JSVERSION_ECMA_5); + return true; +} +END_FIXTURE_TEST(VersionFixture, testVersion_ReturnLosesOverride) + +BEGIN_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride) +{ + CHECK_EQUAL(JS_GetVersion(cx), JSVERSION_ECMA_5); + EXEC( + "checkOverride(false);" + "eval('overrideVersion18();');" + "checkOverride(true);" + "captureVersion();" + ); + CHECK_EQUAL(captured, JSVERSION_1_8); + return true; +} +END_FIXTURE_TEST(VersionFixture, testVersion_EvalPropagatesOverride) diff --git a/js/src/jsapi-tests/tests.cpp b/js/src/jsapi-tests/tests.cpp index 9267eb6b2cbc..30b89be2d3b8 100644 --- a/js/src/jsapi-tests/tests.cpp +++ b/js/src/jsapi-tests/tests.cpp @@ -51,9 +51,7 @@ bool JSAPITest::definePrint() JSObject * JSAPITest::createGlobal(JSPrincipals *principals) { /* Create the global object. */ - JS::CompartmentOptions options; - options.setVersion(JSVERSION_LATEST); - global = JS_NewGlobalObject(cx, getGlobalClass(), principals, options); + global = JS_NewGlobalObject(cx, getGlobalClass(), principals); if (!global) return NULL; JS_AddNamedObjectRoot(cx, &global, "test-global"); diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h index b2e3ed50b839..c3c7e4cb8265 100644 --- a/js/src/jsapi-tests/tests.h +++ b/js/src/jsapi-tests/tests.h @@ -299,6 +299,7 @@ class JSAPITest if (!cx) return NULL; JS_SetOptions(cx, JSOPTION_VAROBJFIX); + JS_SetVersion(cx, JSVERSION_LATEST); JS_SetErrorReporter(cx, &reportError); return cx; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 7ae077659c4f..36a7a07423b3 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -122,6 +122,47 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl return false; } + +/* + * This class is a version-establishing barrier at the head of a VM entry or + * re-entry. It ensures that: + * + * - |newVersion| is the starting (default) version used for the context. + * - The starting version state is not an override. + * - Overrides in the VM session are not propagated to the caller. + */ +class AutoVersionAPI +{ + JSContext * const cx; + JSVersion oldDefaultVersion; + bool oldHasVersionOverride; + JSVersion oldVersionOverride; + JSVersion newVersion; + + public: + AutoVersionAPI(JSContext *cx, JSVersion newVersion) + : cx(cx), + oldDefaultVersion(cx->getDefaultVersion()), + oldHasVersionOverride(cx->isVersionOverridden()), + oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN) + { + this->newVersion = newVersion; + cx->clearVersionOverride(); + cx->setDefaultVersion(newVersion); + } + + ~AutoVersionAPI() { + cx->setDefaultVersion(oldDefaultVersion); + if (oldHasVersionOverride) + cx->overrideVersion(oldVersionOverride); + else + cx->clearVersionOverride(); + } + + /* The version that this scoped-entity establishes. */ + JSVersion version() const { return newVersion; } +}; + #ifdef HAVE_VA_LIST_AS_ARRAY #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap)) #else @@ -694,7 +735,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) numCompartments(0), localeCallbacks(NULL), defaultLocale(NULL), - defaultVersion_(JSVERSION_DEFAULT), #ifdef JS_THREADSAFE ownerThread_(NULL), #endif @@ -901,8 +941,7 @@ JSRuntime::init(uint32_t maxbytes) if (!atomsZone) return false; - JS::CompartmentOptions options; - ScopedJSDeletePtr atomsCompartment(new_(atomsZone.get(), options)); + ScopedJSDeletePtr atomsCompartment(new_(atomsZone.get())); if (!atomsCompartment || !atomsCompartment->init(NULL)) return false; @@ -1300,10 +1339,21 @@ JS_GetVersion(JSContext *cx) return VersionNumber(cx->findVersion()); } -JS_PUBLIC_API(void) -JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version) +JS_PUBLIC_API(JSVersion) +JS_SetVersion(JSContext *cx, JSVersion newVersion) { - compartment->options().setVersion(version); + JS_ASSERT(VersionIsKnown(newVersion)); + JS_ASSERT(!VersionHasFlags(newVersion)); + JSVersion newVersionNumber = newVersion; + + JSVersion oldVersion = cx->findVersion(); + JSVersion oldVersionNumber = VersionNumber(oldVersion); + if (oldVersionNumber == newVersionNumber) + return oldVersionNumber; /* No override actually occurs! */ + + VersionCopyFlags(&newVersion, oldVersion); + cx->maybeOverrideVersion(newVersion); + return oldVersionNumber; } static struct v2smap { @@ -3377,8 +3427,7 @@ class AutoHoldZone }; JS_PUBLIC_API(JSObject *) -JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, - const JS::CompartmentOptions &options) +JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS::ZoneSpecifier zoneSpec) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -3387,18 +3436,18 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JSRuntime *rt = cx->runtime(); Zone *zone; - if (options.zoneSpec == JS::SystemZone) + if (zoneSpec == JS::SystemZone) zone = rt->systemZone; - else if (options.zoneSpec == JS::FreshZone) + else if (zoneSpec == JS::FreshZone) zone = NULL; else - zone = ((JSObject *)options.zoneSpec)->zone(); + zone = ((JSObject *)zoneSpec)->zone(); - JSCompartment *compartment = NewCompartment(cx, zone, principals, options); + JSCompartment *compartment = NewCompartment(cx, zone, principals); if (!compartment) return NULL; - if (options.zoneSpec == JS::SystemZone) { + if (zoneSpec == JS::SystemZone) { rt->systemZone = compartment->zone(); rt->systemZone->isSystem = true; } @@ -5263,6 +5312,13 @@ JSScript * JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, const jschar *chars, size_t length) { + Maybe mava; + if (options.versionSet) { + mava.construct(cx, options.version); + // AutoVersionAPI propagates some compilation flags through. + options.version = mava.ref().version(); + } + JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -5415,6 +5471,13 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options, const char *name, unsigned nargs, const char **argnames, const jschar *chars, size_t length) { + Maybe mava; + if (options.versionSet) { + mava.construct(cx, options.version); + // AutoVersionAPI propagates some compilation flags through. + options.version = mava.ref().version(); + } + JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); @@ -5589,6 +5652,7 @@ JS_ExecuteScriptVersion(JSContext *cx, JSObject *objArg, JSScript *script, jsval JSVersion version) { RootedObject obj(cx, objArg); + AutoVersionAPI ava(cx, version); return JS_ExecuteScript(cx, obj, script, rval); } @@ -5598,6 +5662,13 @@ extern JS_PUBLIC_API(bool) JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options, const jschar *chars, size_t length, jsval *rval) { + Maybe mava; + if (options.versionSet) { + mava.construct(cx, options.version); + // AutoVersionAPI propagates some compilation flags through. + options.version = mava.ref().version(); + } + JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment); AssertHeapIsIdle(cx); CHECK_REQUEST(cx); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 835d6e590985..fb8790bdef0f 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1890,14 +1890,8 @@ JS_ContextIterator(JSRuntime *rt, JSContext **iterp); extern JS_PUBLIC_API(JSVersion) JS_GetVersion(JSContext *cx); -// Mutate the version on the compartment. This is generally discouraged, but -// necessary to support the version mutation in the js and xpc shell command -// set. -// -// It would be nice to put this in jsfriendapi, but the linkage requirements -// of the shells make that impossible. -JS_PUBLIC_API(void) -JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version); +extern JS_PUBLIC_API(JSVersion) +JS_SetVersion(JSContext *cx, JSVersion version); extern JS_PUBLIC_API(const char *) JS_VersionToString(JSVersion version); @@ -3150,25 +3144,11 @@ SameZoneAs(JSObject *obj) return ZoneSpecifier(obj); } -struct JS_PUBLIC_API(CompartmentOptions) { - ZoneSpecifier zoneSpec; - bool hasVersion; - JSVersion version; - - explicit CompartmentOptions() : zoneSpec(JS::FreshZone) - , hasVersion(false) - , version(JSVERSION_UNKNOWN) - {} - - CompartmentOptions &setZone(ZoneSpecifier spec) { zoneSpec = spec; return *this; } - CompartmentOptions &setVersion(JSVersion version_) { hasVersion = true; version = version_; return *this; } -}; - } /* namespace JS */ extern JS_PUBLIC_API(JSObject *) JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, - const JS::CompartmentOptions &options = JS::CompartmentOptions()); + JS::ZoneSpecifier zoneSpec = JS::FreshZone); extern JS_PUBLIC_API(JSObject *) JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 0eb73c280cbe..982f0222ca4a 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -280,6 +280,8 @@ js::NewContext(JSRuntime *rt, size_t stackChunkSize) if (!cx) return NULL; + JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); + if (!cx->cycleDetectorSet.init()) { js_delete(cx); return NULL; @@ -1118,6 +1120,8 @@ js_HandleExecutionInterrupt(JSContext *cx) JSContext::JSContext(JSRuntime *rt) : ContextFriendFields(rt), + defaultVersion(JSVERSION_DEFAULT), + hasVersionOverride(false), throwing(false), exception(UndefinedValue()), options_(0), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 5b129c902a95..1a01b6cda11d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -719,9 +719,6 @@ struct JSRuntime : public JS::shadow::Runtime, /* Default locale for Internationalization API */ char *defaultLocale; - /* Default JSVersion. */ - JSVersion defaultVersion_; - /* See comment for JS_AbortIfWrongThread in jsapi.h. */ #ifdef JS_THREADSAFE public: @@ -831,9 +828,6 @@ struct JSRuntime : public JS::shadow::Runtime, /* Gets current default locale. String remains owned by context. */ const char *getDefaultLocale(); - JSVersion defaultVersion() { return defaultVersion_; } - void setDefaultVersion(JSVersion v) { defaultVersion_ = v; } - /* Base address of the native stack for the current thread. */ uintptr_t nativeStackBase; @@ -1539,6 +1533,11 @@ struct JSContext : js::ContextFriendFields, js::PerThreadData &mainThread() { return runtime()->mainThread; } private: + /* See JSContext::findVersion. */ + JSVersion defaultVersion; /* script compilation version */ + JSVersion versionOverride; /* supercedes defaultVersion when valid */ + bool hasVersionOverride; + /* Exception state -- the exception member is a GC root by definition. */ bool throwing; /* is there a pending exception? */ js::Value exception; /* most-recently-thrown exception */ @@ -1647,11 +1646,51 @@ struct JSContext : js::ContextFriendFields, inline js::RegExpStatics *regExpStatics(); public: + /* + * The default script compilation version can be set iff there is no code running. + * This typically occurs via the JSAPI right after a context is constructed. + */ + inline bool canSetDefaultVersion() const; + + /* Force a version for future script compilation. */ + inline void overrideVersion(JSVersion newVersion); + + /* Set the default script compilation version. */ + void setDefaultVersion(JSVersion version) { + defaultVersion = version; + } + + void clearVersionOverride() { hasVersionOverride = false; } + JSVersion getDefaultVersion() const { return defaultVersion; } + bool isVersionOverridden() const { return hasVersionOverride; } + + JSVersion getVersionOverride() const { + JS_ASSERT(isVersionOverridden()); + return versionOverride; + } + + /* + * Set the default version if possible; otherwise, force the version. + * Return whether an override occurred. + */ + inline bool maybeOverrideVersion(JSVersion newVersion); + + /* + * If there is no code on the stack, turn the override version into the + * default version. + */ + void maybeMigrateVersionOverride() { + JS_ASSERT(stack.empty()); + if (JS_UNLIKELY(isVersionOverridden())) { + defaultVersion = versionOverride; + clearVersionOverride(); + } + } /* * Return: + * - The override version, if there is an override version. * - The newest scripted frame's version, if there is such a frame. - * - The version from the compartment. * - The default version. * * Note: if this ever shows up in a profile, just add caching! diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 84d83bf0b09a..103de78ad18a 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -468,13 +468,38 @@ CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, un inline JSVersion JSContext::findVersion() const { + if (hasVersionOverride) + return versionOverride; + if (JSScript *script = stack.currentScript(NULL, js::ContextStack::ALLOW_CROSS_COMPARTMENT)) return script->getVersion(); - if (compartment() && compartment()->options().hasVersion) - return compartment()->options().version; + return defaultVersion; +} - return runtime()->defaultVersion(); +inline bool +JSContext::canSetDefaultVersion() const +{ + return !stack.hasfp() && !hasVersionOverride; +} + +inline void +JSContext::overrideVersion(JSVersion newVersion) +{ + JS_ASSERT(!canSetDefaultVersion()); + versionOverride = newVersion; + hasVersionOverride = true; +} + +inline bool +JSContext::maybeOverrideVersion(JSVersion newVersion) +{ + if (canSetDefaultVersion()) { + setDefaultVersion(newVersion); + return false; + } + overrideVersion(newVersion); + return true; } inline js::LifoAlloc & diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 6192f8ba4c9f..48b8459d7890 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -30,9 +30,8 @@ using namespace js::gc; using mozilla::DebugOnly; -JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions()) +JSCompartment::JSCompartment(Zone *zone) : zone_(zone), - options_(options), rt(zone->rt), principals(NULL), isSystem(false), diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 7283f07a5176..b103b313b101 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -123,7 +123,6 @@ class DebugScopes; struct JSCompartment { JS::Zone *zone_; - JS::CompartmentOptions options_; JSRuntime *rt; JSPrincipals *principals; @@ -145,8 +144,6 @@ struct JSCompartment JS::Zone *zone() { return zone_; } const JS::Zone *zone() const { return zone_; } - JS::CompartmentOptions &options() { return options_; } - const JS::CompartmentOptions &options() const { return options_; } /* * Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the @@ -262,7 +259,7 @@ struct JSCompartment unsigned debugModeBits; // see debugMode() below public: - JSCompartment(JS::Zone *zone, const JS::CompartmentOptions &options); + JSCompartment(JS::Zone *zone); ~JSCompartment(); bool init(JSContext *cx); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 1b5880aeeed8..1132434c829b 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -827,6 +827,12 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure) /************************************************************************/ +JS_FRIEND_API(void) +js_RevertVersion(JSContext *cx) +{ + cx->clearVersionOverride(); +} + JS_PUBLIC_API(const JSDebugHooks *) JS_GetGlobalDebugHooks(JSRuntime *rt) { diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index f5f0245a2d72..a9db47d1cd06 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -427,6 +427,9 @@ JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure); /************************************************************************/ +extern JS_FRIEND_API(void) +js_RevertVersion(JSContext *cx); + extern JS_PUBLIC_API(const JSDebugHooks *) JS_GetGlobalDebugHooks(JSRuntime *rt); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index d978a77fb3ee..bb92eedcd3df 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -4699,8 +4699,7 @@ AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt) } JSCompartment * -js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals, - const JS::CompartmentOptions &options) +js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals) { JSRuntime *rt = cx->runtime(); JS_AbortIfWrongThread(rt); @@ -4722,7 +4721,7 @@ js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals, zone->isSystem = principals && principals == trusted; } - ScopedJSDeletePtr compartment(cx->new_(zone, options)); + ScopedJSDeletePtr compartment(cx->new_(zone)); if (!compartment || !compartment->init(cx)) return NULL; diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 64fe87ce1cf3..4eec8386f750 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1201,8 +1201,7 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str); namespace js { JSCompartment * -NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals, - const JS::CompartmentOptions &options); +NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals); namespace gc { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index a67a6281b7ee..55a0a1b3c89c 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -625,10 +625,9 @@ static JSBool Version(JSContext *cx, unsigned argc, jsval *vp) { CallArgs args = CallArgsFromVp(argc, vp); - JSVersion origVersion = JS_GetVersion(cx); if (args.length() == 0 || JSVAL_IS_VOID(args[0])) { /* Get version. */ - args.rval().setInt32(origVersion); + args.rval().setInt32(JS_GetVersion(cx)); } else { /* Set version. */ int32_t v = -1; @@ -643,12 +642,20 @@ Version(JSContext *cx, unsigned argc, jsval *vp) JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "version"); return false; } - JS_SetVersionForCompartment(js::GetContextCompartment(cx), JSVersion(v)); - args.rval().setInt32(origVersion); + args.rval().setInt32(JS_SetVersion(cx, JSVersion(v))); } return true; } +static JSBool +RevertVersion(JSContext *cx, unsigned argc, jsval *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + js_RevertVersion(cx); + args.rval().setUndefined(); + return true; +} + static JSScript * GetTopScript(JSContext *cx) { @@ -3558,6 +3565,10 @@ static JSFunctionSpecWithHelp shell_functions[] = { "version([number])", " Get or force a script compilation version number."), + JS_FN_HELP("revertVersion", RevertVersion, 0, 0, +"revertVersion()", +" Revert previously set version number."), + JS_FN_HELP("options", Options, 0, 0, "options([option ...])", " Get or toggle JavaScript options."), @@ -4763,6 +4774,7 @@ NewContext(JSRuntime *rt) JS_SetContextPrivate(cx, data); JS_SetErrorReporter(cx, my_ErrorReporter); + JS_SetVersion(cx, JSVERSION_LATEST); SetContextOptions(cx); if (enableTypeInference) JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE); @@ -4787,10 +4799,8 @@ DestroyContext(JSContext *cx, bool withGC) static JSObject * NewGlobalObject(JSContext *cx, JSObject *sameZoneAs) { - JS::CompartmentOptions options; - options.setZone(sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone) - .setVersion(JSVERSION_LATEST); - RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, options)); + JS::ZoneSpecifier spec = sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone; + RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, spec)); if (!glob) return NULL; diff --git a/js/src/tests/js1_8/regress/regress-384412.js b/js/src/tests/js1_8/regress/regress-384412.js index 92dd9bc59ab5..fa9bed6da397 100644 --- a/js/src/tests/js1_8/regress/regress-384412.js +++ b/js/src/tests/js1_8/regress/regress-384412.js @@ -137,6 +137,19 @@ function test() expect(["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"] + "", ([a + b for (a in 'abc') for (b in '123')]) + ""); +/* + * Version switching + */ + if (typeof version == 'function') + { + var v = version(150); + f = new Function("return version(arguments[0])"); + revertVersion(); + expect(150, f()); + expect(150, eval("f()")); + expect(0, eval("f(0); f()")); + revertVersion(); + } print("End of Tests"); /* diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 12ee830d83b5..fc5c77484ee2 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -833,6 +833,9 @@ ContextStack::popSegment() { space().seg_ = seg_->prevInMemory(); seg_ = seg_->prevInContext(); + + if (!seg_) + cx_->maybeMigrateVersionOverride(); } bool diff --git a/js/xpconnect/idl/nsIXPConnect.idl b/js/xpconnect/idl/nsIXPConnect.idl index c6c73bb73361..d805109cdcc1 100644 --- a/js/xpconnect/idl/nsIXPConnect.idl +++ b/js/xpconnect/idl/nsIXPConnect.idl @@ -44,7 +44,7 @@ class nsWrapperCache; [ref] native nsCCTraversalCallbackRef(nsCycleCollectionTraversalCallback); [ptr] native nsAXPCNativeCallContextPtr(nsAXPCNativeCallContext); [ptr] native nsWrapperCachePtr(nsWrapperCache); -[ref] native JSCompartmentOptions(JS::CompartmentOptions); + native ZoneSpecifier(uintptr_t); [ref] native JSCallArgsRef(const JS::CallArgs); native JSHandleId(JS::HandleId); @@ -291,7 +291,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } %} -[uuid(bd61342d-8a88-4f23-8d2d-1782fff02d26)] +[uuid(2950bc62-ba03-4465-9685-a0eec9e188c2)] interface nsIXPConnect : nsISupports { %{ C++ @@ -318,15 +318,14 @@ interface nsIXPConnect : nsISupports * compartment. Can be null if not on the main thread. * @param aFlags one of the flags below specifying what options this * global object wants. - * @param aOptions JSAPI-specific options for the new compartment. */ nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal( - in JSContextPtr aJSContext, - in nsISupports aCOMObj, - in nsIPrincipal aPrincipal, - in uint32_t aFlags, - in JSCompartmentOptions aOptions); + in JSContextPtr aJSContext, + in nsISupports aCOMObj, + in nsIPrincipal aPrincipal, + in uint32_t aFlags, + in ZoneSpecifier aZoneSpec); const uint32_t INIT_JS_STANDARD_CLASSES = 1 << 0; // Free bit here! diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 36040843005e..9f84e278bf27 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -460,6 +460,9 @@ mozJSComponentLoader::ReallyInit() if (!mContext) return NS_ERROR_OUT_OF_MEMORY; + // Always use the latest js version + JS_SetVersion(mContext, JSVERSION_LATEST); + nsCOMPtr secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); if (!secman) @@ -723,14 +726,11 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx, rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); NS_ENSURE_SUCCESS(rv, nullptr); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone) - .setVersion(JSVERSION_LATEST); rv = xpc->InitClassesWithNewWrappedGlobal(aCx, static_cast(backstagePass), mSystemPrincipal, 0, - options, + JS::SystemZone, getter_AddRefs(holder)); NS_ENSURE_SUCCESS(rv, nullptr); diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 1d4832b57557..3986b49b0a93 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -489,11 +489,10 @@ Load(JSContext *cx, unsigned argc, jsval *vp) static JSBool Version(JSContext *cx, unsigned argc, jsval *vp) { - JSVersion origVersion = JS_GetVersion(cx); - JS_SET_RVAL(cx, vp, INT_TO_JSVAL(origVersion)); if (argc > 0 && JSVAL_IS_INT(JS_ARGV(cx, vp)[0])) - JS_SetVersionForCompartment(js::GetContextCompartment(cx), - JSVersion(JSVAL_TO_INT(JS_ARGV(cx, vp)[0]))); + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(JS_ARGV(cx, vp)[0]))))); + else + JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx))); return true; } @@ -1237,8 +1236,7 @@ ProcessArgs(JSContext *cx, JS::Handle obj, char **argv, int argc, XPC if (++i == argc) { return usage(); } - JS_SetVersionForCompartment(js::GetContextCompartment(cx), - JSVersion(atoi(argv[i]))); + JS_SetVersion(cx, JSVersion(atoi(argv[i]))); break; case 'W': reportWarnings = false; @@ -1402,6 +1400,7 @@ ContextCallback(JSContext *cx, unsigned contextOp) if (contextOp == JSCONTEXT_NEW) { JS_SetErrorReporter(cx, my_ErrorReporter); + JS_SetVersion(cx, JSVERSION_LATEST); } return true; } @@ -1635,15 +1634,12 @@ main(int argc, char **argv, char **envp) return 1; } - JS::CompartmentOptions options; - options.setZone(JS::SystemZone) - .setVersion(JSVERSION_LATEST); nsCOMPtr holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast(backstagePass), systemprincipal, 0, - options, + JS::SystemZone, getter_AddRefs(holder)); if (NS_FAILED(rv)) return 1; diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index fe6c6d7295c0..c9c4b2b7525b 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3279,12 +3279,10 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo MOZ_ASSERT(principal); } - JS::CompartmentOptions compartmentOptions; - compartmentOptions.setZone(options.sameZoneAs + JS::ZoneSpecifier zoneSpec = options.sameZoneAs ? JS::SameZoneAs(js::UncheckedUnwrap(options.sameZoneAs)) - : JS::SystemZone); - RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass, - principal, compartmentOptions)); + : JS::SystemZone; + RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass, principal, zoneSpec)); if (!sandbox) return NS_ERROR_FAILURE; @@ -3822,13 +3820,6 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString& source, return NS_ERROR_INVALID_ARG; jsVersion = JS_StringToVersion(bytes.ptr()); - // Explicitly check for "latest", which we support for sandboxes but - // isn't in the set of web-exposed version strings. - if (jsVersion == JSVERSION_UNKNOWN && - !strcmp(bytes.ptr(), "latest")) - { - jsVersion = JSVERSION_LATEST; - } if (jsVersion == JSVERSION_UNKNOWN) return NS_ERROR_INVALID_ARG; } @@ -3913,11 +3904,12 @@ xpc_EvalInSandbox(JSContext *cx, HandleObject sandboxArg, const nsAString& sourc pusher.Push(sandcx); JSAutoCompartment ac(sandcx, sandbox); + if (jsVersion != JSVERSION_DEFAULT) + JS_SetVersion(sandcx, jsVersion); + JS::CompileOptions options(sandcx); options.setPrincipals(nsJSPrincipals::get(prin)) .setFileAndLine(filename, lineNo); - if (jsVersion != JSVERSION_DEFAULT) - options.setVersion(jsVersion); JS::RootedObject rootedSandbox(sandcx, sandbox); ok = JS::Evaluate(sandcx, rootedSandbox, options, PromiseFlatString(source).get(), source.Length(), diff --git a/js/xpconnect/src/XPCJSContextStack.cpp b/js/xpconnect/src/XPCJSContextStack.cpp index 7547cb6c7961..142cf4ff539f 100644 --- a/js/xpconnect/src/XPCJSContextStack.cpp +++ b/js/xpconnect/src/XPCJSContextStack.cpp @@ -167,9 +167,7 @@ XPCJSContextStack::GetSafeJSContext() JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone); - glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options); + glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, JS::SystemZone); if (glob) { // Make sure the context is associated with a proper compartment diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 0152cc465761..cf62f09bec81 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -285,7 +285,7 @@ FinishCreate(XPCWrappedNativeScope* Scope, nsresult XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper, nsIPrincipal *principal, bool initStandardClasses, - JS::CompartmentOptions& aOptions, + ZoneSpecifier zoneSpec, XPCWrappedNative **wrappedGlobal) { AutoJSContext cx; @@ -315,7 +315,7 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper, MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL); // Create the global. - RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, aOptions)); + RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, zoneSpec)); if (!global) return NS_ERROR_FAILURE; XPCWrappedNativeScope *scope = GetCompartmentPrivate(global)->scope; diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 51675194b0a3..ecbf68b9185c 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -981,7 +981,7 @@ namespace xpc { JSObject* CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, - JS::CompartmentOptions& aOptions) + JS::ZoneSpecifier zoneSpec) { // Make sure that Type Inference is enabled for everything non-chrome. // Sandboxes and compilation scopes are exceptions. See bug 744034. @@ -991,7 +991,7 @@ CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, MOZ_ASSERT(principal); RootedObject global(cx, - JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), aOptions)); + JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), zoneSpec)); if (!global) return nullptr; JSAutoCompartment ac(cx, global); @@ -1027,7 +1027,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsISupports *aCOMObj, nsIPrincipal * aPrincipal, uint32_t aFlags, - JS::CompartmentOptions& aOptions, + JS::ZoneSpecifier zoneSpec, nsIXPConnectJSObjectHolder **_retval) { NS_ASSERTION(aJSContext, "bad param"); @@ -1046,7 +1046,8 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext, nsresult rv = XPCWrappedNative::WrapNewGlobal(helper, aPrincipal, aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES, - aOptions, getter_AddRefs(wrappedGlobal)); + zoneSpec, + getter_AddRefs(wrappedGlobal)); NS_ENSURE_SUCCESS(rv, rv); // Grab a copy of the global and enter its compartment. diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index c742c029c2cc..0354be0b7840 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2471,7 +2471,7 @@ public: static nsresult WrapNewGlobal(xpcObjectHelper &nativeHelper, nsIPrincipal *principal, bool initStandardClasses, - JS::CompartmentOptions& aOptions, + JS::ZoneSpecifier zoneSpec, XPCWrappedNative **wrappedGlobal); static nsresult @@ -3796,7 +3796,7 @@ struct SandboxOptions { JSObject * CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, - JS::CompartmentOptions& aOptions); + JS::ZoneSpecifier zoneSpec); } // Helper for creating a sandbox object to use for evaluating diff --git a/js/xpconnect/tests/unit/bug596580_versioned.js b/js/xpconnect/tests/unit/bug596580_versioned.js new file mode 100644 index 000000000000..cb44db7ce030 --- /dev/null +++ b/js/xpconnect/tests/unit/bug596580_versioned.js @@ -0,0 +1,3 @@ +/* Some constructs that require a high default version number. */ +let x = 12; +function simpleGen() { yield 12; } diff --git a/js/xpconnect/tests/unit/test_bug596580.js b/js/xpconnect/tests/unit/test_bug596580.js new file mode 100644 index 000000000000..706f0b838835 --- /dev/null +++ b/js/xpconnect/tests/unit/test_bug596580.js @@ -0,0 +1,19 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +function run_test() { + var file = do_get_file("bug596580_versioned.js"); + var ios = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + var uri = ios.newFileURI(file); + var scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader); + scriptLoader.loadSubScript(uri.spec); + version(150) + try { + scriptLoader.loadSubScript(uri.spec); + throw new Error("Subscript should fail to load."); + } catch (e if e instanceof SyntaxError) { + // Okay. + } +} diff --git a/js/xpconnect/tests/unit/xpcshell.ini b/js/xpconnect/tests/unit/xpcshell.ini index 852a08d29a35..da728b10a280 100644 --- a/js/xpconnect/tests/unit/xpcshell.ini +++ b/js/xpconnect/tests/unit/xpcshell.ini @@ -5,6 +5,7 @@ tail = [test_bogus_files.js] [test_bug408412.js] [test_bug451678.js] +[test_bug596580.js] [test_bug604362.js] [test_bug641378.js] [test_bug677864.js] diff --git a/netwerk/base/src/ProxyAutoConfig.cpp b/netwerk/base/src/ProxyAutoConfig.cpp index a70754d98bea..e88e9c3e9701 100644 --- a/netwerk/base/src/ProxyAutoConfig.cpp +++ b/netwerk/base/src/ProxyAutoConfig.cpp @@ -536,15 +536,13 @@ private: JSAutoRequest ar(mContext); - JS::CompartmentOptions options; - options.setZone(JS::SystemZone) - .setVersion(JSVERSION_LATEST); - mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options); + mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, JS::SystemZone); NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY); JS_SetGlobalObject(mContext, mGlobal); JS_InitStandardClasses(mContext, mGlobal); + JS_SetVersion(mContext, JSVERSION_LATEST); JS_SetErrorReporter(mContext, PACErrorReporter); if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions)) diff --git a/netwerk/test/httpserver/httpd.js b/netwerk/test/httpserver/httpd.js index fc9bbeb11f00..cbf95287e7a0 100644 --- a/netwerk/test/httpserver/httpd.js +++ b/netwerk/test/httpserver/httpd.js @@ -2727,7 +2727,7 @@ ServerHandler.prototype = // getting the line number where we evaluate the SJS file. Don't // separate these two lines! var line = new Error().lineNumber; - Cu.evalInSandbox(sis.read(file.fileSize), s, "latest"); + Cu.evalInSandbox(sis.read(file.fileSize), s); } catch (e) { From b24eb16a34974b72386430894a358a6ee878e021 Mon Sep 17 00:00:00 2001 From: Thomas Prip Vestergaard Date: Thu, 13 Jun 2013 15:41:55 -0400 Subject: [PATCH 067/615] Bug 718258 - Remove duplicate code. r=bsmedberg --- toolkit/components/build/nsToolkitCompsCID.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h index c7d06cf9b65e..0f6cea5ae4c5 100644 --- a/toolkit/components/build/nsToolkitCompsCID.h +++ b/toolkit/components/build/nsToolkitCompsCID.h @@ -21,9 +21,6 @@ #define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \ "@mozilla.org/autocomplete/controller;1" -#define NS_AUTOCOMPLETECONTROLLER_CONTRACTID \ - "@mozilla.org/autocomplete/controller;1" - #define NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID \ "@mozilla.org/autocomplete/simple-result;1" From d21228aea69d521ca1cd98e39f7a62b7d880ac16 Mon Sep 17 00:00:00 2001 From: Max Li Date: Thu, 13 Jun 2013 15:42:45 -0400 Subject: [PATCH 068/615] Bug 803021 - Doorhanger notifications do not retain accessibility focus. r=mleibovic --- mobile/android/base/DoorHangerPopup.java | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/mobile/android/base/DoorHangerPopup.java b/mobile/android/base/DoorHangerPopup.java index 9d88ce25242a..1a8b265eba99 100644 --- a/mobile/android/base/DoorHangerPopup.java +++ b/mobile/android/base/DoorHangerPopup.java @@ -12,6 +12,7 @@ import org.json.JSONArray; import org.json.JSONObject; import android.graphics.drawable.BitmapDrawable; +import android.os.Build; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; @@ -272,21 +273,30 @@ public class DoorHangerPopup extends PopupWindow if (mAnchor != null) mAnchor.getLocationInWindow(anchorLocation); + // Make the popup focusable for accessibility. This gets done here + // so the node can be accessibility focused, but on pre-ICS devices this + // causes crashes, so it is done after the popup is shown. + if (Build.VERSION.SDK_INT >= 14) { + setFocusable(true); + } + // If there's no anchor or the anchor is out of the window bounds, // just show the popup at the top of the gecko app view. if (mAnchor == null || anchorLocation[1] < 0) { showAtLocation(mActivity.getView(), Gravity.TOP, 0, 0); - return; + } else { + // On tablets, we need to position the popup so that the center of the arrow points to the + // center of the anchor view. On phones the popup stretches across the entire screen, so the + // arrow position is determined by its left margin. + int offset = HardwareUtils.isTablet() ? mAnchor.getWidth()/2 - mArrowWidth/2 - + ((RelativeLayout.LayoutParams) mArrow.getLayoutParams()).leftMargin : 0; + showAsDropDown(mAnchor, offset, -mYOffset); } - // On tablets, we need to position the popup so that the center of the arrow points to the - // center of the anchor view. On phones the popup stretches across the entire screen, so the - // arrow position is determined by its left margin. - int offset = HardwareUtils.isTablet() ? mAnchor.getWidth()/2 - mArrowWidth/2 - - ((RelativeLayout.LayoutParams) mArrow.getLayoutParams()).leftMargin : 0; - showAsDropDown(mAnchor, offset, -mYOffset); - // Make the popup focusable for keyboard accessibility. - setFocusable(true); + if (Build.VERSION.SDK_INT < 14) { + // Make the popup focusable for keyboard accessibility. + setFocusable(true); + } } private void showDividers() { From b8f2911fa0f558251b7029b30947efd75e74c964 Mon Sep 17 00:00:00 2001 From: Kevin Everets Date: Thu, 6 Jun 2013 14:14:31 -0400 Subject: [PATCH 069/615] Bug 880371 - Add debian bootstrapping for mach. r=gps Nearly the same as Ubuntu bootstrap, but uses the build dependencies from Debian's "iceweasel" package instead. --- python/mozboot/bin/bootstrap.py | 1 + python/mozboot/mozboot/bootstrap.py | 3 +++ python/mozboot/mozboot/debian.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 python/mozboot/mozboot/debian.py diff --git a/python/mozboot/bin/bootstrap.py b/python/mozboot/bin/bootstrap.py index 23e2586939ca..55cb033667c1 100755 --- a/python/mozboot/bin/bootstrap.py +++ b/python/mozboot/bin/bootstrap.py @@ -35,6 +35,7 @@ REPOSITORY_PATHS = [ 'mozboot/base.py', 'mozboot/bootstrap.py', 'mozboot/centos.py', + 'mozboot/debian.py', 'mozboot/fedora.py', 'mozboot/gentoo.py', 'mozboot/mint.py', diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py index bc2aca089645..293aa678e372 100644 --- a/python/mozboot/mozboot/bootstrap.py +++ b/python/mozboot/mozboot/bootstrap.py @@ -9,6 +9,7 @@ import platform import sys from mozboot.centos import CentOSBootstrapper +from mozboot.debian import DebianBootstrapper from mozboot.fedora import FedoraBootstrapper from mozboot.gentoo import GentooBootstrapper from mozboot.mint import MintBootstrapper @@ -41,6 +42,8 @@ class Bootstrapper(object): if distro == 'CentOS': cls = CentOSBootstrapper + elif distro in ('Debian', 'debian'): + cls = DebianBootstrapper elif distro == 'Fedora': cls = FedoraBootstrapper elif distro == 'Gentoo Base System': diff --git a/python/mozboot/mozboot/debian.py b/python/mozboot/mozboot/debian.py new file mode 100644 index 000000000000..0ad808768426 --- /dev/null +++ b/python/mozboot/mozboot/debian.py @@ -0,0 +1,29 @@ +# 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/. + +import os + +from mozboot.base import BaseBootstrapper + +class DebianBootstrapper(BaseBootstrapper): + def __init__(self, version, dist_id): + BaseBootstrapper.__init__(self) + + self.version = version + self.dist_id = dist_id + + def install_system_packages(self): + self.run_as_root(['apt-get', 'build-dep', 'iceweasel']) + + self.apt_install( + 'autoconf2.13', + 'libasound2-dev', + 'libcurl4-openssl-dev', + 'libiw-dev', + 'libnotify-dev', + 'libxt-dev', + 'mercurial', + 'mesa-common-dev', + 'uuid', + 'yasm') From 5bab2ff09599acab52a58a6a8c2e5a63e69a5cde Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Fri, 14 Jun 2013 08:19:39 +1200 Subject: [PATCH 070/615] Bug 874855. Add some more security to attaching compositors to compositables. r=nical --- gfx/layers/composite/CompositableHost.h | 1 + gfx/layers/composite/TiledContentHost.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index 65861fca47d4..3db0af3f55f3 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -186,6 +186,7 @@ public: virtual void Attach(Layer* aLayer, Compositor* aCompositor) { + MOZ_ASSERT(aCompositor, "Compositor is required"); SetCompositor(aCompositor); SetLayer(aLayer); } diff --git a/gfx/layers/composite/TiledContentHost.cpp b/gfx/layers/composite/TiledContentHost.cpp index 811596289117..b6afb29ed0c0 100644 --- a/gfx/layers/composite/TiledContentHost.cpp +++ b/gfx/layers/composite/TiledContentHost.cpp @@ -224,6 +224,10 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer, nsIntRect aVisibleRect, gfx::Matrix4x4 aTransform) { + if (!mCompositor) { + NS_WARNING("Can't render tiled content host - no compositor"); + return; + } float resolution = aLayerBuffer.GetResolution(); gfxSize layerScale(1, 1); // We assume that the current frame resolution is the one used in our primary From cc24bdbea3e5015fb56790d3b3029e05cfa2ef51 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Thu, 25 Apr 2013 13:56:43 -0400 Subject: [PATCH 071/615] Bug 844852 - Run GTest on make check. r=ted --- testing/gtest/Makefile.in | 1 + testing/gtest/mozilla/GTestRunner.cpp | 29 ++++++ testing/gtest/rungtests.py | 129 ++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 testing/gtest/rungtests.py diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in index e332f819606f..f6c6d5e5da8c 100644 --- a/testing/gtest/Makefile.in +++ b/testing/gtest/Makefile.in @@ -45,6 +45,7 @@ check gtest:: ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) $(MAKE) -C $(DEPTH)/browser/app repackage endif + $(PYTHON) $(topsrcdir)/testing/gtest/rungtests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) endif endif diff --git a/testing/gtest/mozilla/GTestRunner.cpp b/testing/gtest/mozilla/GTestRunner.cpp index 863c4242058d..f9375ceca2dd 100644 --- a/testing/gtest/mozilla/GTestRunner.cpp +++ b/testing/gtest/mozilla/GTestRunner.cpp @@ -7,6 +7,10 @@ #include "gtest/gtest.h" #include "mozilla/Attributes.h" #include "mozilla/NullPtr.h" +#ifdef MOZ_CRASHREPORTER +#include "nsICrashReporter.h" +#endif +#include "testing/TestHarness.h" #include "prenv.h" using ::testing::EmptyTestEventListener; @@ -78,6 +82,31 @@ int RunGTestFunc() PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort"); + ScopedXPCOM xpcom("GTestScopedXPCOM"); + +#ifdef MOZ_CRASHREPORTER + nsCOMPtr crashreporter; + char *crashreporterStr = PR_GetEnv("MOZ_CRASHREPORTER"); + if (crashreporterStr && !strcmp(crashreporterStr, "1")) { + //TODO: move this to an even-more-common location to use in all + // C++ unittests + crashreporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1"); + if (crashreporter) { + std::cerr << "Setting up crash reporting" << std::endl; + + nsCOMPtr dirsvc = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); + nsCOMPtr cwd; + nsresult rv = dirsvc->Get(NS_OS_CURRENT_WORKING_DIR, + NS_GET_IID(nsIFile), + getter_AddRefs(cwd)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + crashreporter->SetEnabled(true); + crashreporter->SetMinidumpPath(cwd); + } + } +#endif + return RUN_ALL_TESTS(); } diff --git a/testing/gtest/rungtests.py b/testing/gtest/rungtests.py new file mode 100644 index 000000000000..803a87be90c0 --- /dev/null +++ b/testing/gtest/rungtests.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# 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/. + +from __future__ import with_statement +import sys, os, tempfile, shutil +from optparse import OptionParser +import mozprocess, mozinfo, mozlog, mozcrash +from contextlib import contextmanager + +log = mozlog.getLogger('gtests') + +class GTests(object): + # Time (seconds) to wait for test process to complete + TEST_PROC_TIMEOUT = 1200 + # Time (seconds) in which process will be killed if it produces no output. + TEST_PROC_NO_OUTPUT_TIMEOUT = 300 + + def run_gtest(self, prog, xre_path, symbols_path=None): + """ + Run a single C++ unit test program. + + Arguments: + * prog: The path to the test program to run. + * env: The environment to use for running the program. + * symbols_path: A path to a directory containing Breakpad-formatted + symbol files for producing stack traces on crash. + + Return True if the program exits with a zero status, False otherwise. + """ + self.xre_path = xre_path + env = self.build_environment() + basename = os.path.basename(prog) + log.info("Running test %s", basename) + proc = mozprocess.ProcessHandler([prog, "-unittest"], + cwd=os.getcwd(), + env=env) + #TODO: After bug 811320 is fixed, don't let .run() kill the process, + # instead use a timeout in .wait() and then kill to get a stack. + proc.run(timeout=GTests.TEST_PROC_TIMEOUT, + outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) + proc.wait() + if proc.timedOut: + log.testFail("%s | timed out after %d seconds", + basename, GTests.TEST_PROC_TIMEOUT) + return False + if mozcrash.check_for_crashes(os.getcwd(), symbols_path, + test_name=basename): + log.testFail("%s | test crashed", basename) + return False + result = proc.proc.returncode == 0 + if not result: + log.testFail("%s | test failed with return code %d", + basename, proc.proc.returncode) + return result + + def build_core_environment(self, env = {}): + """ + Add environment variables likely to be used across all platforms, including remote systems. + """ + env["MOZILLA_FIVE_HOME"] = self.xre_path + env["MOZ_XRE_DIR"] = self.xre_path + env["XPCOM_DEBUG_BREAK"] = "stack-and-abort" + env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" + env["MOZ_CRASHREPORTER"] = "1" + env["MOZ_RUN_GTEST"] = "1" + # Normally we run with GTest default output, override this to use the TBPL test format. + env["MOZ_TBPL_PARSER"] = "1" + return env + + def build_environment(self): + """ + Create and return a dictionary of all the appropriate env variables and values. + On a remote system, we overload this to set different values and are missing things like os.environ and PATH. + """ + if not os.path.isdir(self.xre_path): + raise Exception("xre_path does not exist: %s", self.xre_path) + env = dict(os.environ) + env = self.build_core_environment(env) + pathvar = "" + if mozinfo.os == "linux": + pathvar = "LD_LIBRARY_PATH" + elif mozinfo.os == "mac": + pathvar = "DYLD_LIBRARY_PATH" + elif mozinfo.os == "win": + pathvar = "PATH" + if pathvar: + if pathvar in env: + env[pathvar] = "%s%s%s" % (self.xre_path, os.pathsep, env[pathvar]) + else: + env[pathvar] = self.xre_path + return env + +class gtestOptions(OptionParser): + def __init__(self): + OptionParser.__init__(self) + self.add_option("--xre-path", + action = "store", type = "string", dest = "xre_path", + default = None, + help = "absolute path to directory containing XRE (probably xulrunner)") + self.add_option("--symbols-path", + action = "store", type = "string", dest = "symbols_path", + default = None, + help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols") + +def main(): + parser = gtestOptions() + options, args = parser.parse_args() + if not args: + print >>sys.stderr, """Usage: %s """ % sys.argv[0] + sys.exit(1) + if not options.xre_path: + print >>sys.stderr, """Error: --xre-path is required""" + sys.exit(1) + prog = os.path.abspath(args[0]) + options.xre_path = os.path.abspath(options.xre_path) + tester = GTests() + try: + result = tester.run_gtest(prog, options.xre_path, options.symbols_path) + except Exception, e: + log.error(str(e)) + result = False + sys.exit(0 if result else 1) + +if __name__ == '__main__': + main() + From e9fa241008f439f7c0db0d019ddbdc3d8913aed5 Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Wed, 12 Jun 2013 15:19:54 -0400 Subject: [PATCH 072/615] Bug 882173 - Define MOZ_USE_PTHREADS if we're using pthreads. r=gps --- configure.in | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/configure.in b/configure.in index 3eb3de2d1ab6..f60c913a13de 100644 --- a/configure.in +++ b/configure.in @@ -83,7 +83,7 @@ AC_PROG_AWK dnl Initialize the Pthread test variables early so they can be dnl overridden by each platform. dnl ======================================================== -USE_PTHREADS= +MOZ_USE_PTHREADS= _PTHREAD_LDFLAGS="" dnl Do not allow a separate objdir build if a srcdir build exists. @@ -3156,17 +3156,17 @@ dnl = Start by checking whether the system support pthreads dnl ======================================================== case "$target_os" in darwin*) - USE_PTHREADS=1 + MOZ_USE_PTHREADS=1 ;; *) MOZ_CHECK_PTHREADS(pthreads, - USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads", + MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads", MOZ_CHECK_PTHREADS(pthread, - USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread", + MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread", MOZ_CHECK_PTHREADS(c_r, - USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r", + MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r", MOZ_CHECK_PTHREADS(c, - USE_PTHREADS=1 + MOZ_USE_PTHREADS=1 ) ) ) @@ -3179,17 +3179,17 @@ dnl Check the command line for --with-pthreads dnl ======================================================== MOZ_ARG_WITH_BOOL(pthreads, [ --with-pthreads Force use of system pthread library with NSPR ], -[ if test "$USE_PTHREADS"x = x; then +[ if test "$MOZ_USE_PTHREADS"x = x; then AC_MSG_ERROR([ --with-pthreads specified for a system without pthread support ]); fi], - USE_PTHREADS= + MOZ_USE_PTHREADS= _PTHREAD_LDFLAGS= ) dnl ======================================================== dnl Do the platform specific pthread hackery dnl ======================================================== -if test "$USE_PTHREADS"x != x +if test "$MOZ_USE_PTHREADS"x != x then dnl dnl See if -pthread is supported. @@ -3275,6 +3275,7 @@ then ;; esac LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}" + AC_SUBST(MOZ_USE_PTHREADS) fi From 3e25d39d17ee3d8226ee40a892d5445b95e3ea8a Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Wed, 12 Jun 2013 16:05:39 -0400 Subject: [PATCH 073/615] Bug 882173 - Build pixman with TLS support. r=jrmuizel --- gfx/cairo/libpixman/src/Makefile.in | 8 ++++++- gfx/cairo/libpixman/src/pixman-compiler.h | 4 +++- gfx/cairo/pixman-xp-dll-workaround | 27 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 gfx/cairo/pixman-xp-dll-workaround diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 181a60bbddd4..edb2418c1560 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -17,7 +17,13 @@ ifeq ($(OS_TARGET),Android) MODULE_OPTIMIZE_FLAGS = -O2 endif -DEFINES += -DPIXMAN_NO_TLS +ifdef MOZ_USE_PTHREADS +DEFINES += -DHAVE_PTHREAD_SETSPECIFIC +endif + +ifdef _MSC_VER +DEFINES += -DPIXMAN_USE_XP_DLL_TLS_WORKAROUND +endif # Build MMX code either with VC or with gcc-on-x86 ifdef _MSC_VER diff --git a/gfx/cairo/libpixman/src/pixman-compiler.h b/gfx/cairo/libpixman/src/pixman-compiler.h index 0bf0c14138a7..31e359fbcd2b 100644 --- a/gfx/cairo/libpixman/src/pixman-compiler.h +++ b/gfx/cairo/libpixman/src/pixman-compiler.h @@ -119,10 +119,12 @@ # define PIXMAN_GET_THREAD_LOCAL(name) \ (&name) -#elif defined(__MINGW32__) +#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND) # define _NO_W32_PSEUDO_MODIFIERS # include +#undef IN +#undef OUT # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ static volatile int tls_ ## name ## _initialized = 0; \ diff --git a/gfx/cairo/pixman-xp-dll-workaround b/gfx/cairo/pixman-xp-dll-workaround new file mode 100644 index 000000000000..e5d1fcbf8248 --- /dev/null +++ b/gfx/cairo/pixman-xp-dll-workaround @@ -0,0 +1,27 @@ +diff --git a/gfx/cairo/libpixman/src/pixman-compiler.h b/gfx/cairo/libpixman/src/pixman-compiler.h +--- a/gfx/cairo/libpixman/src/pixman-compiler.h ++++ b/gfx/cairo/libpixman/src/pixman-compiler.h +@@ -114,20 +114,22 @@ + + #elif defined(TLS) + + # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ + static TLS type name + # define PIXMAN_GET_THREAD_LOCAL(name) \ + (&name) + +-#elif defined(__MINGW32__) ++#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND) + + # define _NO_W32_PSEUDO_MODIFIERS + # include ++#undef IN ++#undef OUT + + # define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \ + static volatile int tls_ ## name ## _initialized = 0; \ + static void *tls_ ## name ## _mutex = NULL; \ + static unsigned tls_ ## name ## _index; \ + \ + static type * \ + tls_ ## name ## _alloc (void) \ From 4b82c566a45cf0aeadda1b362adea7500a567d58 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 12 Jun 2013 16:29:09 -0700 Subject: [PATCH 074/615] Bug 881882 - rm JS_ASMJS (r=sstangl) --HG-- extra : rebase_source : 9b848e6206b471fef6e57432697d6c28b68e80c2 --- js/src/ion/AsmJS.cpp | 12 ------------ js/src/ion/AsmJS.h | 10 +++------- js/src/ion/AsmJSLink.cpp | 4 ---- js/src/ion/AsmJSSignalHandlers.cpp | 21 +++++++-------------- js/src/ion/EffectiveAddressAnalysis.cpp | 4 ---- js/src/ion/IonMacroAssembler.cpp | 2 -- js/src/ion/IonMacroAssembler.h | 2 -- js/src/jsdbgapi.cpp | 4 ++-- 8 files changed, 12 insertions(+), 47 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 82a7c8c9ef2e..ddbee04c707e 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -29,8 +29,6 @@ using namespace js::ion; # include "jitprofiling.h" #endif -#ifdef JS_ASMJS - /*****************************************************************************/ // ParseNode utilities @@ -6062,8 +6060,6 @@ CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtrcompartment()->debugMode()) return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger"); -#ifdef JS_ASMJS if (!EnsureAsmJSSignalHandlersInstalled(cx->runtime())) return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform missing signal handler support"); @@ -6124,9 +6119,6 @@ js::CompileAsmJS(JSContext *cx, TokenStream &ts, ParseNode *fn, const CompileOpt SetAsmJSModuleObject(moduleFun, moduleObj); return Warn(cx, JSMSG_USE_ASM_TYPE_OK); -#else - return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform not supported (yet)"); -#endif } JSBool @@ -6134,13 +6126,9 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); -#ifdef JS_ASMJS bool available = JSC::MacroAssembler().supportsFloatingPoint() && !cx->compartment()->debugMode() && cx->hasOption(JSOPTION_ASMJS); -#else - bool available = false; -#endif args.rval().set(BooleanValue(available)); return true; diff --git a/js/src/ion/AsmJS.h b/js/src/ion/AsmJS.h index fbcdb82d9676..c0147c7be93a 100644 --- a/js/src/ion/AsmJS.h +++ b/js/src/ion/AsmJS.h @@ -12,10 +12,6 @@ # include #endif -#if defined(JS_ION) -# define JS_ASMJS -#endif - namespace js { class ScriptSource; @@ -158,11 +154,11 @@ struct AsmJSParallelTask // Returns true if the given native is the one that is used to implement asm.js // module functions. -#ifdef JS_ASMJS -bool +#ifdef JS_ION +extern bool IsAsmJSModuleNative(js::Native native); #else -static inline bool +inline bool IsAsmJSModuleNative(js::Native native) { return false; diff --git a/js/src/ion/AsmJSLink.cpp b/js/src/ion/AsmJSLink.cpp index 74d267c23c19..e8fb35277e4d 100644 --- a/js/src/ion/AsmJSLink.cpp +++ b/js/src/ion/AsmJSLink.cpp @@ -23,8 +23,6 @@ using namespace js; using namespace js::ion; using namespace mozilla; -#ifdef JS_ASMJS - static bool LinkFail(JSContext *cx, const char *str) { @@ -529,5 +527,3 @@ js::IsAsmJSModuleNative(js::Native native) { return native == LinkAsmJS; } - -#endif // defined(JS_ASMJS) diff --git a/js/src/ion/AsmJSSignalHandlers.cpp b/js/src/ion/AsmJSSignalHandlers.cpp index 25d50f097d74..6536507bcaa0 100644 --- a/js/src/ion/AsmJSSignalHandlers.cpp +++ b/js/src/ion/AsmJSSignalHandlers.cpp @@ -16,8 +16,6 @@ using namespace js; using namespace js::ion; using namespace mozilla; -#ifdef JS_ASMJS - #if defined(XP_WIN) # define XMM_sig(p,i) ((p)->Xmm##i) # define EIP_sig(p) ((p)->Eip) @@ -935,26 +933,24 @@ AsmJSFaultHandler(int signum, siginfo_t *info, void *context) } } # endif -#endif // JS_ASMJS bool EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt) { -#if defined(JS_ASMJS) -# if defined(XP_MACOSX) +#if defined(XP_MACOSX) // On OSX, each JSRuntime gets its own handler. return rt->asmJSMachExceptionHandler.installed() || rt->asmJSMachExceptionHandler.install(rt); -# else +#else // Assume Windows or Unix. For these platforms, there is a single, // process-wide signal handler installed. Take care to only install it once. InstallSignalHandlersMutex::Lock lock; if (lock.handlersInstalled()) return true; -# if defined(XP_WIN) +# if defined(XP_WIN) if (!AddVectoredExceptionHandler(/* FirstHandler = */true, AsmJSExceptionHandler)) return false; -# else // assume Unix +# else // assume Unix struct sigaction sigAction; sigAction.sa_sigaction = &AsmJSFaultHandler; sigemptyset(&sigAction.sa_mask); @@ -963,10 +959,9 @@ EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt) return false; if (sigaction(SIGBUS, &sigAction, &sPrevBusHandler)) return false; -# endif +# endif lock.setHandlersInstalled(); -# endif #endif return true; } @@ -984,7 +979,6 @@ EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt) void js::TriggerOperationCallbackForAsmJSCode(JSRuntime *rt) { -#if defined(JS_ASMJS) JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock()); AsmJSActivation *activation = rt->mainThread.asmJSActivationStackFromAnyThread(); @@ -993,14 +987,13 @@ js::TriggerOperationCallbackForAsmJSCode(JSRuntime *rt) const AsmJSModule &module = activation->module(); -# if defined(XP_WIN) +#if defined(XP_WIN) DWORD oldProtect; if (!VirtualProtect(module.functionCode(), module.functionBytes(), PAGE_NOACCESS, &oldProtect)) MOZ_CRASH(); -# else // assume Unix +#else // assume Unix if (mprotect(module.functionCode(), module.functionBytes(), PROT_NONE)) MOZ_CRASH(); -# endif #endif } diff --git a/js/src/ion/EffectiveAddressAnalysis.cpp b/js/src/ion/EffectiveAddressAnalysis.cpp index e936a6ebfe8d..45b83de2d68a 100644 --- a/js/src/ion/EffectiveAddressAnalysis.cpp +++ b/js/src/ion/EffectiveAddressAnalysis.cpp @@ -9,7 +9,6 @@ using namespace js; using namespace ion; -#ifdef JS_ASMJS static void AnalyzeLsh(MBasicBlock *block, MLsh *lsh) { @@ -87,7 +86,6 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh) last->replaceAllUsesWith(eaddr); block->insertAfter(last, eaddr); } -#endif // This analysis converts patterns of the form: // truncate(x + (y << {0,1,2,3})) @@ -106,13 +104,11 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh) bool EffectiveAddressAnalysis::analyze() { -#if defined(JS_ASMJS) for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) { for (MInstructionIterator i = block->begin(); i != block->end(); i++) { if (i->isLsh()) AnalyzeLsh(*block, i->toLsh()); } } -#endif return true; } diff --git a/js/src/ion/IonMacroAssembler.cpp b/js/src/ion/IonMacroAssembler.cpp index e60feedbce77..3ec382bfad49 100644 --- a/js/src/ion/IonMacroAssembler.cpp +++ b/js/src/ion/IonMacroAssembler.cpp @@ -1208,7 +1208,6 @@ MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg, } } -#ifdef JS_ASMJS ABIArgIter::ABIArgIter(const MIRTypeVector &types) : gen_(), types_(types), @@ -1226,4 +1225,3 @@ ABIArgIter::operator++(int) if (!done()) gen_.next(types_[i_]); } -#endif diff --git a/js/src/ion/IonMacroAssembler.h b/js/src/ion/IonMacroAssembler.h index a009d85d4123..7c48e7081f48 100644 --- a/js/src/ion/IonMacroAssembler.h +++ b/js/src/ion/IonMacroAssembler.h @@ -973,7 +973,6 @@ JSOpToCondition(JSOp op, bool isSigned) typedef Vector MIRTypeVector; -#ifdef JS_ASMJS class ABIArgIter { ABIArgGenerator gen_; @@ -993,7 +992,6 @@ class ABIArgIter MIRType mirType() const { JS_ASSERT(!done()); return types_[i_]; } uint32_t stackBytesConsumedSoFar() const { return gen_.stackBytesConsumedSoFar(); } }; -#endif } // namespace ion } // namespace js diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 1132434c829b..5ee1c1a98e50 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -29,7 +29,7 @@ #include "vm/Interpreter.h" #include "vm/Shape.h" -#ifdef JS_ASMJS +#ifdef JS_ION #include "ion/AsmJSModule.h" #endif @@ -912,7 +912,7 @@ JS_DumpCompartmentPCCounts(JSContext *cx) JS_DumpPCCounts(cx, script); } -#if defined(JS_ASMJS) && defined(DEBUG) +#if defined(JS_ION) && defined(DEBUG) for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) { for (CellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) { JSObject *obj = i.get(); From d38474b95748c291847b4201f5d0d475a5a598b4 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 12 Jun 2013 16:29:47 -0700 Subject: [PATCH 075/615] Bug 881882 - OdinMonkey: report compile time and slow functions in asm.js success message (r=sstangl) --HG-- extra : rebase_source : b72090feaf9e250e5085dcb8731edf4a1ff0daec --- js/src/ion/AsmJS.cpp | 99 ++++++++++++++++++++++++++++++++++++++++---- js/src/ion/AsmJS.h | 3 +- js/src/js.msg | 2 +- js/src/jsworkers.cpp | 5 +++ 4 files changed, 98 insertions(+), 11 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index ddbee04c707e..29abb895f0c0 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -932,6 +932,7 @@ class MOZ_STACK_CLASS ModuleCompiler MIRTypeVector argTypes_; RetType returnType_; mutable Label code_; + unsigned compileTime_; public: Func(ParseNode *fn, ParseNode *body, MoveRef types, RetType returnType) @@ -939,7 +940,8 @@ class MOZ_STACK_CLASS ModuleCompiler body_(body), argTypes_(types), returnType_(returnType), - code_() + code_(), + compileTime_(0) {} Func(MoveRef rhs) @@ -947,7 +949,8 @@ class MOZ_STACK_CLASS ModuleCompiler body_(rhs->body_), argTypes_(Move(rhs->argTypes_)), returnType_(rhs->returnType_), - code_(rhs->code_) + code_(rhs->code_), + compileTime_(rhs->compileTime_) {} ~Func() @@ -964,6 +967,8 @@ class MOZ_STACK_CLASS ModuleCompiler const MIRTypeVector &argMIRTypes() const { return argTypes_; } RetType returnType() const { return returnType_; } Label *codeLabel() const { return &code_; } + unsigned compileTime() const { return compileTime_; } + void accumulateCompileTime(unsigned ms) { compileTime_ += ms; } }; class Global @@ -1100,10 +1105,19 @@ class MOZ_STACK_CLASS ModuleCompiler typedef HashMap ExitMap; private: + struct SlowFunction + { + PropertyName *name; + unsigned ms; + unsigned line; + unsigned column; + }; + typedef HashMap MathNameMap; typedef HashMap GlobalMap; typedef Vector FuncVector; typedef Vector GlobalAccessVector; + typedef Vector SlowFunctionVector; JSContext * cx_; MacroAssembler masm_; @@ -1123,6 +1137,10 @@ class MOZ_STACK_CLASS ModuleCompiler char * errorString_; ParseNode * errorNode_; + + int64_t usecBefore_; + SlowFunctionVector slowFunctions_; + TokenStream & tokenStream_; DebugOnly currentPass_; @@ -1147,6 +1165,8 @@ class MOZ_STACK_CLASS ModuleCompiler globalAccesses_(cx), errorString_(NULL), errorNode_(NULL), + usecBefore_(PRMJ_Now()), + slowFunctions_(cx), tokenStream_(ts), currentPass_(1) {} @@ -1156,7 +1176,7 @@ class MOZ_STACK_CLASS ModuleCompiler tokenStream_.reportAsmJSError(errorNode_->pn_pos.begin, JSMSG_USE_ASM_TYPE_FAIL, errorString_); - JS_smprintf_free(errorString_); + js_free(errorString_); } // Avoid spurious Label assertions on compilation failure. @@ -1235,6 +1255,18 @@ class MOZ_STACK_CLASS ModuleCompiler return false; } + static const unsigned SLOW_FUNCTION_THRESHOLD_MS = 250; + + bool maybeReportCompileTime(ParseNode *fn, unsigned ms) { + if (ms < SLOW_FUNCTION_THRESHOLD_MS) + return true; + SlowFunction sf; + sf.name = FunctionName(fn); + sf.ms = ms; + tokenStream_.srcCoords.lineNumAndColumnIndex(fn->pn_pos.begin, &sf.line, &sf.column); + return slowFunctions_.append(sf); + } + /*************************************************** Read-only interface */ JSContext *cx() const { return cx_; } @@ -1456,6 +1488,31 @@ class MOZ_STACK_CLASS ModuleCompiler module_->exportedFunction(exportIndex).initCodeOffset(masm_.size()); } + void buildCompilationTimeReport(ScopedJSFreePtr *out) { + int64_t usecAfter = PRMJ_Now(); + int msTotal = (usecAfter - usecBefore_) / PRMJ_USEC_PER_MSEC; + ScopedJSFreePtr slowFuns; + if (!slowFunctions_.empty()) { + slowFuns.reset(JS_smprintf("; %d functions compiled slowly: ", slowFunctions_.length())); + if (!slowFuns) + return; + for (unsigned i = 0; i < slowFunctions_.length(); i++) { + SlowFunction &func = slowFunctions_[i]; + JSAutoByteString name; + if (!js_AtomToPrintableString(cx_, func.name, &name)) + return; + slowFuns.reset(JS_smprintf("%s%s:%u:%u (%ums, %g%%)%s", slowFuns.get(), + name.ptr(), func.line, func.column, func.ms, + double(func.ms)/double(msTotal), + i+1 < slowFunctions_.length() ? ", " : "")); + if (!slowFuns) + return; + } + } + out->reset(JS_smprintf("total compilation time %dms%s", + msTotal, slowFuns ? slowFuns.get() : "")); + } + bool finish(ScopedJSDeletePtr *module) { // After finishing, the only valid operation on an ModuleCompiler is // destruction. @@ -4633,6 +4690,8 @@ CheckVariableDecls(ModuleCompiler &m, FunctionCompiler::LocalMap *locals, ParseN static MIRGenerator * CheckFunctionBody(ModuleCompiler &m, ModuleCompiler::Func &func, LifoAlloc &lifo) { + int64_t before = PRMJ_Now(); + // CheckFunctionSignature already has already checked the // function head as well as argument type declarations. The ParseNode* // stored in f.body points to the first non-argument statement. @@ -4675,6 +4734,8 @@ CheckFunctionBody(ModuleCompiler &m, ModuleCompiler::Func &func, LifoAlloc &lifo f.returnVoid(); JS_ASSERT(!tempAlloc->rootList()); + func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC); + return mirGen; } @@ -4682,6 +4743,8 @@ static bool GenerateAsmJSCode(ModuleCompiler &m, ModuleCompiler::Func &func, MIRGenerator &mirGen, LIRGraph &lir) { + int64_t before = PRMJ_Now(); + m.masm().bind(func.codeLabel()); ScopedJSDeletePtr codegen(GenerateCode(&mirGen, &lir, &m.masm())); @@ -4714,6 +4777,10 @@ GenerateAsmJSCode(ModuleCompiler &m, ModuleCompiler::Func &func, // Align internal function headers. m.masm().align(CodeAlignment); + func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC); + if (!m.maybeReportCompileTime(func.fn(), func.compileTime())) + return false; + // Unlike regular IonMonkey which links and generates a new IonCode for // every function, we accumulate all the functions in the module in a // single MacroAssembler and link at end. Linking asm.js doesn't require a @@ -4743,6 +4810,8 @@ CheckFunctionBodiesSequential(ModuleCompiler &m) IonContext icx(m.cx()->compartment(), &mirGen->temp()); + int64_t before = PRMJ_Now(); + if (!OptimizeMIR(mirGen)) return m.fail(func.fn(), "internal compiler failure (probably out of memory)"); @@ -4750,6 +4819,8 @@ CheckFunctionBodiesSequential(ModuleCompiler &m) if (!lir) return m.fail(func.fn(), "internal compiler failure (probably out of memory)"); + func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC); + if (!GenerateAsmJSCode(m, func, *mirGen, *lir)) return false; @@ -4798,8 +4869,12 @@ GenerateCodeForFinishedJob(ModuleCompiler &m, ParallelGroupState &group, AsmJSPa if (!task) return false; + ModuleCompiler::Func &func = m.function(task->funcNum); + + func.accumulateCompileTime(task->compileTime); + // Perform code generation on the main thread. - if (!GenerateAsmJSCode(m, m.function(task->funcNum), *task->mir, *task->lir)) + if (!GenerateAsmJSCode(m, func, *task->mir, *task->lir)) return false; group.compiledJobs++; @@ -5996,7 +6071,8 @@ GenerateExits(ModuleCompiler &m) } static bool -CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr *module) +CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr *module, + ScopedJSFreePtr *compilationTimeReport) { ModuleCompiler m(cx, ts); if (!m.init()) @@ -6057,11 +6133,15 @@ CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr compilationTimeReport; ScopedJSDeletePtr module; - if (!CheckModule(cx, ts, fn, &module)) + if (!CheckModule(cx, ts, fn, &module, &compilationTimeReport)) return !cx->isExceptionPending(); module->initPostLinkFailureInfo(options, scriptSource, bufStart, bufEnd); @@ -6118,7 +6199,7 @@ js::CompileAsmJS(JSContext *cx, TokenStream &ts, ParseNode *fn, const CompileOpt SetAsmJSModuleObject(moduleFun, moduleObj); - return Warn(cx, JSMSG_USE_ASM_TYPE_OK); + return Warn(cx, JSMSG_USE_ASM_TYPE_OK, compilationTimeReport); } JSBool diff --git a/js/src/ion/AsmJS.h b/js/src/ion/AsmJS.h index c0147c7be93a..7e7c1701ff32 100644 --- a/js/src/ion/AsmJS.h +++ b/js/src/ion/AsmJS.h @@ -139,10 +139,11 @@ struct AsmJSParallelTask uint32_t funcNum; // Index |i| of function in |Module.function(i)|. ion::MIRGenerator *mir; // Passed from main thread to worker. ion::LIRGraph *lir; // Passed from worker to main thread. + unsigned compileTime; AsmJSParallelTask(size_t defaultChunkSize) : lifo(defaultChunkSize), - funcNum(0), mir(NULL), lir(NULL) + funcNum(0), mir(NULL), lir(NULL), compileTime(0) { } void init(uint32_t newFuncNum, ion::MIRGenerator *newMir) { diff --git a/js/src/js.msg b/js/src/js.msg index 6be024d6e475..5fb4ecc2ba33 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -394,7 +394,7 @@ MSG_DEF(JSMSG_CURLY_AFTER_MODULE, 340, 0, JSEXN_SYNTAXERR, "missing } after MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 341, 0, JSEXN_SYNTAXERR, "'use asm' directive only works on function code") MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 342, 1, JSEXN_TYPEERR, "asm.js type error: {0}") MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 343, 1, JSEXN_TYPEERR, "asm.js link error: {0}") -MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 344, 0, JSEXN_ERR, "successfully compiled asm.js code") +MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 344, 1, JSEXN_ERR, "successfully compiled asm.js code ({0})") MSG_DEF(JSMSG_BAD_ARROW_ARGS, 345, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)") MSG_DEF(JSMSG_YIELD_IN_ARROW, 346, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield") MSG_DEF(JSMSG_WRONG_VALUE, 347, 2, JSEXN_ERR, "expected {0} but found {1}") diff --git a/js/src/jsworkers.cpp b/js/src/jsworkers.cpp index 1835cc9503d3..0585c03a742b 100644 --- a/js/src/jsworkers.cpp +++ b/js/src/jsworkers.cpp @@ -346,6 +346,8 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state) do { ion::IonContext icx(asmData->mir->compartment, &asmData->mir->temp()); + int64_t before = PRMJ_Now(); + if (!OptimizeMIR(asmData->mir)) break; @@ -353,6 +355,9 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state) if (!asmData->lir) break; + int64_t after = PRMJ_Now(); + asmData->compileTime = (after - before) / PRMJ_USEC_PER_MSEC; + success = true; } while(0); state.lock(); From 2fd31aa3da5b7986f535fdbe879a7720ad09af57 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 12 Jun 2013 15:47:26 -0700 Subject: [PATCH 076/615] Bug 882012: Provide Use to right hand side in CheckStoreArray; r=luke --- js/src/ion/AsmJS.cpp | 12 +++++++++++- js/src/jit-test/tests/asm.js/testHeapAccess.js | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 29abb895f0c0..378ae3f3c412 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -3305,9 +3305,19 @@ CheckStoreArray(FunctionCompiler &f, ParseNode *lhs, ParseNode *rhs, MDefinition if (!CheckArrayAccess(f, lhs, &viewType, &pointerDef)) return false; + Use use; + switch (TypedArrayStoreType(viewType)) { + case ArrayStore_Intish: + use = Use::ToInt32; + break; + case ArrayStore_Doublish: + use = Use::ToNumber; + break; + } + MDefinition *rhsDef; Type rhsType; - if (!CheckExpr(f, rhs, Use::NoCoercion, &rhsDef, &rhsType)) + if (!CheckExpr(f, rhs, use, &rhsDef, &rhsType)) return false; switch (TypedArrayStoreType(viewType)) { diff --git a/js/src/jit-test/tests/asm.js/testHeapAccess.js b/js/src/jit-test/tests/asm.js/testHeapAccess.js index ebdb40a09249..30261890c14f 100644 --- a/js/src/jit-test/tests/asm.js/testHeapAccess.js +++ b/js/src/jit-test/tests/asm.js/testHeapAccess.js @@ -1,5 +1,8 @@ load(libdir + "asm.js"); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[0>>2] = 4.0; return i32[0>>2]|0; } return f'); +assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[0>>2] = 4; return +f32[0>>2]; } return f'); + assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return i8[x+y]|0 } return f'); assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return u8[x+y]|0 } return f'); @@ -161,3 +164,6 @@ assertEq(new Int32Array(BUF_64KB)[12], 11); assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[12]|0 } return f'), this, null, BUF_64KB)(), 11); new Float64Array(BUF_64KB)[0] = 3.5; assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +-f64[0] } return f'), this, null, BUF_64KB)(), -3.5); + +// Bug 882012 +assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + "var identity=foreign.identity;var doubles=new stdlib.Float64Array(heap);function g(){doubles[0]=identity(2.0);return +doubles[0];}return g"), this, {identity: function(x){return x;}}, BUF_64KB)(), 2.0); From c8d412570d432c173cb8dd981a1d8369e539ed08 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Fri, 14 Jun 2013 09:07:07 +1200 Subject: [PATCH 077/615] Bug 881954 - Generalize test_too_many_elements to run on more than just Ogg audio. r=padenot --- content/media/test/manifest.js | 19 ++++++++ .../media/test/test_too_many_elements.html | 44 ++++++++++++++----- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/content/media/test/manifest.js b/content/media/test/manifest.js index 2976e58535b8..25b2f8083a30 100644 --- a/content/media/test/manifest.js +++ b/content/media/test/manifest.js @@ -494,6 +494,25 @@ var gMetadataTests = [ }, ]; +// The resources for test_too_many_elements. +// We loads *lots* of these all at the same time. +var gTooManyElementAudioTests = [ + { name:"small-shot.ogg", type:"audio/ogg" }, + { name:"r11025_s16_c1.wav", type:"audio/x-wav" }, + { name:"detodos.opus", type:"audio/ogg; codecs=opus" }, + { name:"bogus.duh", type:"bogus/duh" } +]; +// Unfortunately the WMF backend on Windows 7 can't handle having lots of +// decoders running concurrently, so we only include MPEG files when running on +// Windows versions 8 and later, and non Windows systems. +if (navigator.userAgent.indexOf("Windows") == -1 || + IsWindows8OrLater()) { + gTooManyElementAudioTests = gTooManyElementAudioTests.concat([ + { name:"small-shot.m4a", type:"audio/mp4" }, + { name:"small-shot.mp3", type:"audio/mpeg" } + ]); +} + function checkMetadata(msg, e, test) { if (test.width) { is(e.videoWidth, test.width, msg + " video width"); diff --git a/content/media/test/test_too_many_elements.html b/content/media/test/test_too_many_elements.html index f144a95d9681..f25976ace929 100644 --- a/content/media/test/test_too_many_elements.html +++ b/content/media/test/test_too_many_elements.html @@ -24,43 +24,65 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=713381 const num = 500; var loadeddata = 0; +var testName = "?"; var result = document.getElementById("result"); document.getElementById("expected").innerHTML = " of " + num + " "; var finish = function(testNum) { return function() { - ok(true, "Received loadeddata event for instance " + testNum ); + ok(true, testName + ": received loadeddata event for instance " + testNum ); loadeddata++; if (loadeddata == num) { - ok(true, "Should receive loadeddata events for all " + num + " elements."); - SimpleTest.finish(); + ok(true, testName + ": should receive loadeddata events for all " + num + " elements."); + nextTest(); } } }; -var resource = getPlayableAudio(gSmallTests); +var testNum = 0; + +function nextTest() { + if (testNum >= gTooManyElementAudioTests.length) { + SimpleTest.finish(); + return; + } + var test = gTooManyElementAudioTests[testNum]; + testNum++; + + if (!document.createElement("audio").canPlayType(test.type)) { + setTimeout(nextTest, 0); + return; + } + var name = test.name; + + loadeddata = 0; + testName = name; -if (resource == null) { - todo(false, "No types supported"); -} else { - SimpleTest.waitForExplicitFinish(); // Load the resource, and play it to ensure it's entirely downloaded. // Once it's played through, create a large number of audio elements which // are the same resource. These will share data with the other resource, and // so be really cheap to create. - var res = new Audio(resource.name); + var res = new Audio(name); res.addEventListener("ended", function() { for (var i=0; i From 77c4771d6e984b3e320e0190a0b0ebe25520025a Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Fri, 14 Jun 2013 09:07:28 +1200 Subject: [PATCH 078/615] Bug 881954 - Only initialize DXVA when we're decoding video. r=padenot --- content/media/wmf/DXVA2Manager.cpp | 14 ++++++++++++++ content/media/wmf/WMFReader.cpp | 19 ++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/content/media/wmf/DXVA2Manager.cpp b/content/media/wmf/DXVA2Manager.cpp index 95ae4c861a25..87ab384a8719 100644 --- a/content/media/wmf/DXVA2Manager.cpp +++ b/content/media/wmf/DXVA2Manager.cpp @@ -168,6 +168,10 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample, return S_OK; } +// Count of the number of DXVAManager's we've created. This is also the +// number of videos we're decoding with DXVA. Use on main thread only. +static uint32_t sDXVAVideosCount = 0; + /* static */ DXVA2Manager* DXVA2Manager::Create() @@ -175,6 +179,14 @@ DXVA2Manager::Create() MOZ_ASSERT(NS_IsMainThread()); HRESULT hr; + // DXVA processing takes up a lot of GPU resources, so limit the number of + // videos we use DXVA with at any one time. + const uint32_t dxvaLimit = + Preferences::GetInt("media.windows-media-foundation.max-dxva-videos", 8); + if (sDXVAVideosCount == dxvaLimit) { + return nullptr; + } + nsAutoPtr d3d9Manager(new D3D9DXVA2Manager()); hr = d3d9Manager->Init(); if (SUCCEEDED(hr)) { @@ -189,11 +201,13 @@ DXVA2Manager::DXVA2Manager() : mLock("DXVA2Manager") { MOZ_ASSERT(NS_IsMainThread()); + ++sDXVAVideosCount; } DXVA2Manager::~DXVA2Manager() { MOZ_ASSERT(NS_IsMainThread()); + --sDXVAVideosCount; } } // namespace mozilla diff --git a/content/media/wmf/WMFReader.cpp b/content/media/wmf/WMFReader.cpp index e8af9e3c5971..652537d3ca8d 100644 --- a/content/media/wmf/WMFReader.cpp +++ b/content/media/wmf/WMFReader.cpp @@ -120,9 +120,18 @@ WMFReader::InitializeDXVA() } mDXVA2Manager = DXVA2Manager::Create(); - NS_ENSURE_TRUE(mDXVA2Manager, false); - return true; + return mDXVA2Manager != nullptr; +} + +static bool +IsVideoContentType(const nsCString& aContentType) +{ + NS_NAMED_LITERAL_CSTRING(video, "video"); + if (FindInReadable(video, aContentType)) { + return true; + } + return false; } nsresult @@ -145,7 +154,11 @@ WMFReader::Init(MediaDecoderReader* aCloneDonor) rv = mByteStream->Init(); NS_ENSURE_SUCCESS(rv, rv); - mUseHwAccel = InitializeDXVA(); + if (IsVideoContentType(mDecoder->GetResource()->GetContentType())) { + mUseHwAccel = InitializeDXVA(); + } else { + mUseHwAccel = false; + } return NS_OK; } From 2db134f9c402f8cfc45cbfc3f40844453a8cb4c6 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Fri, 14 Jun 2013 09:07:59 +1200 Subject: [PATCH 079/615] Bug 881954 - Set the thread limit to the idle limit for WMFByteStream's thread pool. This stops the pool from constantly creating and destroying threads when under load, freeing up virtual address space and reducing our thread count. r=padenot --- content/media/wmf/WMFByteStream.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/content/media/wmf/WMFByteStream.cpp b/content/media/wmf/WMFByteStream.cpp index 47ba195e853b..cca59bae1e08 100644 --- a/content/media/wmf/WMFByteStream.cpp +++ b/content/media/wmf/WMFByteStream.cpp @@ -28,6 +28,9 @@ PRLogModuleInfo* gWMFByteStreamLog = nullptr; #define LOG(...) #endif +// Limit the number of threads that we use for IO. +static const uint32_t NumWMFIoThreads = 4; + // Thread pool listener which ensures that MSCOM is initialized and // deinitialized on the thread pool thread. We can call back into WMF // on this thread, so we need MSCOM working. @@ -143,6 +146,19 @@ WMFByteStream::Init() rv = sThreadPool->SetName(NS_LITERAL_CSTRING("WMFByteStream Async Read Pool")); NS_ENSURE_SUCCESS(rv, rv); + + // We limit the number of threads that we use for IO. Note that the thread + // limit is the same as the idle limit so that we're not constantly creating + // and destroying threads. When the thread pool threads shutdown they + // dispatch an event to the main thread to call nsIThread::Shutdown(), + // and if we're very busy that can take a while to run, and we end up with + // dozens of extra threads. Note that threads that are idle for 60 seconds + // are shutdown naturally. + rv = sThreadPool->SetThreadLimit(NumWMFIoThreads); + NS_ENSURE_SUCCESS(rv, rv); + + rv = sThreadPool->SetIdleThreadLimit(NumWMFIoThreads); + NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr listener = new ThreadPoolListener(); rv = sThreadPool->SetListener(listener); From 7c48823e908cb0a665205ca99edb7c275180bff8 Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Thu, 13 Jun 2013 14:19:04 -0700 Subject: [PATCH 080/615] Bug 872142 - Make selecthelper use async prompts. r=bnicholson --- mobile/android/chrome/content/SelectHelper.js | 125 +++++++++--------- 1 file changed, 60 insertions(+), 65 deletions(-) diff --git a/mobile/android/chrome/content/SelectHelper.js b/mobile/android/chrome/content/SelectHelper.js index af40bc5bb1e2..463edf4d983f 100644 --- a/mobile/android/chrome/content/SelectHelper.js +++ b/mobile/android/chrome/content/SelectHelper.js @@ -23,32 +23,49 @@ var SelectHelper = { show: function(aElement) { let list = this.getListForElement(aElement); - let data = JSON.parse(sendMessageToJava(list)); - let selected = data.button; - if (selected == -1) - return; - var changed = false; - if (aElement instanceof Ci.nsIDOMXULMenuListElement) { - aElement.selectedIndex = selected; - } else if (aElement instanceof HTMLSelectElement) { - if (!(selected instanceof Array)) { - let temp = []; - for (let i = 0; i < list.listitems.length; i++) { - temp[i] = (i == selected); - } - selected = temp; - } - let i = 0; - this.forOptions(aElement, function(aNode) { - if (aNode.selected != selected[i]) - changed = true; - aNode.selected = selected[i++]; - }); + let p = new Prompt({ + window: aElement.contentDocument + }); + + if (aElement.multiple) { + p.addButton({ + label: Strings.browser.GetStringFromName("selectHelper.closeMultipleSelectDialog") + }).setMultiChoiceItems(list); + } else { + p.setSingleChoiceItems(list); } - if (changed) - this.fireOnChange(aElement); + p.show((function(data) { + let selected = data.button; + if (selected == -1) + return; + + let changed = false; + if (aElement instanceof Ci.nsIDOMXULMenuListElement) { + aElement.selectedIndex = selected; + } else if (aElement instanceof HTMLSelectElement) { + if (!Array.isArray(selected)) { + let temp = []; + for (let i = 0; i <= list.length; i++) { + temp[i] = (i == selected); + } + selected = temp; + } + + let i = 0; + this.forOptions(aElement, function(aNode) { + if (aNode.selected != selected[i]) { + changed = true; + aNode.selected = selected[i]; + } + i++ + }); + } + + if (changed) + this.fireOnChange(aElement); + }).bind(this)); }, _isMenu: function(aElement) { @@ -57,70 +74,48 @@ var SelectHelper = { }, getListForElement: function(aElement) { - let result = { - type: "Prompt:Show", - multiple: aElement.multiple, - selected: [], - listitems: [] - }; - - if (aElement.multiple) { - result.buttons = [ - Strings.browser.GetStringFromName("selectHelper.closeMultipleSelectDialog") - ]; - } - let index = 0; - this.forOptions(aElement, function(aNode, aOptions) { + let items = []; + this.forOptions(aElement, function(aNode, aOptions, aParent) { let item = { label: aNode.text || aNode.label, - isGroup: aOptions.isGroup, - inGroup: aOptions.inGroup, + header: aOptions.isGroup, disabled: aNode.disabled, - id: index + id: index, + selected: aNode.selected } - if (aOptions.inGroup) - item.disabled = item.disabled || aNode.parentNode.disabled; - result.listitems[index] = item; - result.selected[index] = aNode.selected; + if (aParent) { + item.child = true; + item.disabled = item.disabled || aParent.disabled; + } + items.push(item); + index++; }); - return result; + return items; }, - forOptions: function(aElement, aFunction) { - let parent = aElement; + forOptions: function(aElement, aFunction, aParent = null) { + let element = aElement; if (aElement instanceof Ci.nsIDOMXULMenuListElement) - parent = aElement.menupopup; - let children = parent.children; + element = aElement.menupopup; + let children = element.children; let numChildren = children.length; // if there are no children in this select, we add a dummy row so that at least something appears if (numChildren == 0) - aFunction.call(this, { label: "" }, { isGroup: false, inGroup: false }); + aFunction.call(this, { label: "" }, { isGroup: false }, aParent); for (let i = 0; i < numChildren; i++) { let child = children[i]; if (child instanceof HTMLOptionElement || child instanceof Ci.nsIDOMXULSelectControlItemElement) { - // This is a regular choice under no group. - aFunction.call(this, child, { - isGroup: false, inGroup: false - }); + aFunction.call(this, child, { isGroup: false }, aParent); } else if (child instanceof HTMLOptGroupElement) { - aFunction.call(this, child, { - isGroup: true, inGroup: false - }); + aFunction.call(this, child, { isGroup: true }); + this.forOptions(child, aFunction, child); - let subchildren = child.children; - let numSubchildren = subchildren.length; - for (let j = 0; j < numSubchildren; j++) { - let subchild = subchildren[j]; - aFunction.call(this, subchild, { - isGroup: false, inGroup: true - }); - } } } }, From 26166581998beecfaf2807579d7974bf049a142d Mon Sep 17 00:00:00 2001 From: Joey Armstrong Date: Thu, 13 Jun 2013 17:49:21 -0400 Subject: [PATCH 081/615] bug 872086-2: move SIMPLE_PROGRAMS to moz.build (file batch #2) r=mshal --- mozglue/tests/Makefile.in | 2 +- mozglue/tests/moz.build | 3 +++ toolkit/mozapps/update/test/Makefile.in | 2 +- toolkit/mozapps/update/test/moz.build | 7 +++++++ uriloader/exthandler/tests/Makefile.in | 2 +- uriloader/exthandler/tests/moz.build | 5 +++++ xpcom/tests/Makefile.in | 2 +- xpcom/tests/external/Makefile.in | 2 +- xpcom/tests/external/moz.build | 3 +++ xpcom/tests/moz.build | 6 ++++++ 10 files changed, 29 insertions(+), 5 deletions(-) diff --git a/mozglue/tests/Makefile.in b/mozglue/tests/Makefile.in index 17809fb2de6e..d437a47c754d 100644 --- a/mozglue/tests/Makefile.in +++ b/mozglue/tests/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk ifdef MOZ_LINKER -SIMPLE_PROGRAMS := TestZip$(BIN_SUFFIX) +DISABLE_SIMPLE_PROGRAMS := TestZip$(BIN_SUFFIX) NO_DIST_INSTALL = 1 STL_FLAGS = diff --git a/mozglue/tests/moz.build b/mozglue/tests/moz.build index e9d5e9737369..1f995db62247 100644 --- a/mozglue/tests/moz.build +++ b/mozglue/tests/moz.build @@ -8,3 +8,6 @@ if CONFIG['MOZ_LINKER']: CPP_SOURCES += [ 'TestZip.cpp', ] + SIMPLE_PROGRAMS += [ + 'TestZip%s' % CONFIG['BIN_SUFFIX'], + ] diff --git a/toolkit/mozapps/update/test/Makefile.in b/toolkit/mozapps/update/test/Makefile.in index b01aac72a218..16b88f940a62 100644 --- a/toolkit/mozapps/update/test/Makefile.in +++ b/toolkit/mozapps/update/test/Makefile.in @@ -33,7 +33,7 @@ cppsrcs = \ $(NULL) # TODO: Base off of CPP_SOURCES in moz.build -SIMPLE_PROGRAMS = $(cppsrcs:.cpp=$(BIN_SUFFIX)) +DISABLED_SIMPLE_PROGRAMS = $(cppsrcs:.cpp=$(BIN_SUFFIX)) INI_TEST_FILES = \ TestAUSReadStrings1.ini \ diff --git a/toolkit/mozapps/update/test/moz.build b/toolkit/mozapps/update/test/moz.build index 991aa438a3b3..1a796a8a7c2f 100644 --- a/toolkit/mozapps/update/test/moz.build +++ b/toolkit/mozapps/update/test/moz.build @@ -12,3 +12,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': ] XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] + +if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': + programs = [ + fyl[0:-4] for fyl in CPP_SOURCES + ] + programs.sort() + SIMPLE_PROGRAMS += programs diff --git a/uriloader/exthandler/tests/Makefile.in b/uriloader/exthandler/tests/Makefile.in index 065e79656bd4..e94681df570c 100644 --- a/uriloader/exthandler/tests/Makefile.in +++ b/uriloader/exthandler/tests/Makefile.in @@ -12,7 +12,7 @@ include $(DEPTH)/config/autoconf.mk FAIL_ON_WARNINGS = 1 -SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) +DISABLED_SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) include $(topsrcdir)/config/config.mk diff --git a/uriloader/exthandler/tests/moz.build b/uriloader/exthandler/tests/moz.build index b9707821144c..824337c9834a 100644 --- a/uriloader/exthandler/tests/moz.build +++ b/uriloader/exthandler/tests/moz.build @@ -17,3 +17,8 @@ if CONFIG['OS_ARCH'] != 'Darwin': CPP_SOURCES += [ 'WriteArgument.cpp', ] + +bin_suffix = CONFIG['BIN_SUFFIX'] +SIMPLE_PROGRAMS += [ + "%s%s" % (fyl[0:-4], bin_suffix) for fyl in CPP_SOURCES +] diff --git a/xpcom/tests/Makefile.in b/xpcom/tests/Makefile.in index c159c082fb49..17171cb19193 100644 --- a/xpcom/tests/Makefile.in +++ b/xpcom/tests/Makefile.in @@ -41,7 +41,7 @@ cppsrcs += TestSTLWrappers.cpp endif # TODO: Use CPPSRCS from moz.build -SIMPLE_PROGRAMS := $(cppsrcs:.cpp=$(BIN_SUFFIX)) +DISABLED_SIMPLE_PROGRAMS := $(cppsrcs:.cpp=$(BIN_SUFFIX)) CPP_UNIT_TESTS = \ ShowAlignments.cpp \ diff --git a/xpcom/tests/external/Makefile.in b/xpcom/tests/external/Makefile.in index 444831f8aa6d..0db888667d35 100644 --- a/xpcom/tests/external/Makefile.in +++ b/xpcom/tests/external/Makefile.in @@ -9,7 +9,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) +DISABLED_SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) include $(topsrcdir)/config/rules.mk diff --git a/xpcom/tests/external/moz.build b/xpcom/tests/external/moz.build index 2322c4c0e689..5a3513d2f7e8 100644 --- a/xpcom/tests/external/moz.build +++ b/xpcom/tests/external/moz.build @@ -10,3 +10,6 @@ CPP_SOURCES += [ 'TestMinStringAPI.cpp', ] +SIMPLE_PROGRAMS += [ + fyl[0:-4] for fyl in CPP_SOURCES +] diff --git a/xpcom/tests/moz.build b/xpcom/tests/moz.build index ea3f5a2c62cd..7e81ee8450eb 100644 --- a/xpcom/tests/moz.build +++ b/xpcom/tests/moz.build @@ -45,3 +45,9 @@ CPP_SOURCES += [ 'TestUnicodeArguments.cpp', 'nsIFileEnumerator.cpp', ] + +programs = [ + fyl[0:-4] for fyl in CPP_SOURCES +] +programs.sort() +SIMPLE_PROGRAMS += programs From c23adc35639e30a287deede2d41e2345d4ebbbec Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Thu, 30 May 2013 21:21:18 -0400 Subject: [PATCH 082/615] bug 877937 - build the js engine in c++11 mode when we do that for the rest of the tree r=ted --- js/src/configure.in | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/js/src/configure.in b/js/src/configure.in index fe18b005eaa9..5987eb5aafb8 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2332,6 +2332,35 @@ else AC_MSG_RESULT(no) fi +dnl Check whether we can use gcc's c++0x mode +AC_LANG_CPLUSPLUS + +if test "$GNU_CXX"; then + _SAVE_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS -std=gnu++0x" + + AC_CACHE_CHECK(for gcc c++0x headers bug without rtti, + ac_cv_cxx0x_headers_bug, + [AC_TRY_COMPILE([#include ], [], + ac_cv_cxx0x_headers_bug="no", + ac_cv_cxx0x_headers_bug="yes")]) + + if test "$CLANG_CXX" -a "$ac_cv_cxx0x_headers_bug" = "yes"; then + CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers" + AC_CACHE_CHECK(whether workaround for gcc c++0x headers conflict with clang works, + ac_cv_cxx0x_clang_workaround, + [AC_TRY_COMPILE([#include ], [], + ac_cv_cxx0x_clang_workaround="yes", + ac_cv_cxx0x_clang_workaround="no")]) + + if test "ac_cv_cxx0x_clang_workaround" = "no"; then + CXXFLAGS="$_SAVE_CXXFLAGS" + fi + elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then + CXXFLAGS="$_SAVE_CXXFLAGS" + fi +fi + AC_LANG_C dnl Check for .hidden assembler directive and visibility attribute. From 44c322f19c203660fef16355f210baaec3e4267e Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Wed, 5 Jun 2013 18:55:17 -0400 Subject: [PATCH 083/615] bug 877937 - make js embedders build as c++11 when we do r=ted f=waldo --- js/src/Makefile.in | 3 ++- js/src/configure.in | 4 ++++ js/src/js-config.in | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/js/src/Makefile.in b/js/src/Makefile.in index a1bc94dff284..4944d3143ba9 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -517,7 +517,8 @@ JS_CONFIG_SUBSTITUTIONS=\ -DMOZJS_PATCH_VERSION="$(MOZJS_PATCH_VERSION)" \ -DMOZJS_ALPHA="$(MOZJS_ALPHA)" \ -DNSPR_CFLAGS="$(NSPR_CFLAGS)" \ - -DNSPR_PKGCONF_CHECK="$(NSPR_PKGCONF_CHECK)" + -DNSPR_PKGCONF_CHECK="$(NSPR_PKGCONF_CHECK)" \ + -DUSE_CXX11="$(USE_CXX11)" $(JS_CONFIG_NAME): js-config.in Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk $(topsrcdir)/config/rules.mk $(RM) $@.tmp diff --git a/js/src/configure.in b/js/src/configure.in index 5987eb5aafb8..f0d62942e626 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2338,6 +2338,7 @@ AC_LANG_CPLUSPLUS if test "$GNU_CXX"; then _SAVE_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS -std=gnu++0x" + USE_CXX11=1 AC_CACHE_CHECK(for gcc c++0x headers bug without rtti, ac_cv_cxx0x_headers_bug, @@ -2355,9 +2356,11 @@ if test "$GNU_CXX"; then if test "ac_cv_cxx0x_clang_workaround" = "no"; then CXXFLAGS="$_SAVE_CXXFLAGS" + USE_CXX11= fi elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then CXXFLAGS="$_SAVE_CXXFLAGS" + USE_CXX11= fi fi @@ -4331,6 +4334,7 @@ AC_SUBST(OS_TEST) AC_SUBST(CPU_ARCH) AC_SUBST(INTEL_ARCHITECTURE) +AC_SUBST(USE_CXX11) AC_SUBST(WRAP_LDFLAGS) AC_SUBST(MKSHLIB) AC_SUBST(MKCSHLIB) diff --git a/js/src/js-config.in b/js/src/js-config.in index d46a96982a99..cf0d867c44fc 100644 --- a/js/src/js-config.in +++ b/js/src/js-config.in @@ -109,7 +109,11 @@ if test "$echo_libdir" = "yes"; then fi if test "$echo_cflags" = "yes"; then - echo "-include $includedir/$LIBRARY_NAME/js/RequiredDefines.h -I$includedir/$LIBRARY_NAME $NSPR_CFLAGS" + cflags="-include $includedir/$LIBRARY_NAME/js/RequiredDefines.h -I$includedir/$LIBRARY_NAME $NSPR_CFLAGS" + if test '@USE_CXX11@' = "1"; then + cflags="$cflags -std=gnu++0x" + fi + echo $cflags fi if test "$echo_libs" = "yes"; then From 6ecaa921b73f20536b356a61a82cddbbaa94ccb4 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Fri, 14 Jun 2013 02:50:53 -0400 Subject: [PATCH 084/615] bug 877937 - placate clang when building the jseng as c++11 r=waldo --- js/src/frontend/ParseMaps.cpp | 4 ++-- js/src/gc/Heap.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/js/src/frontend/ParseMaps.cpp b/js/src/frontend/ParseMaps.cpp index 03a9fabc6fa6..e7ffef5462ad 100644 --- a/js/src/frontend/ParseMaps.cpp +++ b/js/src/frontend/ParseMaps.cpp @@ -133,5 +133,5 @@ frontend::InitAtomMap(JSContext *cx, frontend::AtomIndexMap *indices, HeapPtrAto } } -template class AtomDecls; -template class AtomDecls; +template class js::frontend::AtomDecls; +template class js::frontend::AtomDecls; diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 86cfefef2ac9..097c2944eea2 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -670,10 +670,6 @@ struct ChunkBitmap public: ChunkBitmap() { } - ChunkBitmap(MoveRef b) { - mozilla::PodArrayCopy(bitmap, b->bitmap); - } - MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color, uintptr_t **wordp, uintptr_t *maskp) From fa77ae873c5b542e721bbbb0a9f6682eec229e6d Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 13 Jun 2013 15:14:44 -0700 Subject: [PATCH 085/615] No Bug - Assert that our Rooting ABI is correct; r=sfink --HG-- extra : rebase_source : 3247d6a22f73d278ae4e6904dff28a1b727e5169 --- js/public/RootingAPI.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index 5f4fecb7b0e8..6ffe4597057f 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -178,7 +178,11 @@ template class Heap : public js::HeapBase { public: - Heap() { set(js::RootMethods::initial()); } + Heap() { + MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap), + "Heap must be binary compatible with T."); + set(js::RootMethods::initial()); + } explicit Heap(T p) { set(p); } explicit Heap(const Heap &p) { set(p.ptr); } @@ -251,6 +255,8 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase Handle(Handle handle, typename mozilla::EnableIf::value, int>::Type dummy = 0) { + MOZ_STATIC_ASSERT(sizeof(Handle) == sizeof(T *), + "Handle must be binary compatible with T*."); ptr = reinterpret_cast(handle.address()); } @@ -880,6 +886,8 @@ template inline MutableHandle::MutableHandle(Rooted *root) { + MOZ_STATIC_ASSERT(sizeof(MutableHandle) == sizeof(T *), + "MutableHandle must be binary compatible with T*."); ptr = root->address(); } From edd11a247711fc1549917df9c867af5feb501d0a Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 13 Jun 2013 15:14:59 -0700 Subject: [PATCH 086/615] No Bug - Fix an out-of-date comment in Ion about JM compilation; r=bhackett --HG-- extra : rebase_source : 62d580d82808312c12444cb2c9163b1b569bd945 --- js/src/ion/Ion.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp index 3664b26ddbca..78ba18d5f677 100644 --- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1266,8 +1266,7 @@ AttachFinishedCompilations(JSContext *cx) OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations(); // Incorporate any off thread compilations which have finished, failed or - // have been cancelled, and destroy JM jitcode for any compilations which - // succeeded, to allow entering the Ion code from the interpreter. + // have been cancelled. while (!compilations.empty()) { IonBuilder *builder = compilations.popCopy(); From 0718a98afd294cd336e1490faae87aa80f9b73d5 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Thu, 13 Jun 2013 15:13:13 -0700 Subject: [PATCH 087/615] Bug 829817 - Cycle collect nsCSSPageRule. r=dbaron --- layout/style/crashtests/829817.html | 20 ++++++++++++++++++++ layout/style/crashtests/crashtests.list | 1 + layout/style/nsCSSRules.cpp | 18 ++++++++++++++---- layout/style/nsCSSRules.h | 3 ++- 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 layout/style/crashtests/829817.html diff --git a/layout/style/crashtests/829817.html b/layout/style/crashtests/829817.html new file mode 100644 index 000000000000..a81fb6b79d88 --- /dev/null +++ b/layout/style/crashtests/829817.html @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index badb600eed74..45468fa844c4 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -88,6 +88,7 @@ load 812824.html load 822842.html load 822766-1.html load 827591-1.html +load 829817.html load 840898.html load 842134.html load 862113.html diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 1016bf9d2db6..c74b9f5ad304 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -2261,7 +2261,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule) if (tmp->mDOMDeclaration) { tmp->mDOMDeclaration->DropReference(); - ImplCycleCollectionUnlink(tmp->mDOMDeclaration); + tmp->mDOMDeclaration = nullptr; } NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule) @@ -2744,13 +2744,23 @@ nsCSSPageRule::Clone() const return clone.forget(); } -NS_IMPL_ADDREF(nsCSSPageRule) -NS_IMPL_RELEASE(nsCSSPageRule) +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageRule) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageRule) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSPageRule) + if (tmp->mDOMDeclaration) { + tmp->mDOMDeclaration->DropReference(); + tmp->mDOMDeclaration = nullptr; + } +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSPageRule) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END DOMCI_DATA(CSSPageRule, nsCSSPageRule) // QueryInterface implementation for nsCSSPageRule -NS_INTERFACE_MAP_BEGIN(nsCSSPageRule) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageRule) NS_INTERFACE_MAP_ENTRY(nsIStyleRule) NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule) NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) diff --git a/layout/style/nsCSSRules.h b/layout/style/nsCSSRules.h index 883f2f7768c8..1c637ceb38ab 100644 --- a/layout/style/nsCSSRules.h +++ b/layout/style/nsCSSRules.h @@ -554,7 +554,8 @@ private: nsCSSPageRule(const nsCSSPageRule& aCopy); ~nsCSSPageRule(); public: - NS_DECL_ISUPPORTS + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCSSPageRule, nsIDOMCSSPageRule) // nsIStyleRule methods #ifdef DEBUG From e6b001acadc333e8b1a892a69ccf92d11ea2d0cd Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 13 Jun 2013 18:31:27 -0400 Subject: [PATCH 088/615] Backed out changeset c1c441c9edce (bug 845668) for frequent Windows mochitest-2 crashes. CLOSED TREE --- content/base/src/nsFrameLoader.cpp | 2 ++ content/base/src/nsFrameLoader.h | 1 + 2 files changed, 3 insertions(+) diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 74968abeff73..c63724cadd78 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -2049,6 +2049,8 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr browserDOMWin; rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin)); mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin); + + mChildHost = static_cast(mRemoteBrowser->Manager()); } return true; } diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 64255ec03b07..669631edf87f 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -434,6 +434,7 @@ private: bool mVisible : 1; // XXX leaking + nsCOMPtr mChildHost; RenderFrameParent* mCurrentRemoteFrame; TabParent* mRemoteBrowser; From c18dd6b028b20867f6b903bd69e866562bc54774 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 13 Jun 2013 18:33:46 -0400 Subject: [PATCH 089/615] Backed out changeset b5c0c5b2a6d4 (bug 872086) for Windows bustage. CLOSED TREE --- mozglue/tests/Makefile.in | 2 +- mozglue/tests/moz.build | 3 --- toolkit/mozapps/update/test/Makefile.in | 2 +- toolkit/mozapps/update/test/moz.build | 7 ------- uriloader/exthandler/tests/Makefile.in | 2 +- uriloader/exthandler/tests/moz.build | 5 ----- xpcom/tests/Makefile.in | 2 +- xpcom/tests/external/Makefile.in | 2 +- xpcom/tests/external/moz.build | 3 --- xpcom/tests/moz.build | 6 ------ 10 files changed, 5 insertions(+), 29 deletions(-) diff --git a/mozglue/tests/Makefile.in b/mozglue/tests/Makefile.in index d437a47c754d..17809fb2de6e 100644 --- a/mozglue/tests/Makefile.in +++ b/mozglue/tests/Makefile.in @@ -10,7 +10,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk ifdef MOZ_LINKER -DISABLE_SIMPLE_PROGRAMS := TestZip$(BIN_SUFFIX) +SIMPLE_PROGRAMS := TestZip$(BIN_SUFFIX) NO_DIST_INSTALL = 1 STL_FLAGS = diff --git a/mozglue/tests/moz.build b/mozglue/tests/moz.build index 1f995db62247..e9d5e9737369 100644 --- a/mozglue/tests/moz.build +++ b/mozglue/tests/moz.build @@ -8,6 +8,3 @@ if CONFIG['MOZ_LINKER']: CPP_SOURCES += [ 'TestZip.cpp', ] - SIMPLE_PROGRAMS += [ - 'TestZip%s' % CONFIG['BIN_SUFFIX'], - ] diff --git a/toolkit/mozapps/update/test/Makefile.in b/toolkit/mozapps/update/test/Makefile.in index 16b88f940a62..b01aac72a218 100644 --- a/toolkit/mozapps/update/test/Makefile.in +++ b/toolkit/mozapps/update/test/Makefile.in @@ -33,7 +33,7 @@ cppsrcs = \ $(NULL) # TODO: Base off of CPP_SOURCES in moz.build -DISABLED_SIMPLE_PROGRAMS = $(cppsrcs:.cpp=$(BIN_SUFFIX)) +SIMPLE_PROGRAMS = $(cppsrcs:.cpp=$(BIN_SUFFIX)) INI_TEST_FILES = \ TestAUSReadStrings1.ini \ diff --git a/toolkit/mozapps/update/test/moz.build b/toolkit/mozapps/update/test/moz.build index 1a796a8a7c2f..991aa438a3b3 100644 --- a/toolkit/mozapps/update/test/moz.build +++ b/toolkit/mozapps/update/test/moz.build @@ -12,10 +12,3 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': ] XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini'] - -if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': - programs = [ - fyl[0:-4] for fyl in CPP_SOURCES - ] - programs.sort() - SIMPLE_PROGRAMS += programs diff --git a/uriloader/exthandler/tests/Makefile.in b/uriloader/exthandler/tests/Makefile.in index e94681df570c..065e79656bd4 100644 --- a/uriloader/exthandler/tests/Makefile.in +++ b/uriloader/exthandler/tests/Makefile.in @@ -12,7 +12,7 @@ include $(DEPTH)/config/autoconf.mk FAIL_ON_WARNINGS = 1 -DISABLED_SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) +SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) include $(topsrcdir)/config/config.mk diff --git a/uriloader/exthandler/tests/moz.build b/uriloader/exthandler/tests/moz.build index 824337c9834a..b9707821144c 100644 --- a/uriloader/exthandler/tests/moz.build +++ b/uriloader/exthandler/tests/moz.build @@ -17,8 +17,3 @@ if CONFIG['OS_ARCH'] != 'Darwin': CPP_SOURCES += [ 'WriteArgument.cpp', ] - -bin_suffix = CONFIG['BIN_SUFFIX'] -SIMPLE_PROGRAMS += [ - "%s%s" % (fyl[0:-4], bin_suffix) for fyl in CPP_SOURCES -] diff --git a/xpcom/tests/Makefile.in b/xpcom/tests/Makefile.in index 17171cb19193..c159c082fb49 100644 --- a/xpcom/tests/Makefile.in +++ b/xpcom/tests/Makefile.in @@ -41,7 +41,7 @@ cppsrcs += TestSTLWrappers.cpp endif # TODO: Use CPPSRCS from moz.build -DISABLED_SIMPLE_PROGRAMS := $(cppsrcs:.cpp=$(BIN_SUFFIX)) +SIMPLE_PROGRAMS := $(cppsrcs:.cpp=$(BIN_SUFFIX)) CPP_UNIT_TESTS = \ ShowAlignments.cpp \ diff --git a/xpcom/tests/external/Makefile.in b/xpcom/tests/external/Makefile.in index 0db888667d35..444831f8aa6d 100644 --- a/xpcom/tests/external/Makefile.in +++ b/xpcom/tests/external/Makefile.in @@ -9,7 +9,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DISABLED_SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) +SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX)) include $(topsrcdir)/config/rules.mk diff --git a/xpcom/tests/external/moz.build b/xpcom/tests/external/moz.build index 5a3513d2f7e8..2322c4c0e689 100644 --- a/xpcom/tests/external/moz.build +++ b/xpcom/tests/external/moz.build @@ -10,6 +10,3 @@ CPP_SOURCES += [ 'TestMinStringAPI.cpp', ] -SIMPLE_PROGRAMS += [ - fyl[0:-4] for fyl in CPP_SOURCES -] diff --git a/xpcom/tests/moz.build b/xpcom/tests/moz.build index 7e81ee8450eb..ea3f5a2c62cd 100644 --- a/xpcom/tests/moz.build +++ b/xpcom/tests/moz.build @@ -45,9 +45,3 @@ CPP_SOURCES += [ 'TestUnicodeArguments.cpp', 'nsIFileEnumerator.cpp', ] - -programs = [ - fyl[0:-4] for fyl in CPP_SOURCES -] -programs.sort() -SIMPLE_PROGRAMS += programs From a7976b2932705b795b424f7a0f9dcec36e1c233f Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 13 Jun 2013 18:37:50 -0400 Subject: [PATCH 090/615] Backed out changeset eb8b971070eb (bug 844852) for checktest failures. CLOSED TREE --- testing/gtest/Makefile.in | 1 - testing/gtest/mozilla/GTestRunner.cpp | 29 ------ testing/gtest/rungtests.py | 129 -------------------------- 3 files changed, 159 deletions(-) delete mode 100644 testing/gtest/rungtests.py diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in index f6c6d5e5da8c..e332f819606f 100644 --- a/testing/gtest/Makefile.in +++ b/testing/gtest/Makefile.in @@ -45,7 +45,6 @@ check gtest:: ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) $(MAKE) -C $(DEPTH)/browser/app repackage endif - $(PYTHON) $(topsrcdir)/testing/gtest/rungtests.py --xre-path=$(DIST)/bin --symbols-path=$(DIST)/crashreporter-symbols $(DIST)/bin/$(MOZ_APP_NAME)$(BIN_SUFFIX) endif endif diff --git a/testing/gtest/mozilla/GTestRunner.cpp b/testing/gtest/mozilla/GTestRunner.cpp index f9375ceca2dd..863c4242058d 100644 --- a/testing/gtest/mozilla/GTestRunner.cpp +++ b/testing/gtest/mozilla/GTestRunner.cpp @@ -7,10 +7,6 @@ #include "gtest/gtest.h" #include "mozilla/Attributes.h" #include "mozilla/NullPtr.h" -#ifdef MOZ_CRASHREPORTER -#include "nsICrashReporter.h" -#endif -#include "testing/TestHarness.h" #include "prenv.h" using ::testing::EmptyTestEventListener; @@ -82,31 +78,6 @@ int RunGTestFunc() PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort"); - ScopedXPCOM xpcom("GTestScopedXPCOM"); - -#ifdef MOZ_CRASHREPORTER - nsCOMPtr crashreporter; - char *crashreporterStr = PR_GetEnv("MOZ_CRASHREPORTER"); - if (crashreporterStr && !strcmp(crashreporterStr, "1")) { - //TODO: move this to an even-more-common location to use in all - // C++ unittests - crashreporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1"); - if (crashreporter) { - std::cerr << "Setting up crash reporting" << std::endl; - - nsCOMPtr dirsvc = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); - nsCOMPtr cwd; - nsresult rv = dirsvc->Get(NS_OS_CURRENT_WORKING_DIR, - NS_GET_IID(nsIFile), - getter_AddRefs(cwd)); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - crashreporter->SetEnabled(true); - crashreporter->SetMinidumpPath(cwd); - } - } -#endif - return RUN_ALL_TESTS(); } diff --git a/testing/gtest/rungtests.py b/testing/gtest/rungtests.py deleted file mode 100644 index 803a87be90c0..000000000000 --- a/testing/gtest/rungtests.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python -# -# 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/. - -from __future__ import with_statement -import sys, os, tempfile, shutil -from optparse import OptionParser -import mozprocess, mozinfo, mozlog, mozcrash -from contextlib import contextmanager - -log = mozlog.getLogger('gtests') - -class GTests(object): - # Time (seconds) to wait for test process to complete - TEST_PROC_TIMEOUT = 1200 - # Time (seconds) in which process will be killed if it produces no output. - TEST_PROC_NO_OUTPUT_TIMEOUT = 300 - - def run_gtest(self, prog, xre_path, symbols_path=None): - """ - Run a single C++ unit test program. - - Arguments: - * prog: The path to the test program to run. - * env: The environment to use for running the program. - * symbols_path: A path to a directory containing Breakpad-formatted - symbol files for producing stack traces on crash. - - Return True if the program exits with a zero status, False otherwise. - """ - self.xre_path = xre_path - env = self.build_environment() - basename = os.path.basename(prog) - log.info("Running test %s", basename) - proc = mozprocess.ProcessHandler([prog, "-unittest"], - cwd=os.getcwd(), - env=env) - #TODO: After bug 811320 is fixed, don't let .run() kill the process, - # instead use a timeout in .wait() and then kill to get a stack. - proc.run(timeout=GTests.TEST_PROC_TIMEOUT, - outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) - proc.wait() - if proc.timedOut: - log.testFail("%s | timed out after %d seconds", - basename, GTests.TEST_PROC_TIMEOUT) - return False - if mozcrash.check_for_crashes(os.getcwd(), symbols_path, - test_name=basename): - log.testFail("%s | test crashed", basename) - return False - result = proc.proc.returncode == 0 - if not result: - log.testFail("%s | test failed with return code %d", - basename, proc.proc.returncode) - return result - - def build_core_environment(self, env = {}): - """ - Add environment variables likely to be used across all platforms, including remote systems. - """ - env["MOZILLA_FIVE_HOME"] = self.xre_path - env["MOZ_XRE_DIR"] = self.xre_path - env["XPCOM_DEBUG_BREAK"] = "stack-and-abort" - env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" - env["MOZ_CRASHREPORTER"] = "1" - env["MOZ_RUN_GTEST"] = "1" - # Normally we run with GTest default output, override this to use the TBPL test format. - env["MOZ_TBPL_PARSER"] = "1" - return env - - def build_environment(self): - """ - Create and return a dictionary of all the appropriate env variables and values. - On a remote system, we overload this to set different values and are missing things like os.environ and PATH. - """ - if not os.path.isdir(self.xre_path): - raise Exception("xre_path does not exist: %s", self.xre_path) - env = dict(os.environ) - env = self.build_core_environment(env) - pathvar = "" - if mozinfo.os == "linux": - pathvar = "LD_LIBRARY_PATH" - elif mozinfo.os == "mac": - pathvar = "DYLD_LIBRARY_PATH" - elif mozinfo.os == "win": - pathvar = "PATH" - if pathvar: - if pathvar in env: - env[pathvar] = "%s%s%s" % (self.xre_path, os.pathsep, env[pathvar]) - else: - env[pathvar] = self.xre_path - return env - -class gtestOptions(OptionParser): - def __init__(self): - OptionParser.__init__(self) - self.add_option("--xre-path", - action = "store", type = "string", dest = "xre_path", - default = None, - help = "absolute path to directory containing XRE (probably xulrunner)") - self.add_option("--symbols-path", - action = "store", type = "string", dest = "symbols_path", - default = None, - help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols") - -def main(): - parser = gtestOptions() - options, args = parser.parse_args() - if not args: - print >>sys.stderr, """Usage: %s """ % sys.argv[0] - sys.exit(1) - if not options.xre_path: - print >>sys.stderr, """Error: --xre-path is required""" - sys.exit(1) - prog = os.path.abspath(args[0]) - options.xre_path = os.path.abspath(options.xre_path) - tester = GTests() - try: - result = tester.run_gtest(prog, options.xre_path, options.symbols_path) - except Exception, e: - log.error(str(e)) - result = False - sys.exit(0 if result else 1) - -if __name__ == '__main__': - main() - From 560ba2baa6b7ae5510a3c4d9e77cee8bbd4989f0 Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Fri, 14 Jun 2013 11:34:15 +1200 Subject: [PATCH 091/615] Bug 866567. Mask layers for client container layers. r=mattwoodrow --- gfx/layers/client/ClientContainerLayer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx/layers/client/ClientContainerLayer.h b/gfx/layers/client/ClientContainerLayer.h index a71d2338f232..e44620b6fbfe 100644 --- a/gfx/layers/client/ClientContainerLayer.h +++ b/gfx/layers/client/ClientContainerLayer.h @@ -155,6 +155,10 @@ public: virtual void RenderLayer() { + if (GetMaskLayer()) { + ToClientLayer(GetMaskLayer())->RenderLayer(); + } + // Setup mSupportsComponentAlphaChildren in the same way // that ContainerLayerComposite will do. if (UseIntermediateSurface()) { From d13c6b9f6238c1b56b9a37346f732a3d38af22bf Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Thu, 13 Jun 2013 16:50:46 -0700 Subject: [PATCH 092/615] No bug - Remove from reference files since W3C test suite importer doesn't like it. r=me, DONTBUILD --- .../moz-css21-block-page-break-inside-avoid-8-ref.html | 1 - .../pagination/moz-css21-block-page-break-inside-avoid-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-2-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-5-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-6-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-7-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-8-ref.html | 1 - .../moz-css21-float-page-break-inside-avoid-9-ref.html | 1 - .../moz-css21-inline-page-break-inside-avoid-1-ref.html | 1 - .../moz-css21-rowgroup-page-break-inside-avoid-4-ref.html | 1 - .../moz-css21-rowgroup-page-break-inside-avoid-5-ref.html | 1 - .../moz-css21-rowgroup-page-break-inside-avoid-7-ref.html | 1 - .../moz-css21-rowgroup-page-break-inside-avoid-8-ref.html | 1 - .../moz-css21-table-page-break-inside-avoid-2-ref.html | 1 - .../moz-css21-table-page-break-inside-avoid-3-ref.html | 1 - .../moz-css21-table-page-break-inside-avoid-4-ref.html | 1 - .../moz-css21-table-page-break-inside-avoid-5-ref.html | 1 - .../pagination/moz-css21-table-page-break-inside-avoid-ref.html | 1 - .../moz-multicol3-column-balancing-break-inside-avoid-1-ref.html | 1 - 19 files changed, 19 deletions(-) diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8-ref.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8-ref.html index ced47ef0d96c..bf31a0b710e7 100644 --- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8-ref.html +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-8-ref.html @@ -3,7 +3,6 @@ CSS Test: CSS 2.1 page-break-inside:avoid - + + + + +Mozilla Bug 882653 +

+ +
+
+ + From c82376944c79b2d001e093c837f2632f724afde8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 6 Jun 2013 21:35:53 -0700 Subject: [PATCH 370/615] Bug 634839 (part 2) - Remove more unnecessary #includes from SpiderMonkey. r=jorendorff. --HG-- extra : rebase_source : 32a4ee649fe206ddb966527eb0f6275c076cbea2 --- js/src/assembler/jit/ExecutableAllocator.cpp | 2 -- js/src/assembler/jit/ExecutableAllocator.h | 4 +--- .../jit/ExecutableAllocatorPosix.cpp | 6 +++-- js/src/builtin/Eval.cpp | 6 +++-- js/src/builtin/Intl.cpp | 3 ++- js/src/builtin/Intl.h | 2 ++ js/src/builtin/MapObject.cpp | 1 - js/src/builtin/MapObject.h | 3 --- js/src/builtin/Object.cpp | 4 ++-- js/src/builtin/ParallelArray.cpp | 6 ++--- js/src/builtin/Profilers.cpp | 13 ++++------- js/src/builtin/Profilers.h | 2 +- js/src/ds/LifoAlloc.h | 5 ----- js/src/frontend/BytecodeCompiler.cpp | 3 --- js/src/frontend/BytecodeCompiler.h | 8 ++++++- js/src/frontend/BytecodeEmitter.cpp | 10 --------- js/src/frontend/FoldConstants.cpp | 8 ++----- js/src/frontend/NameFunctions.cpp | 1 - js/src/frontend/ParseMaps-inl.h | 1 - js/src/frontend/ParseMaps.cpp | 1 - js/src/frontend/ParseNode.cpp | 4 ---- js/src/frontend/Parser.cpp | 13 ----------- js/src/frontend/Parser.h | 4 ---- js/src/gc/Iteration.cpp | 1 - js/src/gc/Marking.cpp | 7 ++---- js/src/gc/Memory.cpp | 7 +----- js/src/jscntxtinlines.h | 2 ++ js/src/jskwgen.cpp | 7 ++---- js/src/vm/ArgumentsObject-inl.h | 4 ++-- js/src/vm/ArgumentsObject.cpp | 6 ++--- js/src/vm/ArgumentsObject.h | 6 +++++ js/src/vm/CharacterEncoding.cpp | 3 --- js/src/vm/DateTime.h | 2 -- js/src/vm/Debugger.cpp | 3 --- js/src/vm/Debugger.h | 4 ---- js/src/vm/ForkJoin.cpp | 22 ++++++------------- js/src/vm/GlobalObject.cpp | 1 - js/src/vm/GlobalObject.h | 5 +---- js/src/vm/Interpreter.cpp | 2 -- js/src/vm/Interpreter.h | 1 - js/src/vm/Monitor.h | 5 ----- js/src/vm/ObjectImpl.cpp | 6 ----- js/src/vm/Probes-inl.h | 4 ---- js/src/vm/Probes.cpp | 3 --- js/src/vm/PropertyKey.cpp | 6 ++--- js/src/yarr/PageBlock.h | 3 +-- 46 files changed, 60 insertions(+), 160 deletions(-) diff --git a/js/src/assembler/jit/ExecutableAllocator.cpp b/js/src/assembler/jit/ExecutableAllocator.cpp index 737f6d3667eb..b8ba1eae05ac 100644 --- a/js/src/assembler/jit/ExecutableAllocator.cpp +++ b/js/src/assembler/jit/ExecutableAllocator.cpp @@ -31,8 +31,6 @@ #if ENABLE_ASSEMBLER -#include "prmjtime.h" - namespace JSC { size_t ExecutableAllocator::pageSize = 0; diff --git a/js/src/assembler/jit/ExecutableAllocator.h b/js/src/assembler/jit/ExecutableAllocator.h index 3a756496066c..e3b9026b892e 100644 --- a/js/src/assembler/jit/ExecutableAllocator.h +++ b/js/src/assembler/jit/ExecutableAllocator.h @@ -30,10 +30,8 @@ #include #include "jsalloc.h" -#include "jsapi.h" -#include "jsprvtd.h" -#include "assembler/wtf/Assertions.h" +#include "assembler/wtf/Platform.h" #include "js/HashTable.h" #include "js/Vector.h" diff --git a/js/src/assembler/jit/ExecutableAllocatorPosix.cpp b/js/src/assembler/jit/ExecutableAllocatorPosix.cpp index e334626ccc2f..e92ec809d368 100644 --- a/js/src/assembler/jit/ExecutableAllocatorPosix.cpp +++ b/js/src/assembler/jit/ExecutableAllocatorPosix.cpp @@ -23,13 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "ExecutableAllocator.h" +#include "assembler/jit/ExecutableAllocator.h" #if ENABLE_ASSEMBLER && WTF_OS_UNIX && !WTF_OS_SYMBIAN #include #include -#include + +#include "assembler/wtf/Assertions.h" +#include "assembler/wtf/VMTags.h" namespace JSC { diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index 2d8a26f2571d..f1d653fb6ac5 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -4,12 +4,14 @@ * 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/. */ +#include "builtin/Eval.h" + +#include "mozilla/HashFunctions.h" + #include "jscntxt.h" #include "jsonparser.h" -#include "builtin/Eval.h" #include "frontend/BytecodeCompiler.h" -#include "mozilla/HashFunctions.h" #include "vm/GlobalObject.h" #include "vm/Interpreter-inl.h" diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp index b3046461643d..343821f331dd 100644 --- a/js/src/builtin/Intl.cpp +++ b/js/src/builtin/Intl.cpp @@ -9,6 +9,8 @@ * ECMAScript Internationalization API Specification. */ +#include "builtin/Intl.h" + #include #include "jsapi.h" @@ -16,7 +18,6 @@ #include "jscntxt.h" #include "jsobj.h" -#include "builtin/Intl.h" #include "vm/DateTime.h" #include "vm/GlobalObject.h" #include "vm/Interpreter.h" diff --git a/js/src/builtin/Intl.h b/js/src/builtin/Intl.h index eefec5dbcaaa..d1c8279628b7 100644 --- a/js/src/builtin/Intl.h +++ b/js/src/builtin/Intl.h @@ -7,6 +7,8 @@ #ifndef Intl_h___ #define Intl_h___ +#include "jsapi.h" + #include "js/RootingAPI.h" struct JSContext; diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 43911619f274..d8266a0c3788 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -14,7 +14,6 @@ #include "js/Utility.h" #include "vm/GlobalObject.h" #include "vm/Interpreter.h" -#include "vm/Stack.h" #include "jsobjinlines.h" diff --git a/js/src/builtin/MapObject.h b/js/src/builtin/MapObject.h index 4e58975f61b5..d89fb13449d3 100644 --- a/js/src/builtin/MapObject.h +++ b/js/src/builtin/MapObject.h @@ -7,9 +7,6 @@ #ifndef MapObject_h__ #define MapObject_h__ -#include "mozilla/FloatingPoint.h" -#include "mozilla/GuardObjects.h" - #include "jsapi.h" #include "jscntxt.h" #include "jsobj.h" diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp index 0cb470a5c156..566f4bd1705c 100644 --- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -4,16 +4,16 @@ * 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/. */ +#include "builtin/Object.h" + #include "mozilla/Util.h" #include "jscntxt.h" #include "jsobj.h" -#include "builtin/Object.h" #include "frontend/BytecodeCompiler.h" #include "vm/StringBuffer.h" -#include "jsfuninlines.h" #include "jsobjinlines.h" using namespace js; diff --git a/js/src/builtin/ParallelArray.cpp b/js/src/builtin/ParallelArray.cpp index fb0dab4b58f8..5066bcbc4419 100644 --- a/js/src/builtin/ParallelArray.cpp +++ b/js/src/builtin/ParallelArray.cpp @@ -6,16 +6,14 @@ #include "jsapi.h" #include "jsobj.h" -#include "jsarray.h" #include "builtin/ParallelArray.h" -#include "vm/ForkJoin.h" #include "vm/GlobalObject.h" #include "vm/String.h" -#include "vm/ThreadPool.h" -#include "vm/Interpreter-inl.h" +#include "jsgcinlines.h" +#include "jsobjinlines.h" using namespace js; diff --git a/js/src/builtin/Profilers.cpp b/js/src/builtin/Profilers.cpp index 60c02ec90305..5c061657337e 100644 --- a/js/src/builtin/Profilers.cpp +++ b/js/src/builtin/Profilers.cpp @@ -6,16 +6,10 @@ /* Profiling-related API */ +#include "builtin/Profilers.h" + #include -#include "Profilers.h" -#include "jsapi.h" -#include "jscntxt.h" - -#include "jscntxtinlines.h" -#include "vm/Probes-inl.h" -#include "vm/Stack-inl.h" - #ifdef MOZ_CALLGRIND #include #endif @@ -25,6 +19,8 @@ #include "devtools/Instruments.h" #endif +#include "jscntxtinlines.h" + using namespace js; using mozilla::ArrayLength; @@ -449,7 +445,6 @@ js_DumpCallgrind(const char *outfile) * MOZ_PROFILE_PERF_FLAGS="-e 'foo bar'"). */ -#include #include #include #include diff --git a/js/src/builtin/Profilers.h b/js/src/builtin/Profilers.h index 59c4e992024d..5839ba7c61e7 100644 --- a/js/src/builtin/Profilers.h +++ b/js/src/builtin/Profilers.h @@ -11,7 +11,7 @@ #ifndef Profilers_h___ #define Profilers_h___ -#include "jsapi.h" +#include "jstypes.h" /** * Start any profilers that are available and have been configured on for this diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h index d2a8da9731b5..8b0471df2794 100644 --- a/js/src/ds/LifoAlloc.h +++ b/js/src/ds/LifoAlloc.h @@ -7,10 +7,7 @@ #ifndef LifoAlloc_h__ #define LifoAlloc_h__ -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" -#include "mozilla/GuardObjects.h" #include "mozilla/MemoryChecking.h" #include "mozilla/PodOperations.h" #include "mozilla/TypeTraits.h" @@ -22,8 +19,6 @@ #include "jsutil.h" -#include "js/TemplateLib.h" - namespace js { namespace detail { diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 6abaf1cca6b1..fd042416185b 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -13,14 +13,11 @@ #include "ion/AsmJS.h" #include "vm/GlobalObject.h" -#include "jsinferinlines.h" #include "jsobjinlines.h" #include "frontend/ParseMaps-inl.h" -#include "frontend/ParseNode-inl.h" #include "frontend/Parser-inl.h" #include "frontend/SharedContext-inl.h" -#include "vm/Probes-inl.h" using namespace js; using namespace js::frontend; diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index 35448cee16ec..8db4fea37014 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -8,9 +8,15 @@ #define BytecodeCompiler_h__ #include "jsapi.h" -#include "jsprvtd.h" + +class JSLinearString; namespace js { + +class AutoNameVector; +class LazyScript; +struct SourceCompressionToken; + namespace frontend { JSScript * diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 96b85132cbd4..81862a85aaae 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -14,31 +14,22 @@ #include "mozilla/FloatingPoint.h" #include "mozilla/PodOperations.h" -#ifdef HAVE_MEMORY_H -#include -#endif #include #include "jstypes.h" #include "jsutil.h" -#include "jsprf.h" #include "jsapi.h" #include "jsatom.h" #include "jscntxt.h" -#include "jsversion.h" #include "jsfun.h" #include "jsnum.h" #include "jsopcode.h" #include "jsscript.h" -#include "jsautooplen.h" // generated headers last -#include "ds/LifoAlloc.h" #include "frontend/Parser.h" #include "frontend/TokenStream.h" #include "ion/AsmJS.h" #include "vm/Debugger.h" -#include "vm/RegExpObject.h" -#include "vm/Shape.h" #include "jsatominlines.h" #include "jsobjinlines.h" @@ -47,7 +38,6 @@ #include "frontend/ParseMaps-inl.h" #include "frontend/ParseNode-inl.h" #include "frontend/SharedContext-inl.h" -#include "vm/Shape-inl.h" using namespace js; using namespace js::gc; diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index ea4e1419e9ba..650a739cfc74 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -4,20 +4,16 @@ * 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/. */ +#include "frontend/FoldConstants.h" + #include "mozilla/FloatingPoint.h" #include "jslibmath.h" -#include "frontend/FoldConstants.h" #include "frontend/ParseNode.h" #include "frontend/Parser.h" #include "vm/NumericConversions.h" -#include "jsatominlines.h" - -#include "frontend/Parser-inl.h" -#include "vm/String-inl.h" - using namespace js; using namespace js::frontend; diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index 9f079059237b..9cca6922514c 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -15,7 +15,6 @@ #include "jsfuninlines.h" -#include "vm/String-inl.h" #include "vm/StringBuffer.h" using namespace js; diff --git a/js/src/frontend/ParseMaps-inl.h b/js/src/frontend/ParseMaps-inl.h index 035620b5ffda..406de83de820 100644 --- a/js/src/frontend/ParseMaps-inl.h +++ b/js/src/frontend/ParseMaps-inl.h @@ -9,7 +9,6 @@ #include "jscntxt.h" -#include "frontend/ParseNode.h" /* Need sizeof(js::Definition). */ #include "frontend/ParseMaps.h" namespace js { diff --git a/js/src/frontend/ParseMaps.cpp b/js/src/frontend/ParseMaps.cpp index e7ffef5462ad..332927be4764 100644 --- a/js/src/frontend/ParseMaps.cpp +++ b/js/src/frontend/ParseMaps.cpp @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jscntxt.h" -#include "jscompartment.h" #include "FullParseHandler.h" #include "SyntaxParseHandler.h" diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 2089ec7fd4c4..7319f945f8b4 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -8,10 +8,6 @@ #include "frontend/ParseNode.h" #include "frontend/Parser.h" -#include "jsscriptinlines.h" - -#include "frontend/ParseMaps-inl.h" -#include "frontend/ParseNode-inl.h" #include "frontend/Parser-inl.h" using namespace js; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 32b07164672e..06e4bbcb23d2 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -19,32 +19,20 @@ #include "frontend/Parser.h" -#include -#include - #include "jstypes.h" -#include "jsutil.h" #include "jsapi.h" -#include "jsarray.h" #include "jsatom.h" #include "jscntxt.h" #include "jsversion.h" #include "jsfun.h" -#include "jsgc.h" -#include "jsiter.h" -#include "jslock.h" -#include "jsnum.h" #include "jsobj.h" #include "jsopcode.h" #include "jsscript.h" -#include "jsstr.h" #include "frontend/BytecodeCompiler.h" #include "frontend/FoldConstants.h" #include "frontend/ParseMaps.h" #include "frontend/TokenStream.h" -#include "gc/Marking.h" -#include "vm/Interpreter.h" #include "vm/Shape.h" #include "jsatominlines.h" @@ -57,7 +45,6 @@ #include "frontend/SharedContext-inl.h" #include "vm/NumericConversions.h" -#include "vm/RegExpObject-inl.h" #include "vm/RegExpStatics-inl.h" using namespace js; diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 4f7f361984c2..bd4d8a600bd6 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -10,12 +10,8 @@ /* * JS parser definitions. */ -#include "jsversion.h" #include "jsprvtd.h" #include "jspubtd.h" -#include "jsatom.h" -#include "jsscript.h" -#include "jswin.h" #include "frontend/BytecodeCompiler.h" #include "frontend/FullParseHandler.h" diff --git a/js/src/gc/Iteration.cpp b/js/src/gc/Iteration.cpp index 9421fd9f8882..b69058d63d04 100644 --- a/js/src/gc/Iteration.cpp +++ b/js/src/gc/Iteration.cpp @@ -7,7 +7,6 @@ #include "jsapi.h" #include "jscntxt.h" #include "jsgc.h" -#include "jsprf.h" #include "js/HashTable.h" #include "gc/GCInternals.h" diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index de6ba90068aa..39535157e87d 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -4,18 +4,15 @@ * 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/. */ +#include "gc/Marking.h" + #include "mozilla/DebugOnly.h" -#include "jsprf.h" -#include "jsstr.h" - -#include "gc/Marking.h" #include "ion/IonCode.h" #include "vm/Shape.h" #include "jscompartmentinlines.h" -#include "gc/Nursery-inl.h" #include "vm/Shape-inl.h" #include "vm/String-inl.h" diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp index 399177771718..c121f52f5db9 100644 --- a/js/src/gc/Memory.cpp +++ b/js/src/gc/Memory.cpp @@ -4,13 +4,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "mozilla/Assertions.h" - -#include "jsapi.h" +#include "gc/Memory.h" #include "js/HeapAPI.h" -#include "js/Utility.h" -#include "gc/Memory.h" using namespace js; using namespace js::gc; @@ -307,7 +303,6 @@ gc::GetPageFaultCount() #elif defined(XP_UNIX) || defined(XP_MACOSX) || defined(DARWIN) #include -#include #include #include diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index b7a8a0bc7a9e..0d70eade0b08 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -12,6 +12,8 @@ #include "jscompartment.h" #include "jsfriendapi.h" #include "jsgc.h" +#include "jsiter.h" + #include "builtin/Object.h" // For js::obj_construct #include "frontend/ParseMaps.h" #include "vm/Interpreter.h" diff --git a/js/src/jskwgen.cpp b/js/src/jskwgen.cpp index c5e66707fb98..19d1cd1d7e1e 100644 --- a/js/src/jskwgen.cpp +++ b/js/src/jskwgen.cpp @@ -4,15 +4,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include #include +#include +#include #include #include #include -#include -#include - -#include "jsversion.h" #include "vm/Keywords.h" diff --git a/js/src/vm/ArgumentsObject-inl.h b/js/src/vm/ArgumentsObject-inl.h index 9a9bd505a761..82880151cd5e 100644 --- a/js/src/vm/ArgumentsObject-inl.h +++ b/js/src/vm/ArgumentsObject-inl.h @@ -7,9 +7,9 @@ #ifndef ArgumentsObject_inl_h___ #define ArgumentsObject_inl_h___ -#include "ArgumentsObject.h" +#include "vm/ArgumentsObject.h" -#include "ScopeObject-inl.h" +#include "vm/ScopeObject.h" namespace js { diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index 57e16941b96b..e9163cf22f89 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -4,19 +4,17 @@ * 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/. */ -#include "jsgc.h" +#include "vm/ArgumentsObject-inl.h" + #include "jsinfer.h" #include "vm/GlobalObject.h" -#include "vm/Interpreter.h" #include "vm/Stack.h" -#include "vm/Xdr.h" #include "jsobjinlines.h" #include "gc/Barrier-inl.h" #include "vm/Stack-inl.h" -#include "vm/ArgumentsObject-inl.h" #if defined(JS_ION) #include "ion/IonFrames.h" diff --git a/js/src/vm/ArgumentsObject.h b/js/src/vm/ArgumentsObject.h index 79d0cfbc935c..81dc51b61f99 100644 --- a/js/src/vm/ArgumentsObject.h +++ b/js/src/vm/ArgumentsObject.h @@ -11,6 +11,12 @@ namespace js { +class AbstractFramePtr; + +namespace ion { +class IonJSFrameLayout; +} + /* * ArgumentsData stores the initial indexed arguments provided to the * corresponding and that function itself. It is used to store arguments[i] diff --git a/js/src/vm/CharacterEncoding.cpp b/js/src/vm/CharacterEncoding.cpp index 79266f4fd4db..bc067de24010 100644 --- a/js/src/vm/CharacterEncoding.cpp +++ b/js/src/vm/CharacterEncoding.cpp @@ -8,9 +8,6 @@ #include "js/CharacterEncoding.h" -#include "jscntxtinlines.h" -#include "jsscriptinlines.h" - using namespace JS; Latin1CharsZ diff --git a/js/src/vm/DateTime.h b/js/src/vm/DateTime.h index b0c2a9af8144..965cf2b5eaa4 100644 --- a/js/src/vm/DateTime.h +++ b/js/src/vm/DateTime.h @@ -11,8 +11,6 @@ #include "mozilla/MathAlgorithms.h" #include "mozilla/StandardInteger.h" -#include - #include "NumericConversions.h" namespace js { diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 7c88df9dd075..9cc7c4d42b1c 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -6,8 +6,6 @@ #include "vm/Debugger.h" -#include - #include "jsapi.h" #include "jscntxt.h" #include "jscompartment.h" @@ -24,7 +22,6 @@ #include "jsopcodeinlines.h" #include "gc/FindSCCs-inl.h" -#include "vm/Interpreter-inl.h" #include "vm/Stack-inl.h" using namespace js; diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index dc63a22b6fa1..c7f9927d94c4 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -7,19 +7,15 @@ #ifndef Debugger_h__ #define Debugger_h__ -#include "mozilla/Attributes.h" #include "mozilla/LinkedList.h" #include "jsapi.h" #include "jsclist.h" #include "jscntxt.h" #include "jscompartment.h" -#include "jsgc.h" #include "jsweakmap.h" -#include "jswrapper.h" #include "gc/Barrier.h" -#include "gc/FindSCCs.h" #include "js/HashTable.h" #include "vm/GlobalObject.h" diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index 5d2f6888872f..d7f62403e923 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -5,22 +5,19 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jscntxt.h" -#include "jscompartment.h" - -#include "vm/ForkJoin.h" -#include "vm/Monitor.h" -#include "gc/Marking.h" -#include "ion/BaselineJIT.h" - -#ifdef JS_ION -# include "ion/ParallelArrayAnalysis.h" -#endif #ifdef JS_THREADSAFE # include "prthread.h" # include "prprf.h" #endif +#include "vm/ForkJoin.h" + +#if defined(JS_THREADSAFE) +#include "ion/BaselineJIT.h" +#include "vm/Monitor.h" +#endif + #if defined(DEBUG) && defined(JS_THREADSAFE) && defined(JS_ION) # include "ion/Ion.h" # include "ion/MIR.h" @@ -28,11 +25,6 @@ # include "ion/IonCompartment.h" #endif // DEBUG && THREADSAFE && ION -// For extracting stack extent for each thread. -#include "jsnativestack.h" - -#include "jsinferinlines.h" - #include "vm/Interpreter-inl.h" using namespace js; diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 9e9f6a20c355..71e17c86c22a 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -24,7 +24,6 @@ #include "jsobjinlines.h" #include "vm/GlobalObject-inl.h" -#include "vm/RegExpObject-inl.h" #include "vm/RegExpStatics-inl.h" using namespace js; diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 1fa90af1e530..4e490aa0a272 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -7,19 +7,16 @@ #ifndef GlobalObject_h___ #define GlobalObject_h___ -#include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "jsarray.h" #include "jsbool.h" #include "jsexn.h" #include "jsfun.h" -#include "jsiter.h" #include "jsnum.h" -#include "js/Vector.h" - #include "builtin/RegExp.h" +#include "js/Vector.h" extern JSObject * js_InitObjectClass(JSContext *cx, js::HandleObject obj); diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index ba75d1728e1f..0f9091b019f1 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -14,7 +14,6 @@ #include "mozilla/FloatingPoint.h" #include "mozilla/PodOperations.h" -#include #include #include "jsapi.h" @@ -32,7 +31,6 @@ #include "jspropertycache.h" #include "jsscript.h" #include "jsstr.h" -#include "jsversion.h" #include "builtin/Eval.h" #include "ion/BaselineJIT.h" #include "ion/Ion.h" diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index f46b63d048ac..c7161c4ceef4 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -11,7 +11,6 @@ */ #include "jsprvtd.h" #include "jspubtd.h" -#include "jsopcode.h" #include "vm/Stack.h" diff --git a/js/src/vm/Monitor.h b/js/src/vm/Monitor.h index 9b0144586bde..af31537bc935 100644 --- a/js/src/vm/Monitor.h +++ b/js/src/vm/Monitor.h @@ -7,11 +7,6 @@ #ifndef Monitor_h__ #define Monitor_h__ -#include - -#include "mozilla/DebugOnly.h" - -#include "js/Utility.h" #include "jslock.h" namespace js { diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 8633d5b31140..b937c62d65c0 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -4,21 +4,15 @@ * 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/. */ -#include "mozilla/Assertions.h" -#include "mozilla/Attributes.h" - -#include "js/TemplateLib.h" #include "js/Value.h" #include "vm/Debugger.h" #include "vm/ObjectImpl.h" -#include "jsatominlines.h" #include "jsobjinlines.h" #include "gc/Barrier-inl.h" #include "gc/Marking.h" #include "vm/ObjectImpl-inl.h" -#include "vm/Shape-inl.h" using namespace js; diff --git a/js/src/vm/Probes-inl.h b/js/src/vm/Probes-inl.h index 827247065954..eec9d15b40c7 100644 --- a/js/src/vm/Probes-inl.h +++ b/js/src/vm/Probes-inl.h @@ -10,10 +10,6 @@ #include "vm/Probes.h" #include "jscntxt.h" -#include "jsobj.h" -#include "jsscript.h" - -#include "vm/Stack-inl.h" namespace js { diff --git a/js/src/vm/Probes.cpp b/js/src/vm/Probes.cpp index 2d42597eff67..68d56c519c25 100644 --- a/js/src/vm/Probes.cpp +++ b/js/src/vm/Probes.cpp @@ -7,14 +7,11 @@ #include "Probes-inl.h" #include "jscntxt.h" -#include "jsscript.h" #ifdef INCLUDE_MOZILLA_DTRACE #include "jsscriptinlines.h" #endif -#include "vm/Stack-inl.h" - #define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v)) using namespace js; diff --git a/js/src/vm/PropertyKey.cpp b/js/src/vm/PropertyKey.cpp index 0935cd377c8b..02e33eb3b273 100644 --- a/js/src/vm/PropertyKey.cpp +++ b/js/src/vm/PropertyKey.cpp @@ -6,16 +6,16 @@ /* PropertyKey implementation details. */ -#include "mozilla/Assertions.h" - #include "js/PropertyKey.h" + #include "js/RootingAPI.h" #include "js/Value.h" #include "vm/String.h" -#include "jsinferinlines.h" #include "jsatominlines.h" +#include "vm/String-inl.h" + using namespace js; bool diff --git a/js/src/yarr/PageBlock.h b/js/src/yarr/PageBlock.h index ea98f42f2237..2d58b2ded155 100644 --- a/js/src/yarr/PageBlock.h +++ b/js/src/yarr/PageBlock.h @@ -32,8 +32,7 @@ #include "mozilla/StandardInteger.h" -#include -#include "assembler/wtf/Platform.h" +#include namespace WTF { From dce80b050a561c0f4626f3f1aa902b2018882ee4 Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Fri, 7 Jun 2013 11:02:32 -0700 Subject: [PATCH 371/615] Bug 878614 - Handle subdocument loads/unloads in the inspector actor. r=jwalker --HG-- extra : rebase_source : 08d33498922f3a8b46faa5b1b11c6d8d25de9f17 --- toolkit/devtools/server/actors/inspector.js | 114 +++++++- .../server/tests/mochitest/Makefile.in | 1 + .../test_inspector-mutations-frameload.html | 273 ++++++++++++++++++ 3 files changed, 384 insertions(+), 4 deletions(-) create mode 100644 toolkit/devtools/server/tests/mochitest/test_inspector-mutations-frameload.html diff --git a/toolkit/devtools/server/actors/inspector.js b/toolkit/devtools/server/actors/inspector.js index a03c3fb927c3..eb2c61bb5b52 100644 --- a/toolkit/devtools/server/actors/inspector.js +++ b/toolkit/devtools/server/actors/inspector.js @@ -49,6 +49,8 @@ const {LongStringActor, ShortLongString} = require("devtools/server/actors/strin const promise = require("sdk/core/promise"); const object = require("sdk/util/object"); const events = require("sdk/event/core"); +const { Unknown } = require("sdk/platform/xpcom"); +const { Class } = require("sdk/core/heritage"); Cu.import("resource://gre/modules/Services.jsm"); @@ -570,6 +572,51 @@ let traversalMethod = { } } +/** + * We need to know when a document is navigating away so that we can kill + * the nodes underneath it. We also need to know when a document is + * navigated to so that we can send a mutation event for the iframe node. + * + * The nsIWebProgressListener is the easiest/best way to watch these + * loads that works correctly with the bfcache. + * + * See nsIWebProgressListener for details + * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIWebProgressListener + */ +var ProgressListener = Class({ + extends: Unknown, + interfaces: ["nsIWebProgressListener", "nsISupportsWeakReference"], + + initialize: function(webProgress) { + Unknown.prototype.initialize.call(this); + this.webProgress = webProgress; + this.webProgress.addProgressListener(this); + }, + + destroy: function() { + this.webProgress.removeProgressListener(this); + }, + + onStateChange: makeInfallible(function stateChange(progress, request, flag, status) { + let isWindow = flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW; + let isDocument = flag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT; + if (!(isWindow || isDocument)) { + return; + } + + if (isDocument && (flag & Ci.nsIWebProgressListener.STATE_START)) { + events.emit(this, "windowchange-start", progress.DOMWindow); + } + if (isWindow && (flag & Ci.nsIWebProgressListener.STATE_STOP)) { + events.emit(this, "windowchange-stop", progress.DOMWindow); + } + }), + onProgressChange: function() {}, + onSecurityChange: function() {}, + onStatusChange: function() {}, + onLocationChange: function() {}, +}); + /** * Server side of the DOM walker. */ @@ -587,7 +634,7 @@ var WalkerActor = protocol.ActorClass({ * @param DebuggerServerConnection conn * The server connection. */ - initialize: function(conn, document, options) { + initialize: function(conn, document, webProgress, options) { protocol.Actor.prototype.initialize.call(this, conn); this.rootDoc = document; this._refMap = new Map(); @@ -599,6 +646,13 @@ var WalkerActor = protocol.ActorClass({ this._orphaned = new Set(); this.onMutations = this.onMutations.bind(this); + this.onFrameLoad = this.onFrameLoad.bind(this); + this.onFrameUnload = this.onFrameUnload.bind(this); + + this.progressListener = ProgressListener(webProgress); + + events.on(this.progressListener, "windowchange-start", this.onFrameUnload); + events.on(this.progressListener, "windowchange-stop", this.onFrameLoad); // Ensure that the root document node actor is ready and // managed. @@ -619,6 +673,7 @@ var WalkerActor = protocol.ActorClass({ destroy: function() { protocol.Actor.prototype.destroy.call(this); + this.progressListener.destroy(); this.rootDoc = null; }, @@ -1146,8 +1201,44 @@ var WalkerActor = protocol.ActorClass({ if (needEvent) { events.emit(this, "new-mutations"); } - } + }, + onFrameLoad: function(window) { + let frame = window.frameElement; + let frameActor = this._refMap.get(frame); + if (!frameActor) { + return; + } + let needEvent = this._pendingMutations.length === 0; + this._pendingMutations.push({ + type: "frameLoad", + target: frameActor.actorID, + added: [], + removed: [] + }); + + if (needEvent) { + events.emit(this, "new-mutations"); + } + }, + + onFrameUnload: function(window) { + let doc = window.document; + let documentActor = this._refMap.get(doc); + if (!documentActor) { + return; + } + + let needEvent = this._pendingMutations.length === 0; + this._pendingMutations.push({ + type: "documentUnload", + target: documentActor.actorID + }); + this.releaseNode(documentActor); + if (needEvent) { + events.emit(this, "new-mutations"); + } + } }); /** @@ -1215,7 +1306,7 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { let targetID = change.target; let targetFront = this.get(targetID); if (!targetFront) { - console.error("Got a mutation for an unexpected actor: " + targetID); + console.trace("Got a mutation for an unexpected actor: " + targetID + ", please file a bug on bugzilla.mozilla.org!"); continue; } @@ -1257,6 +1348,20 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { emittedMutation.added = addedFronts; emittedMutation.removed = removedFronts; targetFront._form.numChildren = change.numChildren; + } else if (change.type === "frameLoad") { + // Nothing we need to do here, except verify that we don't have any + // document children, because we should have gotten a documentUnload + // first. + for (let child of targetFront.treeChildren()) { + if (child.nodeType === Ci.nsIDOMNode.DOCUMENT_NODE) { + console.trace("Got an unexpected frameLoad in the inspector, please file a bug on bugzilla.mozilla.org!"); + } + } + } else if (change.type === "documentUnload") { + // We try to give fronts instead of actorIDs, but these fronts need + // to be destroyed now. + emittedMutation.target = targetFront.actorID; + targetFront.destroy(); } else { targetFront.updateMutation(change); } @@ -1310,10 +1415,11 @@ var InspectorActor = protocol.ActorClass({ } else if (tabActor.browser instanceof Ci.nsIDOMElement) { this.window = tabActor.browser.contentWindow; } + this.webProgress = tabActor._tabbrowser; }, getWalker: method(function(options={}) { - return WalkerActor(this.conn, this.window.document, options); + return WalkerActor(this.conn, this.window.document, this.webProgress, options); }, { request: {}, response: { diff --git a/toolkit/devtools/server/tests/mochitest/Makefile.in b/toolkit/devtools/server/tests/mochitest/Makefile.in index 711224f17ce2..0596c87aecde 100644 --- a/toolkit/devtools/server/tests/mochitest/Makefile.in +++ b/toolkit/devtools/server/tests/mochitest/Makefile.in @@ -16,6 +16,7 @@ MOCHITEST_CHROME_FILES = \ inspector-traversal-data.html \ test_inspector-mutations-attr.html \ test_inspector-mutations-childlist.html \ + test_inspector-mutations-frameload.html \ test_inspector-mutations-value.html \ test_inspector-release.html \ test_inspector-traversal.html \ diff --git a/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-frameload.html b/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-frameload.html new file mode 100644 index 000000000000..7402b0c7e990 --- /dev/null +++ b/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-frameload.html @@ -0,0 +1,273 @@ + + + + + + Test for Bug + + + + + + + +Mozilla Bug +Test Document +

+ +
+
+ + From d886ea39e6f8b9d4aa9d25032db3675c0ba1c98f Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Fri, 7 Jun 2013 11:06:39 -0700 Subject: [PATCH 372/615] Bug 878443 - Let the inspector actor expire actors for nodes that are no longer connected to the tree. r=jwalker --HG-- extra : rebase_source : 0f6e871eebfd817b70d8229127b6cd285950ea86 --- toolkit/devtools/server/actors/inspector.js | 31 +++++++++++-- .../test_inspector-mutations-childlist.html | 46 ++++++++++++++++++- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/toolkit/devtools/server/actors/inspector.js b/toolkit/devtools/server/actors/inspector.js index eb2c61bb5b52..991a19d817c4 100644 --- a/toolkit/devtools/server/actors/inspector.js +++ b/toolkit/devtools/server/actors/inspector.js @@ -1118,12 +1118,22 @@ var WalkerActor = protocol.ActorClass({ * removedNodes and addedNodes list, so if the client is interested * in the new set of children it needs to issue a `children` request. */ - getMutations: method(function() { + getMutations: method(function(options={}) { let pending = this._pendingMutations || []; this._pendingMutations = []; + + if (options.cleanup) { + for (let node of this._orphaned) { + this.releaseNode(node); + } + this._orphaned = new Set(); + } + return pending; }, { - request: {}, + request: { + cleanup: Option(0) + }, response: { mutations: RetVal("array:dommutation") } @@ -1245,6 +1255,9 @@ var WalkerActor = protocol.ActorClass({ * Client side of the DOM walker. */ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { + // Set to true if cleanup should be requested after every mutation list. + autoCleanup: true, + initialize: function(client, form) { protocol.Front.prototype.initialize.call(this, client, form); this._orphaned = new Set(); @@ -1298,8 +1311,8 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { /** * Get any unprocessed mutation records and process them. */ - getMutations: protocol.custom(function() { - return this._getMutations().then(mutations => { + getMutations: protocol.custom(function(options={}) { + return this._getMutations(options).then(mutations => { let emitMutations = []; for (let change of mutations) { // The target is only an actorID, get the associated front. @@ -1368,6 +1381,14 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { emitMutations.push(emittedMutation); } + + if (options.cleanup) { + for (let node of this._orphaned) { + node.destroy(); + } + this._orphaned = new Set(); + } + events.emit(this, "mutations", emitMutations); }); }, { @@ -1380,7 +1401,7 @@ var WalkerFront = exports.WalkerFront = protocol.FrontClass(WalkerActor, { */ onMutations: protocol.preEvent("new-mutations", function() { // Fetch and process the mutations. - this.getMutations().then(null, console.error); + this.getMutations({cleanup: this.autoCleanup}).then(null, console.error); }), // XXX hack during transition to remote inspector: get a proper NodeFront diff --git a/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html b/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html index 58891034b0a9..d0b9e796d6a5 100644 --- a/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html +++ b/toolkit/devtools/server/tests/mochitest/test_inspector-mutations-childlist.html @@ -89,6 +89,7 @@ function mutationTest(testSpec) { return function() { setup(() => { promiseDone(loadSelectors(testSpec.load || ["html"]).then(() => { + gWalker.autoCleanup = !!testSpec.autoCleanup; if (testSpec.preCheck) { testSpec.preCheck(); } @@ -122,6 +123,7 @@ function mutationTest(testSpec) { // Verify that our dummy mutation works. addTest(mutationTest({ + autoCleanup: false, postCheck: function(mutations) { is(mutations.length, 0, "Dummy mutation is filtered out."); } @@ -130,6 +132,7 @@ addTest(mutationTest({ // Test a simple move to a different location in the sibling list for the same // parent. addTest(mutationTest({ + autoCleanup: false, load: ["#longlist div"], moves: [ ["#a", "#longlist"] @@ -150,6 +153,7 @@ addTest(mutationTest({ // Test a move to another location that is within our ownership tree. addTest(mutationTest({ + autoCleanup: false, load: ["#longlist div", "#longlist-sibling"], moves: [ ["#a", "#longlist-sibling"] @@ -171,6 +175,7 @@ addTest(mutationTest({ // Move an unseen node with a seen parent into our ownership tree - should generate a // childList pair with no adds or removes. addTest(mutationTest({ + autoCleanup: false, load: ["#longlist"], moves: [ ["#longlist-sibling", "#longlist"] @@ -189,6 +194,7 @@ addTest(mutationTest({ // Move an unseen node with an unseen parent into our ownership tree. Should only // generate one childList mutation with no adds or removes. addTest(mutationTest({ + autoCleanup: false, load: ["#longlist div"], moves: [ ["#longlist-sibling-firstchild", "#longlist"] @@ -203,6 +209,7 @@ addTest(mutationTest({ // Move a node between unseen nodes, should generate no mutations. addTest(mutationTest({ + autoCleanup: false, load: ["html"], moves: [ ["#longlist-sibling", "#longlist"] @@ -212,8 +219,9 @@ addTest(mutationTest({ } })); -// Orphan a node. +// Orphan a node and don't clean it up addTest(mutationTest({ + autoCleanup: false, load: ["#longlist div"], moves: [ ["#longlist", null] @@ -229,8 +237,26 @@ addTest(mutationTest({ } })); +// Orphan a node, and do clean it up. +addTest(mutationTest({ + autoCleanup: true, + load: ["#longlist div"], + moves: [ + ["#longlist", null] + ], + postCheck: function(mutations) { + is(mutations.length, 1, "Should generate one mutation."); + let change = mutations[0]; + is(change.type, "childList", "Should be a childList."); + is(change.removed.length, 1, "Should have removed a child."); + let ownership = clientOwnershipTree(gWalker); + is(ownership.orphaned.length, 0, "Should have no orphaned subtrees."); + } +})); + // Orphan a node by moving it into the tree but out of our visible subtree. addTest(mutationTest({ + autoCleanup: false, load: ["#longlist div"], moves: [ ["#longlist", "#longlist-sibling"] @@ -246,6 +272,24 @@ addTest(mutationTest({ } })); +// Orphan a node by moving it into the tree but out of our visible subtree, and clean it up. +addTest(mutationTest({ + autoCleanup: true, + load: ["#longlist div"], + moves: [ + ["#longlist", "#longlist-sibling"] + ], + postCheck: function(mutations) { + is(mutations.length, 1, "Should generate one mutation."); + let change = mutations[0]; + is(change.type, "childList", "Should be a childList."); + is(change.removed.length, 1, "Should have removed a child."); + let ownership = clientOwnershipTree(gWalker); + is(ownership.orphaned.length, 0, "Should have no orphaned subtrees."); + } +})); + + addTest(function cleanup() { delete gInspectee; delete gWalker; From 56245c0a0c48d4a2d5c265066074930a05e268e9 Mon Sep 17 00:00:00 2001 From: Drew Willcoxon Date: Thu, 13 Jun 2013 19:31:43 -0700 Subject: [PATCH 373/615] Bug 759964 - Part 3 - Add nsIDocShell.allowMedia test. r=test --- content/html/content/test/Makefile.in | 5 + content/html/content/test/allowMedia.sjs | 12 ++ .../html/content/test/test_allowMedia.html | 107 ++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 content/html/content/test/allowMedia.sjs create mode 100644 content/html/content/test/test_allowMedia.html diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index 471e6c2e1ddf..aab783c5825c 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -357,6 +357,11 @@ MOCHITEST_FILES = \ wakelock.ogg \ wakelock.ogv \ test_bug869040.html \ + allowMedia.sjs \ + $(NULL) + +MOCHITEST_CHROME_FILES = \ + test_allowMedia.html \ $(NULL) MOCHITEST_BROWSER_FILES = \ diff --git a/content/html/content/test/allowMedia.sjs b/content/html/content/test/allowMedia.sjs new file mode 100644 index 000000000000..f29619cd89e1 --- /dev/null +++ b/content/html/content/test/allowMedia.sjs @@ -0,0 +1,12 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(req, resp) { + resp.setHeader("Cache-Control", "no-cache", false); + resp.setHeader("Content-Type", "text/plain", false); + + let stateKey = "allowMediaState"; + let state = getState(stateKey); + setState(stateKey, req.queryString ? "FAIL" : ""); + resp.write(state || "PASS"); +} diff --git a/content/html/content/test/test_allowMedia.html b/content/html/content/test/test_allowMedia.html new file mode 100644 index 000000000000..b040470db449 --- /dev/null +++ b/content/html/content/test/test_allowMedia.html @@ -0,0 +1,107 @@ + + + + + + Test for Bug 759964 + + + + + +Mozilla Bug 759964 +

+

+ + From d71663e21ddcbf0d083948d8677beda863acd0a3 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Thu, 13 Jun 2013 19:56:09 -0700 Subject: [PATCH 374/615] Back out b06b9c8b19a3 (bug 873149) for turning every Android mochitest orange --- testing/mochitest/tests/SimpleTest/TestRunner.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/testing/mochitest/tests/SimpleTest/TestRunner.js b/testing/mochitest/tests/SimpleTest/TestRunner.js index d171f46329b7..3934e0f4ca68 100644 --- a/testing/mochitest/tests/SimpleTest/TestRunner.js +++ b/testing/mochitest/tests/SimpleTest/TestRunner.js @@ -84,8 +84,6 @@ TestRunner._expectedMaxAsserts = 0; TestRunner.timeout = 5 * 60 * 1000; // 5 minutes. TestRunner.maxTimeouts = 4; // halt testing after too many timeouts TestRunner.runSlower = false; -TestRunner.slowestTestTime = 0; -TestRunner.slowestTestURL = ""; TestRunner._expectingProcessCrash = false; @@ -347,10 +345,9 @@ TestRunner.runNextTest = function() { SpecialPowers.unregisterProcessCrashObservers(); TestRunner.log("TEST-START | Shutdown"); // used by automation.py - TestRunner.log("Passed: " + $("pass-count").innerHTML); - TestRunner.log("Failed: " + $("fail-count").innerHTML); - TestRunner.log("Todo: " + $("todo-count").innerHTML); - TestRunner.log("Slowest: " + TestRunner.slowestTestTime + 'ms - ' + TestRunner.slowestTestURL); + TestRunner.log("Passed: " + $("pass-count").innerHTML); + TestRunner.log("Failed: " + $("fail-count").innerHTML); + TestRunner.log("Todo: " + $("todo-count").innerHTML); // If we are looping, don't send this cause it closes the log file if (TestRunner.repeat == 0) { TestRunner.log("SimpleTest FINISHED"); @@ -439,10 +436,6 @@ TestRunner.testFinished = function(tests) { TestRunner.log("TEST-END | " + TestRunner.currentTestURL + " | finished in " + runtime + "ms"); - if (TestRunner.slowestTestTime < runtime && TestRunner._timeoutFactor == 1) { - TestRunner.slowestTestTime = runtime; - TestRunner.slowestTestURL = TestRunner.currentTestURL; - } TestRunner.updateUI(tests); From ee9146ca2a232b0f81f70bc412fe975e4c7eff41 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Thu, 13 Jun 2013 21:16:24 -0700 Subject: [PATCH 375/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/29beb399a2a9 Author: Dominic Kuo Desc: Merge pull request #10265 from dominickuo/bug-870320 Bug 870320 - [email] adjust attachments on compose page, r=asutherland ======== https://hg.mozilla.org/integration/gaia-central/rev/25ba62b6d988 Author: Dominic Kuo Desc: Bug 870320 - [email] adjust attachments on compose page --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 9f6273519ce4..481e891bc2b7 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "c38c45692f2d3c03789cda2d12b8203a77660fdd", + "revision": "29beb399a2a902fbd0ea4d72ba7a424468b5e0b7", "repo_path": "/integration/gaia-central" } From 438e131ca1ec0e11e13ab7a58d3cc459714df64e Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Thu, 13 Jun 2013 21:31:21 -0700 Subject: [PATCH 376/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/7da67b95354a Author: mozshiao9 Desc: Merge pull request #10377 from mozshiao9/master_camera_881539 Bug 881539 - [camera] buttons in filmstrip preview mode are white-on-white r=djf ======== https://hg.mozilla.org/integration/gaia-central/rev/f983ab24fcda Author: Mark Shiao Desc: Bug 881539 - [camera] buttons in filmstrip preview mode are white-on-white --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 481e891bc2b7..f8806bc7e54e 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "29beb399a2a902fbd0ea4d72ba7a424468b5e0b7", + "revision": "7da67b95354a92d8b13bb8735eb08e4a3733698b", "repo_path": "/integration/gaia-central" } From ea9c858f402feb1776c8dec15cfd0ae545ad588c Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Thu, 13 Jun 2013 23:31:24 -0700 Subject: [PATCH 377/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/7bfb4efb6e67 Author: huchengtw-moz Desc: Merge pull request #10363 from huchengtw-moz/video/Bug_879362_when_youtube_video_complete_ux_is_ambiguous Bug 879362 - [A/V][video] When YouTube video completes, UX (Pause button...r=@djf ======== https://hg.mozilla.org/integration/gaia-central/rev/a61eb11d24d4 Author: John Hu Desc: Bug 879362 - [A/V][video] When YouTube video completes, UX (Pause button, timer) is ambiguous --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index f8806bc7e54e..8c79c7950b23 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "7da67b95354a92d8b13bb8735eb08e4a3733698b", + "revision": "7bfb4efb6e67c97e1178fa340a17eff63d0c33d4", "repo_path": "/integration/gaia-central" } From 55fb5be4c5b82bbe2327bf4540db82802a834fc9 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 00:46:22 -0700 Subject: [PATCH 378/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/6b0f94b457eb Author: Arthur Chen Desc: Merge pull request #10310 from crh0716/876335 Bug 876335 - Update additional information by HandledCall itself ======== https://hg.mozilla.org/integration/gaia-central/rev/8d16cf3f9444 Author: crh0716 Desc: Bug 876335 - Update additional information by HandledCall itself --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 8c79c7950b23..883519cf930a 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "7bfb4efb6e67c97e1178fa340a17eff63d0c33d4", + "revision": "6b0f94b457ebd9b4f0e82cb2f82dddd6b4f26561", "repo_path": "/integration/gaia-central" } From 28fe0bd054ccd51e8afa0302f6aab6f77b485af4 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 01:01:22 -0700 Subject: [PATCH 379/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/c5cc02744017 Author: Alive.Kuo Desc: Merge pull request #10313 from alivedise/bugzilla/870316/add-vibration-icon-back Bug 870316 - add vibration icon back, r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/80fb6ac6e9d8 Author: Alive Kuo Desc: Bug 870316 - add vibration icon back --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 883519cf930a..7339ef4c9c23 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "6b0f94b457ebd9b4f0e82cb2f82dddd6b4f26561", + "revision": "c5cc027440172d9b2e94bda6d44551049da6ce89", "repo_path": "/integration/gaia-central" } From 37f750c5b86d77ee0ec04225123776081f12c6e7 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 01:01:42 -0700 Subject: [PATCH 380/615] Bumping gaia.json for 4 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/62530b21fd6a Author: Fabien Cazenave Desc: Merge pull request #10384 from fabi1cazenave/wifiDefaultStatus-bug881195 Bug 881195 - [Buri][Setting] WIFI status not correctly displayed at startup, r=kaze ======== https://hg.mozilla.org/integration/gaia-central/rev/cd08bcc4dc2f Author: Fabien Cazenave Desc: Bug 881195 - [Buri][Setting] WIFI status not correctly displayed at startup, r=kaze ======== https://hg.mozilla.org/integration/gaia-central/rev/d17a97015204 Author: Alive.Kuo Desc: Merge pull request #10366 from alivedise/bugzilla/880609_master/wake-lock-after-device-off-and-on Bug 880609 - Request wake lock failed after device is off and on. r=timdream, a=leo+ ======== https://hg.mozilla.org/integration/gaia-central/rev/b4e58e3951eb Author: Alive Kuo Desc: Bug 880609 - Request wake lock failed after device is off and on. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7339ef4c9c23..76f8ecad574d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "c5cc027440172d9b2e94bda6d44551049da6ce89", + "revision": "62530b21fd6a6d9e18d0a6b8053fea916fa14f1c", "repo_path": "/integration/gaia-central" } From 90dd45dc6205c7899ed16f4cd75b44ed5352d8ef Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 02:01:26 -0700 Subject: [PATCH 381/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/f5f12069851f Author: steveck-chung Desc: Merge pull request #10379 from mozshiao9/master_mms_882129 Bug 882129 - [MMS] [UX] Thread view. Spinner inside bubbles should be centered in the 4 rem margin. r=steveck-chung ======== https://hg.mozilla.org/integration/gaia-central/rev/bd5cc2497b70 Author: Mark Shiao Desc: Bug 882129 - [MMS] [UX] Thread view. Spinner inside bubbles should be centered in the 4 rem margin --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 76f8ecad574d..45ea9720ba6c 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "62530b21fd6a6d9e18d0a6b8053fea916fa14f1c", + "revision": "f5f12069851f39b356d9ae276bdd5f17bf44357c", "repo_path": "/integration/gaia-central" } From 4cb53bd0a3c9015c5883760ee26dd45496aad9ce Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 02:16:23 -0700 Subject: [PATCH 382/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/3b558b81bc51 Author: Alive.Kuo Desc: Merge pull request #10152 from leob2g/Bug_878662_Sound_Manager_CEWarningDialog_is_displayed_at_CEWarningVol_+_1 Bug 878662 - [System][Sound Manager] CEWarningDialog is displayed in incorrect timing, r=alive ======== https://hg.mozilla.org/integration/gaia-central/rev/415ee260023a Author: hanj.kim Desc: Bug 878662 - [System][Sound Manager] CEWarningDialog is displayed at CEWarningVol + 1 --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 45ea9720ba6c..df5570404415 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "f5f12069851f39b356d9ae276bdd5f17bf44357c", + "revision": "3b558b81bc51aeb3034c27c498554c8eda352bb0", "repo_path": "/integration/gaia-central" } From a689c3d3b705c05e4055d10f33e59885e51798f9 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 02:31:23 -0700 Subject: [PATCH 383/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/b9e4a914a18a Author: Cristian Rodriguez Desc: Merge pull request #10345 from crdlc/bug-860992 Bug 860992 - [B2G][Contacts] Time stamp of last contact import is not sh... ======== https://hg.mozilla.org/integration/gaia-central/rev/ec99eef7da34 Author: crdlc Desc: Bug 860992 - [B2G][Contacts] Time stamp of last contact import is not shown under Gmail or Hotmail in Contact Settings --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index df5570404415..cdc60817d10a 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "3b558b81bc51aeb3034c27c498554c8eda352bb0", + "revision": "b9e4a914a18a1f518f83181994b3657e9db07e3b", "repo_path": "/integration/gaia-central" } From e1c7a56bb33622dafff3015d52d83cb9e217c8a4 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 02:46:24 -0700 Subject: [PATCH 384/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/49915c05d4ef Author: Timothy Guan-tin Chien Desc: Merge pull request #10388 from timdream/facebook-oauth-fix Bug 882363 - Only enable Facebook functionality if the app id is part of the partner customization, r=@yurenju, a=tef+ ======== https://hg.mozilla.org/integration/gaia-central/rev/debf7ab07509 Author: Francisco Jordano Desc: Bug 882363 - Only enable Facebook functionality if the app id is part of the partner customization. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index cdc60817d10a..32ac95123864 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "b9e4a914a18a1f518f83181994b3657e9db07e3b", + "revision": "49915c05d4efa8b2ec05213daa49db4333a1fbe2", "repo_path": "/integration/gaia-central" } From b9246e8e67662346ee09362ecbc962d2d251edf6 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 03:01:23 -0700 Subject: [PATCH 385/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/ba32214cf08d Author: Cristian Rodriguez Desc: Merge pull request #10385 from crdlc/bug-878422-master Bug 878422 - [Homescreen] Logo stays forever after the quick access bar ... ======== https://hg.mozilla.org/integration/gaia-central/rev/be0f00827d3b Author: crdlc Desc: Bug 878422 - [Homescreen] Logo stays forever after the quick access bar crashed --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 32ac95123864..3a9df6d44b92 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "49915c05d4efa8b2ec05213daa49db4333a1fbe2", + "revision": "ba32214cf08d14d11c01db6b0f0cf6d476b55939", "repo_path": "/integration/gaia-central" } From a0c54ddbbee2c426a2ff8d3b279fab41bd99d0b0 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 05:31:23 -0700 Subject: [PATCH 386/615] Bumping gaia.json for 5 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/4740827fec69 Author: Timothy Guan-tin Chien Desc: Merge pull request #10391 from samjoch/bug-883090-SoundsRemoveStartupShutdownSounds Bug 883090 - [Sounds] Remove startup shutdown sounds and controls, r=@timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/368d15f14a38 Author: Sam Joch Desc: Revert "Merge pull request #9739 from samjoch/bug-812245-SoundShutDownAnimationNeedsASound" This reverts commit e4bf807f22dd5c392d181a216b2e7d4ccd162308, reversing changes made to 644c3a44023d6f8b447b8ad9d57583a1c5f6f723. ======== https://hg.mozilla.org/integration/gaia-central/rev/6427f2157f03 Author: Sam Joch Desc: Revert "Merge pull request #9284 from samjoch/bug-801895-SoundsUpdateBootSound" This reverts commit 0ec2a2558cf41da4a2bf52bf6a550e5e2293602c, reversing changes made to 71385ac3858d720e562f7818b01c9b62698b0478. ======== https://hg.mozilla.org/integration/gaia-central/rev/01437fb355ce Author: Sam Joch Desc: Revert "Merge pull request #10117 from samjoch/bug-877813-SoundsControlToTurnOffBootAndShutdownSoundsIsNeededInSettings" This reverts commit d5d898bb28b5ff931ec2bbdfe0b096b8e45329c9, reversing changes made to b81ceb38b2eb044d8bb8a75baf7f551667e79441. Conflicts: build/settings.py ======== https://hg.mozilla.org/integration/gaia-central/rev/e0886b6948ba Author: Sam Joch Desc: Revert "Bug 879869 - Disable startup/shutdown sound by default r=lightsofapollo" This reverts commit 45b9a38a486c87642052e08c7213c43ac20b222c. Conflicts: build/settings.py --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 3a9df6d44b92..7220c34dc83b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "ba32214cf08d14d11c01db6b0f0cf6d476b55939", + "revision": "4740827fec69f2a87743d0e457a4fd64005fe88b", "repo_path": "/integration/gaia-central" } From 69d8a2927a93b0167fcd630efeeca2115de85841 Mon Sep 17 00:00:00 2001 From: Albert Crespell Date: Sat, 8 Jun 2013 09:57:02 +0200 Subject: [PATCH 387/615] Bug 877607 - Convert sample dates to local timezone when return. r=gene.lian --- dom/network/src/NetworkStatsDB.jsm | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/dom/network/src/NetworkStatsDB.jsm b/dom/network/src/NetworkStatsDB.jsm index a5ec3227b4aa..2ef3bd758aec 100644 --- a/dom/network/src/NetworkStatsDB.jsm +++ b/dom/network/src/NetworkStatsDB.jsm @@ -71,16 +71,16 @@ NetworkStatsDB.prototype = { } }, - convertDate: function convertDate(aDate) { + normalizeDate: function normalizeDate(aDate) { // Convert to UTC according to timezone and // filter timestamp to get SAMPLE_RATE precission - let timestamp = aDate.getTime() - aDate.getTimezoneOffset() * 60 * 1000; + let timestamp = aDate.getTime() - (new Date()).getTimezoneOffset() * 60 * 1000; timestamp = Math.floor(timestamp / SAMPLE_RATE) * SAMPLE_RATE; return timestamp; }, saveStats: function saveStats(stats, aResultCb) { - let timestamp = this.convertDate(stats.date); + let timestamp = this.normalizeDate(stats.date); stats = {connectionType: stats.connectionType, timestamp: timestamp, @@ -234,8 +234,9 @@ NetworkStatsDB.prototype = { }, find: function find(aResultCb, aOptions) { - let start = this.convertDate(aOptions.start); - let end = this.convertDate(aOptions.end); + let offset = (new Date()).getTimezoneOffset() * 60 * 1000; + let start = this.normalizeDate(aOptions.start); + let end = this.normalizeDate(aOptions.end); if (DEBUG) { debug("Find: connectionType:" + aOptions.connectionType + " start: " + start + " end: " + end); @@ -259,14 +260,14 @@ NetworkStatsDB.prototype = { if (cursor){ data.push({ rxBytes: cursor.value.rxBytes, txBytes: cursor.value.txBytes, - date: new Date(cursor.value.timestamp) }); + date: new Date(cursor.value.timestamp + offset) }); cursor.continue(); return; } // When requested samples (start / end) are not in the range of now and // now - VALUES_MAX_LENGTH, fill with empty samples. - this.fillResultSamples(start, end, data); + this.fillResultSamples(start + offset, end + offset, data); txn.result.connectionType = aOptions.connectionType; txn.result.start = aOptions.start; @@ -277,8 +278,9 @@ NetworkStatsDB.prototype = { }, findAll: function findAll(aResultCb, aOptions) { - let start = this.convertDate(aOptions.start); - let end = this.convertDate(aOptions.end); + let offset = (new Date()).getTimezoneOffset() * 60 * 1000; + let start = this.normalizeDate(aOptions.start); + let end = this.normalizeDate(aOptions.end); if (DEBUG) { debug("FindAll: start: " + start + " end: " + end + "\n"); @@ -299,20 +301,21 @@ NetworkStatsDB.prototype = { let request = store.index("timestamp").openCursor(range).onsuccess = function(event) { var cursor = event.target.result; if (cursor) { - if (data.length > 0 && data[data.length - 1].date.getTime() == cursor.value.timestamp) { + if (data.length > 0 && + data[data.length - 1].date.getTime() == cursor.value.timestamp + offset) { // Time is the same, so add values. data[data.length - 1].rxBytes += cursor.value.rxBytes; data[data.length - 1].txBytes += cursor.value.txBytes; } else { data.push({ rxBytes: cursor.value.rxBytes, txBytes: cursor.value.txBytes, - date: new Date(cursor.value.timestamp) }); + date: new Date(cursor.value.timestamp + offset) }); } cursor.continue(); return; } - this.fillResultSamples(start, end, data); + this.fillResultSamples(start + offset, end + offset, data); txn.result.connectionType = aOptions.connectionType; txn.result.start = aOptions.start; From 931d03523d243a0cf420e0e40f69731d36071418 Mon Sep 17 00:00:00 2001 From: Albert Crespell Date: Sat, 8 Jun 2013 09:57:02 +0200 Subject: [PATCH 388/615] Bug 877607 - Tests. r=gene.lian --- dom/network/tests/test_networkstats_basics.html | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dom/network/tests/test_networkstats_basics.html b/dom/network/tests/test_networkstats_basics.html index 958838c65ecd..1f76ba0bb1dc 100644 --- a/dom/network/tests/test_networkstats_basics.html +++ b/dom/network/tests/test_networkstats_basics.html @@ -51,8 +51,9 @@ function test() { } function checkDataDates(data, start, end, sampleRate){ - start = Math.floor(start.getTime() / sampleRate) * sampleRate; - end = Math.floor(end.getTime() / sampleRate) * sampleRate; + var offset = (new Date()).getTimezoneOffset() * 60 * 1000; + start = Math.floor((start.getTime() - offset) / sampleRate) * sampleRate + offset; + end = Math.floor((end.getTime() - offset) / sampleRate) * sampleRate + offset; var counter = 0; var date = start; @@ -149,7 +150,9 @@ var steps = [ // Get samplerate in millis var sampleRate = netStats.sampleRate * 1000; // Get date with samplerate's precision - var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate); + var offset = new Date().getTimezoneOffset() * 60 * 1000; + var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate) + * sampleRate + offset); var startDate = new Date(endDate.getTime() - (sampleRate * diff)); // Calculate the number of samples that should be returned based on the // the samplerate and including final and initial samples. @@ -179,7 +182,9 @@ var steps = [ // Get samplerate in millis var sampleRate = netStats.sampleRate * 1000; // Get date with samplerate's precision - var endDate = new Date(Math.floor(new Date().getTime() / sampleRate) * sampleRate); + var offset = new Date().getTimezoneOffset() * 60 * 1000; + var endDate = new Date(Math.floor((new Date().getTime() - offset) / sampleRate) + * sampleRate + offset); var startDate = new Date(endDate.getTime() - (sampleRate * diff)); // Calculate the number of samples that should be returned based on the // the samplerate and including final and initial samples. From 465d00dbcde99dffda21ab89a6411e7e4c55adfb Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Sat, 15 Jun 2013 10:21:50 -0700 Subject: [PATCH 389/615] Backout revision 5c76c23df424 for bad commit message. --- toolkit/devtools/server/transport.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/toolkit/devtools/server/transport.js b/toolkit/devtools/server/transport.js index 412ddc3ddfc9..b0e598935f0a 100644 --- a/toolkit/devtools/server/transport.js +++ b/toolkit/devtools/server/transport.js @@ -219,17 +219,13 @@ LocalDebuggerTransport.prototype = { } this._deepFreeze(aPacket); let other = this.other; - if (other) { - Services.tm.currentThread.dispatch(makeInfallible(function() { - // Avoid the cost of JSON.stringify() when logging is disabled. - if (wantLogging) { - dumpn("Received packet " + serial + ": " + JSON.stringify(aPacket, null, 2)); - } - if (other.hooks) { - other.hooks.onPacket(aPacket); - } - }, "LocalDebuggerTransport instance's this.other.hooks.onPacket"), 0); - } + Services.tm.currentThread.dispatch(makeInfallible(function() { + // Avoid the cost of JSON.stringify() when logging is disabled. + if (wantLogging) { + dumpn("Received packet " + serial + ": " + JSON.stringify(aPacket, null, 2)); + } + other.hooks.onPacket(aPacket); + }, "LocalDebuggerTransport instance's this.other.hooks.onPacket"), 0); }, /** From b4b2f88a8f34c1c8d58dcbe64406e3412697238f Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Mon, 10 Jun 2013 21:16:47 -0700 Subject: [PATCH 390/615] Bug 881101 - hooks.other is null after shutting down the debugger. r=past --- toolkit/devtools/server/transport.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/toolkit/devtools/server/transport.js b/toolkit/devtools/server/transport.js index b0e598935f0a..412ddc3ddfc9 100644 --- a/toolkit/devtools/server/transport.js +++ b/toolkit/devtools/server/transport.js @@ -219,13 +219,17 @@ LocalDebuggerTransport.prototype = { } this._deepFreeze(aPacket); let other = this.other; - Services.tm.currentThread.dispatch(makeInfallible(function() { - // Avoid the cost of JSON.stringify() when logging is disabled. - if (wantLogging) { - dumpn("Received packet " + serial + ": " + JSON.stringify(aPacket, null, 2)); - } - other.hooks.onPacket(aPacket); - }, "LocalDebuggerTransport instance's this.other.hooks.onPacket"), 0); + if (other) { + Services.tm.currentThread.dispatch(makeInfallible(function() { + // Avoid the cost of JSON.stringify() when logging is disabled. + if (wantLogging) { + dumpn("Received packet " + serial + ": " + JSON.stringify(aPacket, null, 2)); + } + if (other.hooks) { + other.hooks.onPacket(aPacket); + } + }, "LocalDebuggerTransport instance's this.other.hooks.onPacket"), 0); + } }, /** From 29a332adb285fe5043b6f40a020cffda86c89e98 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Fri, 14 Jun 2013 22:37:59 -0700 Subject: [PATCH 391/615] Bug 862199 - double the timeout for test_bug416317-2.html so it doesn't time out on b2g all the time --HG-- extra : rebase_source : a9949516a2abb87b725fc9ac1f56020bf4c213e6 --- content/base/test/test_bug416317-2.html | 1 + 1 file changed, 1 insertion(+) diff --git a/content/base/test/test_bug416317-2.html b/content/base/test/test_bug416317-2.html index 020abf7593d3..943a6e5e80fb 100644 --- a/content/base/test/test_bug416317-2.html +++ b/content/base/test/test_bug416317-2.html @@ -23,6 +23,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=416317 From fab441ed1d380d8809685d1e6181fdfc1cc8c5dd Mon Sep 17 00:00:00 2001 From: Reuben Morais Date: Sat, 15 Jun 2013 22:46:18 -0700 Subject: [PATCH 392/615] No bug - Fix typo in browser-ui.js --- browser/metro/base/content/browser-ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 1d21706378fe..77d49c93dd95 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -574,7 +574,7 @@ var BrowserUI = { this._sslDiskCacheEnabled = Services.prefs.getBoolPref(aData); break; case "browser.urlbar.formatting.enabled": - this._formattingEnabled = Services.prefs.getBookPref(aData); + this._formattingEnabled = Services.prefs.getBoolPref(aData); break; case "browser.urlbar.trimURLs": this._mayTrimURLs = Services.prefs.getBoolPref(aData); From e6783d543630915290b3856fc49c7c2cd2de50b7 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 16 Jun 2013 12:05:39 +0100 Subject: [PATCH 393/615] Bug 876450 - non-scaling-stroke doesn't work with svg.text.css-frames.enabled. r=heycam --HG-- rename : layout/reftests/svg/non-scaling-stroke-03-ref.svg => layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg rename : layout/reftests/svg/non-scaling-stroke-03.svg => layout/reftests/svg/text/dynamic-non-scaling-stroke.svg --- .../text/dynamic-non-scaling-stroke-ref.svg | 11 +++++++ .../svg/text/dynamic-non-scaling-stroke.svg | 31 +++++++++++++++++++ layout/reftests/svg/text/reftest.list | 1 + layout/svg/nsSVGTextFrame2.cpp | 6 ++++ layout/svg/nsSVGUtils.cpp | 16 ++++------ layout/svg/svg.css | 1 + 6 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg create mode 100644 layout/reftests/svg/text/dynamic-non-scaling-stroke.svg diff --git a/layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg b/layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg new file mode 100644 index 000000000000..8fb57ed2c10e --- /dev/null +++ b/layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg @@ -0,0 +1,11 @@ + + + hello there + + hello there + + hello there + diff --git a/layout/reftests/svg/text/dynamic-non-scaling-stroke.svg b/layout/reftests/svg/text/dynamic-non-scaling-stroke.svg new file mode 100644 index 000000000000..ea3ba1990928 --- /dev/null +++ b/layout/reftests/svg/text/dynamic-non-scaling-stroke.svg @@ -0,0 +1,31 @@ + + + Test non-scaling-stroke repainting when ancestor transforms change + + + + + hello there + + hello there + + hello there + + diff --git a/layout/reftests/svg/text/reftest.list b/layout/reftests/svg/text/reftest.list index 8732c244c279..dfa3570de00d 100644 --- a/layout/reftests/svg/text/reftest.list +++ b/layout/reftests/svg/text/reftest.list @@ -157,6 +157,7 @@ HTTP(../..) == simple-transform-rotate.svg simple-transform-rotate-ref.svg == dynamic-font-size-4.svg dynamic-font-size-4-ref.svg == dynamic-dominant-baseline.svg dynamic-dominant-baseline-ref.svg == dynamic-multiple-x.svg dynamic-multiple-x-ref.svg +fuzzy-if(!d2d,14,2) == dynamic-non-scaling-stroke.svg dynamic-non-scaling-stroke-ref.svg # text and masks HTTP(../..) == mask-applied.svg mask-applied-ref.svg diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp index 9c43435236a9..f6597912594f 100644 --- a/layout/svg/nsSVGTextFrame2.cpp +++ b/layout/svg/nsSVGTextFrame2.cpp @@ -3232,6 +3232,12 @@ nsSVGTextFrame2::NotifySVGChanged(uint32_t aFlags) needNewBounds = true; needGlyphMetricsUpdate = true; } + if (StyleSVGReset()->mVectorEffect == + NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE) { + // Stroke currently contributes to our mRect, and our stroke depends on + // the transform to our outer- if |vector-effect:non-scaling-stroke|. + needNewBounds = true; + } } if (needNewBounds) { diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 58b0e1a7d80d..ea4c0df8a8d7 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -1334,13 +1334,13 @@ nsSVGUtils::GetFirstNonAAncestorFrame(nsIFrame* aStartFrame) gfxMatrix nsSVGUtils::GetStrokeTransform(nsIFrame *aFrame) { + if (aFrame->GetContent()->IsNodeOfType(nsINode::eTEXT)) { + aFrame = aFrame->GetParent(); + } + if (aFrame->StyleSVGReset()->mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE) { - if (aFrame->GetContent()->IsNodeOfType(nsINode::eTEXT)) { - aFrame = aFrame->GetParent(); - } - nsIContent *content = aFrame->GetContent(); NS_ABORT_IF_FALSE(content->IsSVG(), "bad cast"); @@ -1732,14 +1732,10 @@ GetStrokeDashData(nsIFrame* aFrame, *aDashOffset = aObjectPaint->GetStrokeDashOffset(); } else { *aDashOffset = nsSVGUtils::CoordToFloat(presContext, - ctx, - style->mStrokeDashoffset); + ctx, + style->mStrokeDashoffset); } - if (content->IsNodeOfType(nsINode::eTEXT)) { - content = content->GetParent(); - } - return (totalLength > 0.0); } diff --git a/layout/svg/svg.css b/layout/svg/svg.css index 96870089942c..03462c8a693f 100644 --- a/layout/svg/svg.css +++ b/layout/svg/svg.css @@ -61,6 +61,7 @@ foreignObject { *|*::-moz-svg-text { unicode-bidi: inherit; + vector-effect: inherit; } *[xml|space=preserve] { From 0c69b8dfcd375123b265355083d7430c92e49064 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Sun, 16 Jun 2013 07:12:20 -0600 Subject: [PATCH 394/615] Bug 883623 - Check free variables within eval'ed code before restarting processing of top level statements in the eval. --- js/src/frontend/BytecodeCompiler.cpp | 91 ++++++++++++++---------- js/src/jit-test/tests/basic/bug883623.js | 7 ++ 2 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug883623.js diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 588f46897187..138551a93864 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -76,6 +76,52 @@ CheckArgumentsWithinEval(JSContext *cx, Parser &parser, Handle return true; } +static bool +MaybeCheckEvalFreeVariables(JSContext *cx, HandleScript evalCaller, HandleObject scopeChain, + Parser &parser, + ParseContext &pc) +{ + if (!evalCaller || !evalCaller->functionOrCallerFunction()) + return true; + + // Watch for uses of 'arguments' within the evaluated script, both as + // free variables and as variables redeclared with 'var'. + RootedFunction fun(cx, evalCaller->functionOrCallerFunction()); + HandlePropertyName arguments = cx->names().arguments; + for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) { + if (r.front().key() == arguments) { + if (!CheckArgumentsWithinEval(cx, parser, fun)) + return false; + } + } + for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) { + if (r.front().key() == arguments) { + if (!CheckArgumentsWithinEval(cx, parser, fun)) + return false; + } + } + + // If the eval'ed script contains any debugger statement, force construction + // of arguments objects for the caller script and any other scripts it is + // transitively nested inside. The debugger can access any variable on the + // scope chain. + if (pc.sc->hasDebuggerStatement()) { + RootedObject scope(cx, scopeChain); + while (scope->isScope() || scope->isDebugScope()) { + if (scope->isCall() && !scope->asCall().isForEval()) { + RootedScript script(cx, scope->asCall().callee().nonLazyScript()); + if (script->argumentsHasVarBinding()) { + if (!JSScript::argumentsOptimizationFailed(cx, script)) + return false; + } + } + scope = scope->enclosingScope(); + } + } + + return true; +} + inline bool CanLazilyParse(JSContext *cx, const CompileOptions &options) { @@ -235,6 +281,12 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, // be ambiguous. parser.clearAbortedSyntaxParse(); parser.tokenStream.seek(pos); + + // Destroying the parse context will destroy its free + // variables, so check if any deoptimization is needed. + if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref())) + return NULL; + pc.destroy(); pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0); @@ -265,44 +317,11 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain, parser.handler.freeTree(pn); } - if (!SetSourceMap(cx, parser.tokenStream, ss, script)) + if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, pc.ref())) return NULL; - if (evalCaller && evalCaller->functionOrCallerFunction()) { - // Watch for uses of 'arguments' within the evaluated script, both as - // free variables and as variables redeclared with 'var'. - RootedFunction fun(cx, evalCaller->functionOrCallerFunction()); - HandlePropertyName arguments = cx->names().arguments; - for (AtomDefnRange r = pc.ref().lexdeps->all(); !r.empty(); r.popFront()) { - if (r.front().key() == arguments) { - if (!CheckArgumentsWithinEval(cx, parser, fun)) - return NULL; - } - } - for (AtomDefnListMap::Range r = pc.ref().decls().all(); !r.empty(); r.popFront()) { - if (r.front().key() == arguments) { - if (!CheckArgumentsWithinEval(cx, parser, fun)) - return NULL; - } - } - - // If the eval'ed script contains any debugger statement, force construction - // of arguments objects for the caller script and any other scripts it is - // transitively nested inside. - if (pc.ref().sc->hasDebuggerStatement()) { - RootedObject scope(cx, scopeChain); - while (scope->isScope() || scope->isDebugScope()) { - if (scope->isCall() && !scope->asCall().isForEval()) { - RootedScript script(cx, scope->asCall().callee().nonLazyScript()); - if (script->argumentsHasVarBinding()) { - if (!JSScript::argumentsOptimizationFailed(cx, script)) - return NULL; - } - } - scope = scope->enclosingScope(); - } - } - } + if (!SetSourceMap(cx, parser.tokenStream, ss, script)) + return NULL; /* * Nowadays the threaded interpreter needs a stop instruction, so we diff --git a/js/src/jit-test/tests/basic/bug883623.js b/js/src/jit-test/tests/basic/bug883623.js new file mode 100644 index 000000000000..d5599fb1f9f4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug883623.js @@ -0,0 +1,7 @@ + +(function() { + eval("\ + arguments.valueOf();\ + with (function(){}){};\ + "); +})() \ No newline at end of file From 17af22f50a37ae18c297985c5cd1f49fc24f1fd1 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Sun, 16 Jun 2013 10:24:45 -0600 Subject: [PATCH 395/615] Bug 883630 - Watch for lazy functions when iterating inline Ion frames, clean up methods for accessing function scripts. --- js/src/ion/AsmJS.cpp | 5 ++++- js/src/ion/IonFrames.cpp | 7 ++++++- js/src/jscompartment.cpp | 11 +++++++---- js/src/jsfun.h | 40 ++++++++++++++++++++++------------------ js/src/jsfuninlines.h | 19 +++++++++++++++++++ js/src/shell/js.cpp | 25 +++++++++++++++---------- 6 files changed, 73 insertions(+), 34 deletions(-) diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index c54d503f36fc..6a1a15927fd8 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -5316,7 +5316,10 @@ GenerateEntries(ModuleCompiler &m) static inline bool TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv) { - JSScript *script = exitDatum->fun->maybeNonLazyScript(); + if (!exitDatum->fun->hasScript()) + return true; + + JSScript *script = exitDatum->fun->nonLazyScript(); if (!script) return true; diff --git a/js/src/ion/IonFrames.cpp b/js/src/ion/IonFrames.cpp index e6231e26c79d..310e1870303d 100644 --- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -1267,7 +1267,12 @@ InlineFrameIteratorMaybeGC::findNextFrame() si_.nextFrame(); callee_ = funval.toObject().toFunction(); - script_ = callee_->nonLazyScript(); + + // Inlined functions may be clones that still point to the lazy script + // for the executed script, if they are clones. The actual script + // exists though, just make sure the function points to it. + script_ = callee_->getExistingScript(); + pc_ = script_->code + si_.pcOffset(); } diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 300e5b9448ca..45cb0803d0ba 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -634,8 +634,8 @@ CreateLazyScriptsForCompartment(JSContext *cx) if (obj->compartment() == cx->compartment() && obj->isFunction()) { JSFunction *fun = obj->toFunction(); if (fun->isInterpretedLazy()) { - LazyScript *lazy = fun->lazyScript(); - if (lazy->sourceObject() && !lazy->maybeScript()) { + LazyScript *lazy = fun->lazyScriptOrNull(); + if (lazy && lazy->sourceObject() && !lazy->maybeScript()) { if (!lazyFunctions.append(fun)) return false; } @@ -666,8 +666,11 @@ CreateLazyScriptsForCompartment(JSContext *cx) JSObject *obj = i.get(); if (obj->compartment() == cx->compartment() && obj->isFunction()) { JSFunction *fun = obj->toFunction(); - if (fun->isInterpretedLazy() && fun->lazyScript()->maybeScript()) - JS_ALWAYS_TRUE(fun->getOrCreateScript(cx)); + if (fun->isInterpretedLazy()) { + LazyScript *lazy = fun->lazyScriptOrNull(); + if (lazy && lazy->maybeScript()) + fun->getExistingScript(); + } } } diff --git a/js/src/jsfun.h b/js/src/jsfun.h index e5d060a0e831..1ededa6e8366 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -208,6 +208,27 @@ class JSFunction : public JSObject static bool createScriptForLazilyInterpretedFunction(JSContext *cx, js::HandleFunction fun); + // Function Scripts + // + // Interpreted functions may either have an explicit JSScript (hasScript()) + // or be lazy with sufficient information to construct the JSScript if + // necessary (isInterpretedLazy()). + // + // A lazy function will have a LazyScript if the function came from parsed + // source, or NULL if the function is a clone of a self hosted function. + // + // There are several methods to get the script of an interpreted function: + // + // - For all interpreted functions, getOrCreateScript() will get the + // JSScript, delazifying the function if necessary. This is the safest to + // use, but has extra checks, requires a cx and may trigger a GC. + // + // - For functions which may have a LazyScript but whose JSScript is known + // to exist, getExistingScript() will get the script and delazify the + // function if necessary. + // + // - For functions known to have a JSScript, nonLazyScript() will get it. + JSScript *getOrCreateScript(JSContext *cx) { JS_ASSERT(isInterpreted()); JS_ASSERT(cx); @@ -222,35 +243,18 @@ class JSFunction : public JSObject return u.i.s.script_; } - static bool maybeGetOrCreateScript(JSContext *cx, js::HandleFunction fun, - js::MutableHandle script) - { - if (fun->isNative()) { - script.set(NULL); - return true; - } - script.set(fun->getOrCreateScript(cx)); - return fun->hasScript(); - } + inline JSScript *getExistingScript(); JSScript *nonLazyScript() const { JS_ASSERT(hasScript()); return JS::HandleScript::fromMarkedLocation(&u.i.s.script_); } - JSScript *maybeNonLazyScript() const { - return hasScript() ? nonLazyScript() : NULL; - } - js::HeapPtrScript &mutableScript() { JS_ASSERT(isInterpreted()); return *(js::HeapPtrScript *)&u.i.s.script_; } - // A lazily interpreted function will have an associated LazyScript if the - // script has not yet been parsed. For functions whose scripts are lazily - // cloned from self hosted code, there is no LazyScript. - js::LazyScript *lazyScript() const { JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_); return u.i.s.lazy_; diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 17c5508d83aa..a114029339ea 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -223,6 +223,25 @@ CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObjec } /* namespace js */ +inline JSScript * +JSFunction::getExistingScript() +{ + JS_ASSERT(isInterpreted()); + if (isInterpretedLazy()) { + js::LazyScript *lazy = lazyScript(); + JS_ASSERT(lazy->maybeScript()); + + if (zone()->needsBarrier()) + js::LazyScript::writeBarrierPre(lazy); + + flags &= ~INTERPRETED_LAZY; + flags |= INTERPRETED; + initScript(lazy->maybeScript()); + } + JS_ASSERT(hasScript()); + return u.i.s.script_; +} + inline void JSFunction::setScript(JSScript *script_) { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 18a174ff95c6..e6d447b3e576 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1444,11 +1444,15 @@ ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL) else break; } - - RootedScript script(cx); - JSFunction::maybeGetOrCreateScript(cx, fun, &script); - if (!script) + + if (!fun->isInterpreted()) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_SCRIPTS_ONLY); + return NULL; + } + + JSScript *script = fun->getOrCreateScript(cx); + if (!script) + return NULL; if (fun && funp) *funp = fun; @@ -1891,13 +1895,14 @@ DisassembleScript(JSContext *cx, HandleScript script, HandleFunction fun, bool l JSObject *obj = objects->vector[i]; if (obj->isFunction()) { Sprint(sp, "\n"); - RootedFunction f(cx, obj->toFunction()); - RootedScript script(cx); - JSFunction::maybeGetOrCreateScript(cx, f, &script); - if (!script) + RootedFunction fun(cx, obj->toFunction()); + if (fun->isInterpreted()) { + RootedScript script(cx, fun->getOrCreateScript(cx)); + if (!script || !DisassembleScript(cx, script, fun, lines, recursive, sp)) + return false; + } else { Sprint(sp, "[native code]\n"); - else if (!DisassembleScript(cx, script, fun, lines, recursive, sp)) - return false; + } } } } From 3444a4cb1ac4677fb8b15473c2624f66ef79e5e6 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Sun, 16 Jun 2013 10:37:56 -0600 Subject: [PATCH 396/615] Bug 883562 - Check for lazy functions when bailing out from Ion to Baseline. --- js/src/ion/BaselineBailouts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/ion/BaselineBailouts.cpp b/js/src/ion/BaselineBailouts.cpp index edb45e70406c..d85b5dbf7d46 100644 --- a/js/src/ion/BaselineBailouts.cpp +++ b/js/src/ion/BaselineBailouts.cpp @@ -1060,7 +1060,7 @@ ion::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt RootedFunction callee(cx, iter.maybeCallee()); if (callee) { IonSpew(IonSpew_BaselineBailouts, " Callee function (%s:%u)", - callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno); + callee->getExistingScript()->filename(), callee->getExistingScript()->lineno); } else { IonSpew(IonSpew_BaselineBailouts, " No callee!"); } @@ -1098,7 +1098,7 @@ ion::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt caller = scr; callerPC = callPC; fun = nextCallee; - scr = fun->nonLazyScript(); + scr = fun->getExistingScript(); snapIter.nextFrame(); frameNo++; From d1b9bd138f36c053b9c451845da139073dc017ed Mon Sep 17 00:00:00 2001 From: Douglas Crosher Date: Fri, 14 Jun 2013 21:16:55 +1000 Subject: [PATCH 397/615] Bug 883108 - Asm.js: re-enable Ion Spew, r=nmatsakis --- js/src/ion/IonSpewer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/src/ion/IonSpewer.cpp b/js/src/ion/IonSpewer.cpp index 5c4ac32e609c..a2b7f88dce59 100644 --- a/js/src/ion/IonSpewer.cpp +++ b/js/src/ion/IonSpewer.cpp @@ -160,8 +160,6 @@ IonSpewer::spewPass(const char *pass) { if (!isSpewingFunction()) return; - if (!GetIonContext()->cx) - return; c1Spewer.spewPass(pass); jsonSpewer.beginPass(pass); @@ -175,8 +173,6 @@ IonSpewer::spewPass(const char *pass, LinearScanAllocator *ra) { if (!isSpewingFunction()) return; - if (!GetIonContext()->cx) - return; c1Spewer.spewPass(pass); c1Spewer.spewIntervals(pass, ra); From 98a01c5b49d87d35e0039cacb1f897feaa2e003c Mon Sep 17 00:00:00 2001 From: Douglas Crosher Date: Fri, 14 Jun 2013 21:03:19 +1000 Subject: [PATCH 398/615] Bug 883106 - IonMonkey: avoid emitting zero length perf Jit map entries, r=nmatsakis --- js/src/ion/PerfSpewer.cpp | 70 ++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/js/src/ion/PerfSpewer.cpp b/js/src/ion/PerfSpewer.cpp index 368bea73a310..8229a1e98ff2 100644 --- a/js/src/ion/PerfSpewer.cpp +++ b/js/src/ion/PerfSpewer.cpp @@ -24,29 +24,32 @@ using namespace js::ion; #define PERF_MODE_FUNC 2 #define PERF_MODE_BLOCK 3 -static bool PerfChecked = false; - #ifdef JS_ION_PERF static uint32_t PerfMode = 0; +static bool PerfChecked = false; + void js::ion::CheckPerf() { - const char *env = getenv("IONPERF"); - if (env == NULL) { - PerfMode = PERF_MODE_NONE; - } else if (!strcmp(env, "none")) { - PerfMode = PERF_MODE_NONE; - } else if (!strcmp(env, "block")) { - PerfMode = PERF_MODE_BLOCK; - } else if (!strcmp(env, "func")) { - PerfMode = PERF_MODE_FUNC; - } else { - fprintf(stderr, "Use IONPERF=func to record at basic block granularity\n"); - fprintf(stderr, "Use IONPERF=block to record at basic block granularity\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Be advised that using IONPERF will cause all scripts\n"); - fprintf(stderr, "to be leaked.\n"); - exit(0); + if (!PerfChecked) { + const char *env = getenv("IONPERF"); + if (env == NULL) { + PerfMode = PERF_MODE_NONE; + } else if (!strcmp(env, "none")) { + PerfMode = PERF_MODE_NONE; + } else if (!strcmp(env, "block")) { + PerfMode = PERF_MODE_BLOCK; + } else if (!strcmp(env, "func")) { + PerfMode = PERF_MODE_FUNC; + } else { + fprintf(stderr, "Use IONPERF=func to record at basic block granularity\n"); + fprintf(stderr, "Use IONPERF=block to record at basic block granularity\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Be advised that using IONPERF will cause all scripts\n"); + fprintf(stderr, "to be leaked.\n"); + exit(0); + } + PerfChecked = true; } } @@ -135,13 +138,16 @@ PerfSpewer::writeProfile(JSScript *script, uint32_t thisFunctionIndex = nextFunctionIndex++; if (PerfFuncEnabled()) { - fprintf(fp_, - "%lx %lx %s:%d: Func%02d\n", - reinterpret_cast(code->raw()), - (unsigned long) code->instructionsSize(), - script->filename(), - script->lineno, - thisFunctionIndex); + unsigned long size = (unsigned long) code->instructionsSize(); + if (size > 0) { + fprintf(fp_, + "%lx %lx %s:%d: Func%02d\n", + reinterpret_cast(code->raw()), + size, + script->filename(), + script->lineno, + thisFunctionIndex); + } } else if (PerfBlockEnabled()) { uintptr_t funcStart = uintptr_t(code->raw()); uintptr_t funcEnd = funcStart + code->instructionsSize(); @@ -163,11 +169,15 @@ PerfSpewer::writeProfile(JSScript *script, } cur = blockEnd; - fprintf(fp_, - "%lx %lx %s:%d:%d: Func%02d-Block%d\n", - blockStart, blockEnd - blockStart, - r.filename, r.lineNumber, r.columnNumber, - thisFunctionIndex, r.id); + unsigned long size = blockEnd - blockStart; + + if (size > 0) { + fprintf(fp_, + "%lx %lx %s:%d:%d: Func%02d-Block%d\n", + blockStart, size, + r.filename, r.lineNumber, r.columnNumber, + thisFunctionIndex, r.id); + } } // Any stuff after the basic blocks is presumably OOL code, From 459c46a60d64bc5e0ee90133247a10590d6f9685 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Wed, 12 Jun 2013 14:26:25 +1200 Subject: [PATCH 399/615] Bug 812881 - Backout due to devices no longer crashing - r=bjacob a=akeybl --- widget/android/GfxInfo.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/widget/android/GfxInfo.cpp b/widget/android/GfxInfo.cpp index b4e6bfa14f5a..7884a80874b3 100644 --- a/widget/android/GfxInfo.cpp +++ b/widget/android/GfxInfo.cpp @@ -472,11 +472,6 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature, // All Sony devices (Bug 845734) bool isBlocklisted = - cModel.Find("SCH-I535", true) != -1 || - cModel.Find("SGH-I747", true) != -1 || - cModel.Find("SGH-T999", true) != -1 || - cModel.Find("SPH-L710", true) != -1 || - cModel.Find("GT-I8190", true) != -1 || cModel.Find("GT-P3100", true) != -1 || cModel.Find("GT-P3110", true) != -1 || cModel.Find("GT-P3113", true) != -1 || From 09024c54897f8cc7d98880af07d97cb4417f8c44 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 18 Jun 2013 21:48:45 +0300 Subject: [PATCH 400/615] Bug 847611 - Paris bindings for autogenerated events, r=peterv --- dom/base/nsWrapperCache.h | 2 +- dom/bindings/Bindings.conf | 1 + .../tests/approved/test_interfaces.html.json | 6 - .../Ms2ger/test_missing_arguments.html.json | 3 +- dom/interfaces/events/nsIDOMCloseEvent.idl | 2 +- .../events/nsIDOMDeviceLightEvent.idl | 2 +- .../interfaces/nsIDOMCFStateChangeEvent.idl | 2 +- .../interfaces/nsIDOMUSSDReceivedEvent.idl | 2 +- dom/webidl/BlobEvent.webidl | 17 + dom/webidl/BluetoothDeviceEvent.webidl | 17 + dom/webidl/CFStateChangeEvent.webidl | 30 +- dom/webidl/CallEvent.webidl | 17 + dom/webidl/CloseEvent.webidl | 35 ++ dom/webidl/CustomEvent.webidl | 20 +- dom/webidl/DOMTransactionEvent.webidl | 23 + dom/webidl/DataErrorEvent.webidl | 16 + dom/webidl/DeviceLightEvent.webidl | 16 + dom/webidl/DeviceOrientationEvent.webidl | 32 ++ dom/webidl/DeviceProximityEvent.webidl | 20 + dom/webidl/DeviceStorageChangeEvent.webidl | 18 + dom/webidl/DummyBinding.webidl | 2 - dom/webidl/ElementReplaceEvent.webidl | 23 + dom/webidl/GamepadAxisMoveEvent.webidl | 18 + dom/webidl/GamepadButtonEvent.webidl | 16 + dom/webidl/GamepadEvent.webidl | 16 + dom/webidl/HashChangeEvent.webidl | 26 + dom/webidl/IccCardLockErrorEvent.webidl | 18 + dom/webidl/MozApplicationEvent.webidl | 17 + dom/webidl/MozCellBroadcastEvent.webidl | 17 + dom/webidl/MozContactChangeEvent.webidl | 18 + dom/webidl/MozMmsEvent.webidl | 17 + dom/webidl/MozSettingsEvent.webidl | 19 + dom/webidl/MozSmsEvent.webidl | 17 + dom/webidl/MozVoicemailEvent.webidl | 17 + dom/webidl/MozWifiConnectionInfoEvent.webidl | 25 + dom/webidl/MozWifiStatusChangeEvent.webidl | 19 + dom/webidl/PageTransitionEvent.webidl | 23 + dom/webidl/PopStateEvent.webidl | 24 + dom/webidl/PopupBlockedEvent.webidl | 33 ++ dom/webidl/ProgressEvent.webidl | 20 + dom/webidl/SmartCardEvent.webidl | 16 + dom/webidl/SpeechRecognitionError.webidl | 27 + dom/webidl/SpeechRecognitionEvent.webidl | 23 + dom/webidl/SpeechSynthesisEvent.webidl | 14 +- dom/webidl/StorageEvent.webidl | 42 ++ dom/webidl/StyleRuleChangeEvent.webidl | 19 + ...tyleSheetApplicableStateChangeEvent.webidl | 18 + dom/webidl/StyleSheetChangeEvent.webidl | 18 + dom/webidl/USSDReceivedEvent.webidl | 12 +- dom/webidl/UserProximityEvent.webidl | 16 + dom/webidl/WebIDL.mk | 66 ++- js/xpconnect/src/Makefile.in | 16 +- js/xpconnect/src/event_impl_gen.conf.in | 9 + js/xpconnect/src/event_impl_gen.py | 543 +++++++++++++++--- 54 files changed, 1401 insertions(+), 104 deletions(-) create mode 100644 dom/webidl/BlobEvent.webidl create mode 100644 dom/webidl/BluetoothDeviceEvent.webidl create mode 100644 dom/webidl/CallEvent.webidl create mode 100644 dom/webidl/CloseEvent.webidl create mode 100644 dom/webidl/DOMTransactionEvent.webidl create mode 100644 dom/webidl/DataErrorEvent.webidl create mode 100644 dom/webidl/DeviceLightEvent.webidl create mode 100644 dom/webidl/DeviceOrientationEvent.webidl create mode 100644 dom/webidl/DeviceProximityEvent.webidl create mode 100644 dom/webidl/DeviceStorageChangeEvent.webidl create mode 100644 dom/webidl/ElementReplaceEvent.webidl create mode 100644 dom/webidl/GamepadAxisMoveEvent.webidl create mode 100644 dom/webidl/GamepadButtonEvent.webidl create mode 100644 dom/webidl/GamepadEvent.webidl create mode 100644 dom/webidl/HashChangeEvent.webidl create mode 100644 dom/webidl/IccCardLockErrorEvent.webidl create mode 100644 dom/webidl/MozApplicationEvent.webidl create mode 100644 dom/webidl/MozCellBroadcastEvent.webidl create mode 100644 dom/webidl/MozContactChangeEvent.webidl create mode 100644 dom/webidl/MozMmsEvent.webidl create mode 100644 dom/webidl/MozSettingsEvent.webidl create mode 100644 dom/webidl/MozSmsEvent.webidl create mode 100644 dom/webidl/MozVoicemailEvent.webidl create mode 100644 dom/webidl/MozWifiConnectionInfoEvent.webidl create mode 100644 dom/webidl/MozWifiStatusChangeEvent.webidl create mode 100644 dom/webidl/PageTransitionEvent.webidl create mode 100644 dom/webidl/PopStateEvent.webidl create mode 100644 dom/webidl/PopupBlockedEvent.webidl create mode 100644 dom/webidl/ProgressEvent.webidl create mode 100644 dom/webidl/SmartCardEvent.webidl create mode 100644 dom/webidl/SpeechRecognitionError.webidl create mode 100644 dom/webidl/SpeechRecognitionEvent.webidl create mode 100644 dom/webidl/StorageEvent.webidl create mode 100644 dom/webidl/StyleRuleChangeEvent.webidl create mode 100644 dom/webidl/StyleSheetApplicableStateChangeEvent.webidl create mode 100644 dom/webidl/StyleSheetChangeEvent.webidl create mode 100644 dom/webidl/UserProximityEvent.webidl diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index f7e1a513dd96..44d3c054afcd 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -123,7 +123,7 @@ public: void SetIsDOMBinding() { - MOZ_ASSERT(!mWrapper && !GetWrapperFlags(), + MOZ_ASSERT(!mWrapper && !(GetWrapperFlags() & ~WRAPPER_IS_DOM_BINDING), "This flag should be set before creating any wrappers."); SetWrapperFlags(WRAPPER_IS_DOM_BINDING); } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index c035cd57b2cc..6059f3ccc872 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1620,6 +1620,7 @@ addExternalIface('Counter') addExternalIface('CSSRule') addExternalIface('DeviceAcceleration', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True) addExternalIface('DeviceRotationRate', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True) +addExternalIface('mozIDOMApplication', nativeType='mozIDOMApplication', headerFile='nsIDOMApplicationRegistry.h') addExternalIface('CSSRuleList') addExternalIface('DOMStringList') addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel') diff --git a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json index b2dc56fd4b1e..ff304deff331 100644 --- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json +++ b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json @@ -34,12 +34,6 @@ "Event interface: new Event(\"foo\") must have own property \"isTrusted\"": true, "Event interface: new Event(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true, "CustomEvent interface: existence and properties of interface object": true, - "CustomEvent interface constructor": true, - "CustomEvent interface: existence and properties of interface prototype object": true, - "CustomEvent interface: existence and properties of interface prototype object's \"constructor\" property": true, - "CustomEvent interface: attribute detail": true, - "Stringification of new CustomEvent(\"foo\")": "debug", - "CustomEvent interface: calling initCustomEvent(DOMString,boolean,boolean,any) on new CustomEvent(\"foo\") with too few arguments must throw TypeError": true, "Event interface: new CustomEvent(\"foo\") must have own property \"isTrusted\"": true, "Event interface: new CustomEvent(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true, "MutationObserver interface: operation observe(Node,MutationObserverInit)": true, diff --git a/dom/imptests/failures/webapps/WebStorage/tests/submissions/Ms2ger/test_missing_arguments.html.json b/dom/imptests/failures/webapps/WebStorage/tests/submissions/Ms2ger/test_missing_arguments.html.json index 35810a3d3793..42a36331b75e 100644 --- a/dom/imptests/failures/webapps/WebStorage/tests/submissions/Ms2ger/test_missing_arguments.html.json +++ b/dom/imptests/failures/webapps/WebStorage/tests/submissions/Ms2ger/test_missing_arguments.html.json @@ -8,6 +8,5 @@ "Should throw TypeError for function \"function () { sessionStorage.getItem(); }\".": true, "Should throw TypeError for function \"function () { sessionStorage.setItem(); }\".": true, "Should throw TypeError for function \"function () { sessionStorage.setItem(\"a\"); }\".": true, - "Should throw TypeError for function \"function () { sessionStorage.removeItem(); }\".": true, - "Should throw TypeError for function \"function () { new StorageEvent(); }\".": true + "Should throw TypeError for function \"function () { sessionStorage.removeItem(); }\".": true } diff --git a/dom/interfaces/events/nsIDOMCloseEvent.idl b/dom/interfaces/events/nsIDOMCloseEvent.idl index 722e5e78230a..6c9a788cf6d8 100644 --- a/dom/interfaces/events/nsIDOMCloseEvent.idl +++ b/dom/interfaces/events/nsIDOMCloseEvent.idl @@ -6,7 +6,7 @@ #include "nsIDOMEvent.idl" /** - * The nsIDOMCloseEvent interface is the interface to the event + * The CloseEvent interface is the interface to the event * close on a WebSocket object. * * For more information on this interface, please see diff --git a/dom/interfaces/events/nsIDOMDeviceLightEvent.idl b/dom/interfaces/events/nsIDOMDeviceLightEvent.idl index c7b50d8f1ed7..d8641f3ee359 100644 --- a/dom/interfaces/events/nsIDOMDeviceLightEvent.idl +++ b/dom/interfaces/events/nsIDOMDeviceLightEvent.idl @@ -17,5 +17,5 @@ interface nsIDOMDeviceLightEvent : nsIDOMEvent dictionary DeviceLightEventInit : EventInit { - double value; + double value = Infinity; }; diff --git a/dom/network/interfaces/nsIDOMCFStateChangeEvent.idl b/dom/network/interfaces/nsIDOMCFStateChangeEvent.idl index dfe2db1522dd..0b8d9fd93df6 100644 --- a/dom/network/interfaces/nsIDOMCFStateChangeEvent.idl +++ b/dom/network/interfaces/nsIDOMCFStateChangeEvent.idl @@ -10,7 +10,7 @@ interface nsIDOMCFStateChangeEvent : nsIDOMEvent /** * Indicates about errors while setting up the Call forwarding rule. */ - readonly attribute bool success; + readonly attribute boolean success; /** * Indicates what to do with the rule. diff --git a/dom/network/interfaces/nsIDOMUSSDReceivedEvent.idl b/dom/network/interfaces/nsIDOMUSSDReceivedEvent.idl index 93618c5e7019..b859890ad87e 100644 --- a/dom/network/interfaces/nsIDOMUSSDReceivedEvent.idl +++ b/dom/network/interfaces/nsIDOMUSSDReceivedEvent.idl @@ -19,6 +19,6 @@ interface nsIDOMUSSDReceivedEvent : nsIDOMEvent dictionary USSDReceivedEventInit : EventInit { - DOMString message; + DOMString? message; boolean sessionEnded; }; diff --git a/dom/webidl/BlobEvent.webidl b/dom/webidl/BlobEvent.webidl new file mode 100644 index 000000000000..770a071455f1 --- /dev/null +++ b/dom/webidl/BlobEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface Blob; + +[Constructor(DOMString type, optional BlobEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface BlobEvent : Event +{ + readonly attribute Blob? data; +}; + +dictionary BlobEventInit : EventInit +{ + Blob? data = null; +}; diff --git a/dom/webidl/BluetoothDeviceEvent.webidl b/dom/webidl/BluetoothDeviceEvent.webidl new file mode 100644 index 000000000000..744e0861e513 --- /dev/null +++ b/dom/webidl/BluetoothDeviceEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface BluetoothDevice; + +[Constructor(DOMString type, optional BluetoothDeviceEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface BluetoothDeviceEvent : Event +{ + readonly attribute BluetoothDevice? device; +}; + +dictionary BluetoothDeviceEventInit : EventInit +{ + BluetoothDevice? device = null; +}; diff --git a/dom/webidl/CFStateChangeEvent.webidl b/dom/webidl/CFStateChangeEvent.webidl index 6e425c84ba7b..998ff80b6d97 100644 --- a/dom/webidl/CFStateChangeEvent.webidl +++ b/dom/webidl/CFStateChangeEvent.webidl @@ -1,12 +1,26 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ -dictionary CFStateChangeEventDict { - boolean success = false; - short action = -1; - short reason = -1; - DOMString? number = null; - short timeSeconds = -1; - short serviceClass = -1; +[Constructor(DOMString type, optional CFStateChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface CFStateChangeEvent : Event +{ + readonly attribute boolean success; + readonly attribute unsigned short action; + readonly attribute unsigned short reason; + readonly attribute DOMString? number; + readonly attribute unsigned short timeSeconds; + readonly attribute unsigned short serviceClass; +}; + +dictionary CFStateChangeEventInit : EventInit +{ + boolean success = false; + unsigned short action = 0; + unsigned short reason = 0; + DOMString number = ""; + unsigned short timeSeconds = 0; + unsigned short serviceClass = 0; }; diff --git a/dom/webidl/CallEvent.webidl b/dom/webidl/CallEvent.webidl new file mode 100644 index 000000000000..83db7db030ca --- /dev/null +++ b/dom/webidl/CallEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface TelephonyCall; + +[Constructor(DOMString type, optional CallEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface CallEvent : Event +{ + readonly attribute TelephonyCall? call; +}; + +dictionary CallEventInit : EventInit +{ + TelephonyCall? call = null; +}; diff --git a/dom/webidl/CloseEvent.webidl b/dom/webidl/CloseEvent.webidl new file mode 100644 index 000000000000..220da9c34b88 --- /dev/null +++ b/dom/webidl/CloseEvent.webidl @@ -0,0 +1,35 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * The nsIDOMCloseEvent interface is the interface to the event + * close on a WebSocket object. + * + * For more information on this interface, please see + * http://www.whatwg.org/specs/web-apps/current-work/multipage/network.html#closeevent + */ + +[Constructor(DOMString type, optional CloseEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface CloseEvent : Event +{ + readonly attribute boolean wasClean; + readonly attribute unsigned short code; + readonly attribute DOMString? reason; + + // initCloseEvent is a Gecko specific deprecated method. + [Throws] + void initCloseEvent(DOMString type, + boolean canBubble, + boolean cancelable, + boolean wasClean, + unsigned short code, + DOMString? reason); +}; + +dictionary CloseEventInit : EventInit +{ + boolean wasClean = false; + unsigned short code = 0; + DOMString reason = ""; +}; diff --git a/dom/webidl/CustomEvent.webidl b/dom/webidl/CustomEvent.webidl index 9cf373250915..e4c541b523a2 100644 --- a/dom/webidl/CustomEvent.webidl +++ b/dom/webidl/CustomEvent.webidl @@ -6,15 +6,25 @@ * The origin of this IDL file is * http://www.w3.org/TR/2012/WD-dom-20120105/ * - * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C * liability, trademark and document use rules apply. */ -[Constructor(DOMString type, optional CustomEventInit eventInitDict)] -interface CustomEvent : Event { +[Constructor(DOMString type, optional CustomEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface CustomEvent : Event +{ + [Throws] readonly attribute any detail; + + // initCustomEvent is a Gecko specific deprecated method. + [Throws] + void initCustomEvent(DOMString type, + boolean canBubble, + boolean cancelable, + any detail); }; -dictionary CustomEventInit : EventInit { - any detail; +dictionary CustomEventInit : EventInit +{ + any detail = null; }; diff --git a/dom/webidl/DOMTransactionEvent.webidl b/dom/webidl/DOMTransactionEvent.webidl new file mode 100644 index 000000000000..959ca2483db5 --- /dev/null +++ b/dom/webidl/DOMTransactionEvent.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DOMTransactionEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DOMTransactionEvent : Event +{ + [Throws] + readonly attribute any transactions; + + [Throws] + void initDOMTransactionEvent(DOMString type, + boolean canBubble, + boolean cancelable, + any transactions); +}; + +dictionary DOMTransactionEventInit : EventInit +{ + any transactions = null; +}; diff --git a/dom/webidl/DataErrorEvent.webidl b/dom/webidl/DataErrorEvent.webidl new file mode 100644 index 000000000000..2e66a2578655 --- /dev/null +++ b/dom/webidl/DataErrorEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DataErrorEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DataErrorEvent : Event +{ + readonly attribute DOMString? message; +}; + +dictionary DataErrorEventInit : EventInit +{ + DOMString message = ""; +}; diff --git a/dom/webidl/DeviceLightEvent.webidl b/dom/webidl/DeviceLightEvent.webidl new file mode 100644 index 000000000000..c238b77e2c60 --- /dev/null +++ b/dom/webidl/DeviceLightEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DeviceLightEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DeviceLightEvent : Event +{ + readonly attribute double value; +}; + +dictionary DeviceLightEventInit : EventInit +{ + unrestricted double value = Infinity; +}; diff --git a/dom/webidl/DeviceOrientationEvent.webidl b/dom/webidl/DeviceOrientationEvent.webidl new file mode 100644 index 000000000000..8e3ad7adbf92 --- /dev/null +++ b/dom/webidl/DeviceOrientationEvent.webidl @@ -0,0 +1,32 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DeviceOrientationEvent : Event +{ + readonly attribute double alpha; + readonly attribute double beta; + readonly attribute double gamma; + readonly attribute boolean absolute; + + // initDeviceOrientationEvent is a Gecko specific deprecated method. + [Throws] + void initDeviceOrientationEvent(DOMString type, + boolean canBubble, + boolean cancelable, + double alpha, + double beta, + double gamma, + boolean absolute); +}; + +dictionary DeviceOrientationEventInit : EventInit +{ + double alpha = 0; + double beta = 0; + double gamma = 0; + boolean absolute = false; +}; diff --git a/dom/webidl/DeviceProximityEvent.webidl b/dom/webidl/DeviceProximityEvent.webidl new file mode 100644 index 000000000000..44ff14b55f8e --- /dev/null +++ b/dom/webidl/DeviceProximityEvent.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DeviceProximityEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DeviceProximityEvent : Event +{ + readonly attribute double value; + readonly attribute double min; + readonly attribute double max; +}; + +dictionary DeviceProximityEventInit : EventInit +{ + unrestricted double value = Infinity; + unrestricted double min = -Infinity; + unrestricted double max = Infinity; +}; diff --git a/dom/webidl/DeviceStorageChangeEvent.webidl b/dom/webidl/DeviceStorageChangeEvent.webidl new file mode 100644 index 000000000000..494501250840 --- /dev/null +++ b/dom/webidl/DeviceStorageChangeEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional DeviceStorageChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface DeviceStorageChangeEvent : Event +{ + readonly attribute DOMString? path; + readonly attribute DOMString? reason; +}; + +dictionary DeviceStorageChangeEventInit : EventInit +{ + DOMString path = ""; + DOMString reason = ""; +}; diff --git a/dom/webidl/DummyBinding.webidl b/dom/webidl/DummyBinding.webidl index d8f3981e9bab..7bdfbbe7dd3f 100644 --- a/dom/webidl/DummyBinding.webidl +++ b/dom/webidl/DummyBinding.webidl @@ -10,8 +10,6 @@ interface DummyInterface { readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler; FilePropertyBag fileBag(); - CFStateChangeEventDict cfstateChangeEvent(); - USSDReceivedEventDict ussdReceivedEvent(); InspectorRGBTriple rgbTriple(); Function getFunction(); void funcSocketsDict(optional SocketsDict arg); diff --git a/dom/webidl/ElementReplaceEvent.webidl b/dom/webidl/ElementReplaceEvent.webidl new file mode 100644 index 000000000000..6090657f29fd --- /dev/null +++ b/dom/webidl/ElementReplaceEvent.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional ElementReplaceEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface ElementReplaceEvent : Event +{ + readonly attribute Element? upgrade; + + // initElementReplaceEvent is a Gecko specific deprecated method. + [Throws] + void initElementReplaceEvent(DOMString type, + boolean canBubble, + boolean cancelable, + Element? upgrade); +}; + +dictionary ElementReplaceEventInit : EventInit +{ + Element? upgrade = null; +}; diff --git a/dom/webidl/GamepadAxisMoveEvent.webidl b/dom/webidl/GamepadAxisMoveEvent.webidl new file mode 100644 index 000000000000..d22789d0ff3d --- /dev/null +++ b/dom/webidl/GamepadAxisMoveEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional GamepadAxisMoveEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface GamepadAxisMoveEvent : GamepadEvent +{ + readonly attribute unsigned long axis; + readonly attribute double value; +}; + +dictionary GamepadAxisMoveEventInit : GamepadEventInit +{ + unsigned long axis = 0; + double value = 0; +}; diff --git a/dom/webidl/GamepadButtonEvent.webidl b/dom/webidl/GamepadButtonEvent.webidl new file mode 100644 index 000000000000..2e4352d554f8 --- /dev/null +++ b/dom/webidl/GamepadButtonEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional GamepadButtonEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface GamepadButtonEvent : GamepadEvent +{ + readonly attribute unsigned long button; +}; + +dictionary GamepadButtonEventInit : GamepadEventInit +{ + unsigned long button = 0; +}; diff --git a/dom/webidl/GamepadEvent.webidl b/dom/webidl/GamepadEvent.webidl new file mode 100644 index 000000000000..c559b482b382 --- /dev/null +++ b/dom/webidl/GamepadEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional GamepadEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface GamepadEvent : Event +{ + readonly attribute Gamepad? gamepad; +}; + +dictionary GamepadEventInit : EventInit +{ + Gamepad? gamepad = null; +}; diff --git a/dom/webidl/HashChangeEvent.webidl b/dom/webidl/HashChangeEvent.webidl new file mode 100644 index 000000000000..a43b4a244074 --- /dev/null +++ b/dom/webidl/HashChangeEvent.webidl @@ -0,0 +1,26 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional HashChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface HashChangeEvent : Event +{ + readonly attribute DOMString? oldURL; + readonly attribute DOMString? newURL; + + // initHashChangeEvent is a Gecko specific deprecated method. + [Throws] + void initHashChangeEvent(DOMString type, + boolean canBubble, + boolean cancelable, + DOMString? oldURL, + DOMString? newURL); +}; + +dictionary HashChangeEventInit : EventInit +{ + DOMString oldURL = ""; + DOMString newURL = ""; +}; diff --git a/dom/webidl/IccCardLockErrorEvent.webidl b/dom/webidl/IccCardLockErrorEvent.webidl new file mode 100644 index 000000000000..4b64f6954415 --- /dev/null +++ b/dom/webidl/IccCardLockErrorEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional IccCardLockErrorEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface IccCardLockErrorEvent : Event +{ + readonly attribute DOMString? lockType; + readonly attribute long retryCount; +}; + +dictionary IccCardLockErrorEventInit : EventInit +{ + DOMString lockType = ""; + long retryCount = 0; +}; diff --git a/dom/webidl/MozApplicationEvent.webidl b/dom/webidl/MozApplicationEvent.webidl new file mode 100644 index 000000000000..b37d606e0960 --- /dev/null +++ b/dom/webidl/MozApplicationEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface mozIDOMApplication; + +[Constructor(DOMString type, optional MozApplicationEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozApplicationEvent : Event +{ + readonly attribute mozIDOMApplication? application; +}; + +dictionary MozApplicationEventInit : EventInit +{ + mozIDOMApplication? application = null; +}; diff --git a/dom/webidl/MozCellBroadcastEvent.webidl b/dom/webidl/MozCellBroadcastEvent.webidl new file mode 100644 index 000000000000..b82ebf097c5e --- /dev/null +++ b/dom/webidl/MozCellBroadcastEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface MozCellBroadcastMessage; + +[Constructor(DOMString type, optional MozCellBroadcastEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozCellBroadcastEvent : Event +{ + readonly attribute MozCellBroadcastMessage? message; +}; + +dictionary MozCellBroadcastEventInit : EventInit +{ + MozCellBroadcastMessage? message = null; +}; diff --git a/dom/webidl/MozContactChangeEvent.webidl b/dom/webidl/MozContactChangeEvent.webidl new file mode 100644 index 000000000000..d31087276727 --- /dev/null +++ b/dom/webidl/MozContactChangeEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional MozContactChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozContactChangeEvent : Event +{ + readonly attribute DOMString? contactID; + readonly attribute DOMString? reason; +}; + +dictionary MozContactChangeEventInit : EventInit +{ + DOMString contactID = ""; + DOMString reason = ""; +}; diff --git a/dom/webidl/MozMmsEvent.webidl b/dom/webidl/MozMmsEvent.webidl new file mode 100644 index 000000000000..4883a63a72f6 --- /dev/null +++ b/dom/webidl/MozMmsEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface MozMmsMessage; + +[Constructor(DOMString type, optional MozMmsEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozMmsEvent : Event +{ + readonly attribute MozMmsMessage? message; +}; + +dictionary MozMmsEventInit : EventInit +{ + MozMmsMessage? message = null; +}; diff --git a/dom/webidl/MozSettingsEvent.webidl b/dom/webidl/MozSettingsEvent.webidl new file mode 100644 index 000000000000..a534f3ae8357 --- /dev/null +++ b/dom/webidl/MozSettingsEvent.webidl @@ -0,0 +1,19 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional MozSettingsEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozSettingsEvent : Event +{ + readonly attribute DOMString? settingName; + [Throws] + readonly attribute any settingValue; +}; + +dictionary MozSettingsEventInit : EventInit +{ + DOMString settingName = ""; + any settingValue = null; +}; diff --git a/dom/webidl/MozSmsEvent.webidl b/dom/webidl/MozSmsEvent.webidl new file mode 100644 index 000000000000..e7d2db66779d --- /dev/null +++ b/dom/webidl/MozSmsEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface MozSmsMessage; + +[Constructor(DOMString type, optional MozSmsEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozSmsEvent : Event +{ + readonly attribute MozSmsMessage? message; +}; + +dictionary MozSmsEventInit : EventInit +{ + MozSmsMessage? message = null; +}; diff --git a/dom/webidl/MozVoicemailEvent.webidl b/dom/webidl/MozVoicemailEvent.webidl new file mode 100644 index 000000000000..119b03f18b53 --- /dev/null +++ b/dom/webidl/MozVoicemailEvent.webidl @@ -0,0 +1,17 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface MozVoicemailStatus; + +[Constructor(DOMString type, optional MozVoicemailEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozVoicemailEvent : Event +{ + readonly attribute MozVoicemailStatus? status; +}; + +dictionary MozVoicemailEventInit : EventInit +{ + MozVoicemailStatus? status = null; +}; diff --git a/dom/webidl/MozWifiConnectionInfoEvent.webidl b/dom/webidl/MozWifiConnectionInfoEvent.webidl new file mode 100644 index 000000000000..6caca8e8fb4c --- /dev/null +++ b/dom/webidl/MozWifiConnectionInfoEvent.webidl @@ -0,0 +1,25 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional MozWifiConnectionInfoEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozWifiConnectionInfoEvent : Event +{ + [Throws] + readonly attribute any network; + readonly attribute short signalStrength; + readonly attribute short relSignalStrength; + readonly attribute long linkSpeed; + readonly attribute DOMString? ipAddress; +}; + +dictionary MozWifiConnectionInfoEventInit : EventInit +{ + any network = null; + short signalStrength = 0; + short relSignalStrength = 0; + long linkSpeed = 0; + DOMString ipAddress = ""; +}; diff --git a/dom/webidl/MozWifiStatusChangeEvent.webidl b/dom/webidl/MozWifiStatusChangeEvent.webidl new file mode 100644 index 000000000000..a3fc99fb47e8 --- /dev/null +++ b/dom/webidl/MozWifiStatusChangeEvent.webidl @@ -0,0 +1,19 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional MozWifiStatusChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface MozWifiStatusChangeEvent : Event +{ + [Throws] + readonly attribute any network; + readonly attribute DOMString? status; +}; + +dictionary MozWifiStatusChangeEventInit : EventInit +{ + any network = null; + DOMString status = ""; +}; diff --git a/dom/webidl/PageTransitionEvent.webidl b/dom/webidl/PageTransitionEvent.webidl new file mode 100644 index 000000000000..2925602995a8 --- /dev/null +++ b/dom/webidl/PageTransitionEvent.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional PageTransitionEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface PageTransitionEvent : Event +{ + readonly attribute boolean persisted; + + // initPageTransitionEvent is a Gecko specific deprecated method. + [Throws] + void initPageTransitionEvent(DOMString type, + boolean canBubble, + boolean cancelable, + boolean persisted); +}; + +dictionary PageTransitionEventInit : EventInit +{ + boolean persisted = false; +}; diff --git a/dom/webidl/PopStateEvent.webidl b/dom/webidl/PopStateEvent.webidl new file mode 100644 index 000000000000..f1b5c8fa84c6 --- /dev/null +++ b/dom/webidl/PopStateEvent.webidl @@ -0,0 +1,24 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional PopStateEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface PopStateEvent : Event +{ + [Throws] + readonly attribute any state; + + // initPopStateEvent is a Gecko specific deprecated method. + [Throws] + void initPopStateEvent(DOMString type, + boolean canBubble, + boolean cancelable, + any state); +}; + +dictionary PopStateEventInit : EventInit +{ + any state = null; +}; diff --git a/dom/webidl/PopupBlockedEvent.webidl b/dom/webidl/PopupBlockedEvent.webidl new file mode 100644 index 000000000000..16f6ca453f4c --- /dev/null +++ b/dom/webidl/PopupBlockedEvent.webidl @@ -0,0 +1,33 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface Window; +interface URI; + +[Constructor(DOMString type, optional PopupBlockedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface PopupBlockedEvent : Event +{ + readonly attribute Window? requestingWindow; + readonly attribute URI? popupWindowURI; + readonly attribute DOMString? popupWindowName; + readonly attribute DOMString? popupWindowFeatures; + + [Throws] + void initPopupBlockedEvent(DOMString type, + boolean canBubble, + boolean cancelable, + Window? requestingWindow, + URI? popupWindowURI, + DOMString? popupWindowName, + DOMString? popupWindowFeatures); +}; + +dictionary PopupBlockedEventInit : EventInit +{ + Window? requestingWindow = null; + URI? popupWindowURI = null; + DOMString popupWindowName = ""; + DOMString popupWindowFeatures = ""; +}; diff --git a/dom/webidl/ProgressEvent.webidl b/dom/webidl/ProgressEvent.webidl new file mode 100644 index 000000000000..997f88719b52 --- /dev/null +++ b/dom/webidl/ProgressEvent.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional ProgressEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface ProgressEvent : Event +{ + readonly attribute boolean lengthComputable; + readonly attribute unsigned long long loaded; + readonly attribute unsigned long long total; +}; + +dictionary ProgressEventInit : EventInit +{ + boolean lengthComputable = false; + unsigned long long loaded = 0; + unsigned long long total = 0; +}; diff --git a/dom/webidl/SmartCardEvent.webidl b/dom/webidl/SmartCardEvent.webidl new file mode 100644 index 000000000000..f2515b02d82d --- /dev/null +++ b/dom/webidl/SmartCardEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional SmartCardEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface SmartCardEvent : Event +{ + readonly attribute DOMString? tokenName; +}; + +dictionary SmartCardEventInit : EventInit +{ + DOMString tokenName = ""; +}; diff --git a/dom/webidl/SpeechRecognitionError.webidl b/dom/webidl/SpeechRecognitionError.webidl new file mode 100644 index 000000000000..91725a59128c --- /dev/null +++ b/dom/webidl/SpeechRecognitionError.webidl @@ -0,0 +1,27 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional SpeechRecognitionErrorInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface SpeechRecognitionError : Event +{ + const unsigned long NO_SPEECH = 0; + const unsigned long ABORTED = 1; + const unsigned long AUDIO_CAPTURE = 2; + const unsigned long NETWORK = 3; + const unsigned long NOT_ALLOWED = 4; + const unsigned long SERVICE_NOT_ALLOWED = 5; + const unsigned long BAD_GRAMMAR = 6; + const unsigned long LANGUAGE_NOT_SUPPORTED = 7; + + readonly attribute unsigned long error; + readonly attribute DOMString? message; +}; + +dictionary SpeechRecognitionErrorInit : EventInit +{ + unsigned long error = 0; + DOMString message = ""; +}; diff --git a/dom/webidl/SpeechRecognitionEvent.webidl b/dom/webidl/SpeechRecognitionEvent.webidl new file mode 100644 index 000000000000..b64db97aae8c --- /dev/null +++ b/dom/webidl/SpeechRecognitionEvent.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface nsISupports; + +[Constructor(DOMString type, optional SpeechRecognitionEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface SpeechRecognitionEvent : Event +{ + readonly attribute unsigned long resultIndex; + readonly attribute nsISupports? results; + readonly attribute DOMString? interpretation; + readonly attribute Document? emma; +}; + +dictionary SpeechRecognitionEventInit : EventInit +{ + unsigned long resultIndex = 0; + nsISupports? results = null; + DOMString interpretation = ""; + Document? emma = null; +}; diff --git a/dom/webidl/SpeechSynthesisEvent.webidl b/dom/webidl/SpeechSynthesisEvent.webidl index 15902ab0c64f..33219ecaf664 100644 --- a/dom/webidl/SpeechSynthesisEvent.webidl +++ b/dom/webidl/SpeechSynthesisEvent.webidl @@ -9,10 +9,18 @@ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C * liability, trademark and document use rules apply. */ -interface Event; -interface SpeechSynthesisEvent : Event { +[Constructor(DOMString type, optional SpeechSynthesisEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface SpeechSynthesisEvent : Event +{ readonly attribute unsigned long charIndex; readonly attribute float elapsedTime; - readonly attribute DOMString name; + readonly attribute DOMString? name; +}; + +dictionary SpeechSynthesisEventInit : EventInit +{ + unsigned long charIndex = 0; + float elapsedTime = 0; + DOMString name = ""; }; diff --git a/dom/webidl/StorageEvent.webidl b/dom/webidl/StorageEvent.webidl new file mode 100644 index 000000000000..b74779252f45 --- /dev/null +++ b/dom/webidl/StorageEvent.webidl @@ -0,0 +1,42 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + * + * Interface for a client side storage. See + * http://dev.w3.org/html5/webstorage/#the-storage-event + * for more information. + * + * Event sent to a window when a storage area changes. + */ +interface Storage; + +[Constructor(DOMString type, optional StorageEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface StorageEvent : Event +{ + readonly attribute DOMString? key; + readonly attribute DOMString? oldValue; + readonly attribute DOMString? newValue; + readonly attribute DOMString? url; + readonly attribute Storage? storageArea; + + // initStorageEvent is a Gecko specific deprecated method. + [Throws] + void initStorageEvent(DOMString type, + boolean canBubble, + boolean cancelable, + DOMString? key, + DOMString? oldValue, + DOMString? newValue, + DOMString? url, + Storage? storageArea); +}; + +dictionary StorageEventInit : EventInit +{ + DOMString? key = null; + DOMString? oldValue = null; + DOMString? newValue = null; + DOMString url = ""; + Storage? storageArea = null; +}; diff --git a/dom/webidl/StyleRuleChangeEvent.webidl b/dom/webidl/StyleRuleChangeEvent.webidl new file mode 100644 index 000000000000..1e211edddf9e --- /dev/null +++ b/dom/webidl/StyleRuleChangeEvent.webidl @@ -0,0 +1,19 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +interface CSSRule; + +[Constructor(DOMString type, optional StyleRuleChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface StyleRuleChangeEvent : Event +{ + readonly attribute CSSStyleSheet? stylesheet; + readonly attribute CSSRule? rule; +}; + +dictionary StyleRuleChangeEventInit : EventInit +{ + CSSStyleSheet? stylesheet = null; + CSSRule? rule = null; +}; diff --git a/dom/webidl/StyleSheetApplicableStateChangeEvent.webidl b/dom/webidl/StyleSheetApplicableStateChangeEvent.webidl new file mode 100644 index 000000000000..483a386cdf7d --- /dev/null +++ b/dom/webidl/StyleSheetApplicableStateChangeEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional StyleSheetApplicableStateChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface StyleSheetApplicableStateChangeEvent : Event +{ + readonly attribute CSSStyleSheet? stylesheet; + readonly attribute boolean applicable; +}; + +dictionary StyleSheetApplicableStateChangeEventInit : EventInit +{ + CSSStyleSheet? stylesheet = null; + boolean applicable = false; +}; diff --git a/dom/webidl/StyleSheetChangeEvent.webidl b/dom/webidl/StyleSheetChangeEvent.webidl new file mode 100644 index 000000000000..b6019d83145d --- /dev/null +++ b/dom/webidl/StyleSheetChangeEvent.webidl @@ -0,0 +1,18 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional StyleSheetChangeEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface StyleSheetChangeEvent : Event +{ + readonly attribute CSSStyleSheet? stylesheet; + readonly attribute boolean documentSheet; +}; + +dictionary StyleSheetChangeEventInit : EventInit +{ + CSSStyleSheet? stylesheet = null; + boolean documentSheet = false; +}; diff --git a/dom/webidl/USSDReceivedEvent.webidl b/dom/webidl/USSDReceivedEvent.webidl index cda66e66851b..b7fa9098f66e 100644 --- a/dom/webidl/USSDReceivedEvent.webidl +++ b/dom/webidl/USSDReceivedEvent.webidl @@ -4,7 +4,15 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ -dictionary USSDReceivedEventDict { +[Constructor(DOMString type, optional USSDReceivedEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface USSDReceivedEvent : Event +{ + readonly attribute DOMString? message; + readonly attribute boolean sessionEnded; +}; + +dictionary USSDReceivedEventInit : EventInit +{ DOMString? message = null; boolean sessionEnded = false; -}; \ No newline at end of file +}; diff --git a/dom/webidl/UserProximityEvent.webidl b/dom/webidl/UserProximityEvent.webidl new file mode 100644 index 000000000000..8b64b81c9be2 --- /dev/null +++ b/dom/webidl/UserProximityEvent.webidl @@ -0,0 +1,16 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[Constructor(DOMString type, optional UserProximityEventInit eventInitDict), HeaderFile="GeneratedEventClasses.h"] +interface UserProximityEvent : Event +{ + readonly attribute boolean near; +}; + +dictionary UserProximityEventInit : EventInit +{ + boolean near = false; +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 17b57365b89b..2ce7c97dcb9c 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -32,7 +32,6 @@ webidl_files = \ CanvasRenderingContext2D.webidl \ CaretPosition.webidl \ CDATASection.webidl \ - CFStateChangeEvent.webidl \ ChannelMergerNode.webidl \ ChannelSplitterNode.webidl \ CharacterData.webidl \ @@ -344,7 +343,6 @@ webidl_files = \ WheelEvent.webidl \ UndoManager.webidl \ URLUtils.webidl \ - USSDReceivedEvent.webidl \ VideoStreamTrack.webidl \ WaveShaperNode.webidl \ WaveTable.webidl \ @@ -391,6 +389,7 @@ webidl_files += \ SpeechSynthesisUtterance.webidl \ SpeechSynthesisVoice.webidl \ SpeechSynthesis.webidl \ + SpeechSynthesisEvent.webidl \ $(NULL) endif @@ -406,6 +405,69 @@ webidl_files += \ $(NULL) endif +webidl_files += \ + ProgressEvent.webidl \ + StorageEvent.webidl \ + DeviceProximityEvent.webidl \ + MozSettingsEvent.webidl \ + UserProximityEvent.webidl \ + CustomEvent.webidl \ + PageTransitionEvent.webidl \ + DOMTransactionEvent.webidl \ + PopStateEvent.webidl \ + HashChangeEvent.webidl \ + CloseEvent.webidl \ + MozContactChangeEvent.webidl \ + DeviceOrientationEvent.webidl \ + DeviceLightEvent.webidl \ + MozApplicationEvent.webidl \ + SmartCardEvent.webidl \ + StyleRuleChangeEvent.webidl \ + StyleSheetChangeEvent.webidl \ + StyleSheetApplicableStateChangeEvent.webidl \ + ElementReplaceEvent.webidl \ + MozSmsEvent.webidl \ + MozMmsEvent.webidl \ + DeviceStorageChangeEvent.webidl \ + PopupBlockedEvent.webidl \ + BlobEvent.webidl \ + $(NULL) + +ifdef MOZ_B2G_BT +webidl_files += \ + BluetoothDeviceEvent.webidl \ + $(NULL) +endif + +ifdef MOZ_B2G_RIL +webidl_files += \ + CallEvent.webidl \ + CFStateChangeEvent.webidl \ + DataErrorEvent.webidl \ + IccCardLockErrorEvent.webidl \ + MozWifiStatusChangeEvent.webidl \ + MozWifiConnectionInfoEvent.webidl \ + MozCellBroadcastEvent.webidl \ + MozVoicemailEvent.webidl \ + USSDReceivedEvent.webidl \ + $(NULL) +endif + +ifdef MOZ_GAMEPAD +webidl_files += \ + GamepadEvent.webidl \ + GamepadButtonEvent.webidl \ + GamepadAxisMoveEvent.webidl \ + $(NULL) +endif + +ifdef MOZ_WEBSPEECH +webidl_files += \ + SpeechRecognitionEvent.webidl \ + SpeechRecognitionError.webidl \ + $(NULL) +endif + ifdef ENABLE_TESTS test_webidl_files := \ TestCodeGen.webidl \ diff --git a/js/xpconnect/src/Makefile.in b/js/xpconnect/src/Makefile.in index f76cd151ec28..bd92293ba6a1 100644 --- a/js/xpconnect/src/Makefile.in +++ b/js/xpconnect/src/Makefile.in @@ -117,7 +117,10 @@ GeneratedEvents.h: $(srcdir)/dictionary_helper_gen.conf \ --header-output GeneratedEvents.h \ event_impl_gen.conf +GeneratedEventClasses.h: GeneratedEvents.cpp + GeneratedEvents.cpp: DictionaryHelpers.h \ + GeneratedEvents.h \ $(srcdir)/dictionary_helper_gen.conf \ event_impl_gen.conf \ $(srcdir)/dictionary_helper_gen.py \ @@ -130,13 +133,23 @@ GeneratedEvents.cpp: DictionaryHelpers.h \ -I$(LIBXUL_DIST)/sdk/bin \ $(srcdir)/event_impl_gen.py \ -I $(DEPTH)/dist/idl \ - --header-output GeneratedEvents.h \ + --class-declarations GeneratedEventClasses.h \ --stub-output GeneratedEvents.cpp \ --makedepend-output $(MDDEPDIR)/event_impl_gen.pp \ event_impl_gen.conf +GeneratedEvents-webidl: event_impl_gen.conf + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + $(PLY_INCLUDE) \ + -I$(LIBXUL_DIST)/sdk/bin \ + $(srcdir)/event_impl_gen.py \ + -I $(DEPTH)/dist/idl \ + --webidltarget=$(top_srcdir)/dom/webidl \ + event_impl_gen.conf + _EXTRA_EXPORT_FILES = \ DictionaryHelpers.h \ + GeneratedEventClasses.h \ $(NULL) libs:: $(_EXTRA_EXPORT_FILES) @@ -149,6 +162,7 @@ GARBAGE += \ DictionaryHelpers.cpp \ GeneratedEvents.h \ GeneratedEvents.cpp \ + GeneratedEventClasses.h \ event_impl_gen.conf \ xpidl_debug \ $(MDDEPDIR)/dom_qsgen.pp \ diff --git a/js/xpconnect/src/event_impl_gen.conf.in b/js/xpconnect/src/event_impl_gen.conf.in index c0b5709421ef..b12a11c952bc 100644 --- a/js/xpconnect/src/event_impl_gen.conf.in +++ b/js/xpconnect/src/event_impl_gen.conf.in @@ -75,3 +75,12 @@ exclude_automatic_type_include = [ 'mozIDOMApplication', 'nsIDOMBlob' ] + +""" Map xpidl interface names to implementation classes. The third column is the canonical interface. """ +xpidl_to_native = [ + ['nsIDOMDocument', 'nsIDocument', 'nsIDocument'], + ['nsIDOMElement', 'mozilla::dom::Element', 'mozilla::dom::Element'], + ['nsIDOMCSSStyleSheet', 'nsCSSStyleSheet', 'nsIStyleSheet'], + ['nsIDOMGamepad', 'nsDOMGamepad', 'nsIDOMGamepad'] + ] + diff --git a/js/xpconnect/src/event_impl_gen.py b/js/xpconnect/src/event_impl_gen.py index fdbefadc67ca..28fd074da207 100644 --- a/js/xpconnect/src/event_impl_gen.py +++ b/js/xpconnect/src/event_impl_gen.py @@ -23,22 +23,24 @@ def findIDL(includePath, interfaceFileName): "in include path %r" % (interfaceFileName, includePath)) +eventFileNameToIdl = {}; + def loadIDL(parser, includePath, filename): + global eventFileNameToIdl + if filename in eventFileNameToIdl: + return eventFileNameToIdl[filename] + idlFile = findIDL(includePath, filename) if not idlFile in makeutils.dependencies: makeutils.dependencies.append(idlFile) idl = p.parse(open(idlFile).read(), idlFile) idl.resolve(includePath, p) + eventFileNameToIdl[filename] = idl return idl def loadEventIDL(parser, includePath, eventname): eventidl = ("nsIDOM%s.idl" % eventname) - idlFile = findIDL(includePath, eventidl) - if not idlFile in makeutils.dependencies: - makeutils.dependencies.append(idlFile) - idl = p.parse(open(idlFile).read(), idlFile) - idl.resolve(includePath, p) - return idl + return loadIDL(parser, includePath, eventidl) class Configuration: def __init__(self, filename): @@ -47,6 +49,7 @@ class Configuration: self.simple_events = config.get('simple_events', []) self.special_includes = config.get('special_includes', []) self.exclude_automatic_type_include = config.get('exclude_automatic_type_include', []) + self.xpidl_to_native = config.get('xpidl_to_native', []) def readConfigFile(filename): return Configuration(filename) @@ -54,6 +57,12 @@ def readConfigFile(filename): def firstCap(str): return str[0].upper() + str[1:] +def getBaseName(iface): + basename = ("%s" % iface.base[6:]) + if (basename == "Event"): + basename = "nsDOMEvent" + return basename + def print_header_file(fd, conf): fd.write("#if defined MOZ_GENERATED_EVENT_LIST\n") for e in conf.simple_events: @@ -84,6 +93,138 @@ def print_header_file(fd, conf): fd.write("\n#endif\n") fd.write("#endif\n") +def print_classes_file(fd, conf): + fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n") + fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n") + + fd.write("#include \"nsDOMEvent.h\"\n"); + includes = [] + for s in conf.special_includes: + if not s in includes: + includes.append(strip_end(s, ".h")) + + for e in conf.simple_events: + if not e in includes: + includes.append(("nsIDOM%s" % e)) + + attrnames = [] + for e in conf.simple_events: + idl = loadEventIDL(p, options.incdirs, e) + collect_names_and_non_primitive_attribute_types(idl, attrnames, includes) + + for c in includes: + if not c in conf.exclude_automatic_type_include: + fd.write("#include \"%s.h\"\n" % c) + + for e in conf.simple_events: + fd.write('#include "mozilla/dom/%sBinding.h"\n' % e); + + fd.write("namespace mozilla {\n") + fd.write("namespace dom {\n") + for e in conf.simple_events: + idl = loadEventIDL(p, options.incdirs, e) + for pr in idl.productions: + if pr.kind == 'interface': + print_class_declaration(e, pr, fd, conf) + fd.write("} // namespace dom\n") + fd.write("} // namespace mozilla\n\n") + fd.write("#endif\n"); + +def print_class_declaration(eventname, iface, fd, conf): + classname = ("%s" % eventname) + basename = getBaseName(iface) + attributes = [] + ccattributes = [] + for member in iface.members: + if isinstance(member, xpidl.Attribute): + attributes.append(member) + if (member.realtype.nativeType('in').endswith('*')): + ccattributes.append(member); + + baseinterfaces = [] + baseiface = iface.idl.getName(iface.base, iface.location) + while baseiface.name != "nsIDOMEvent": + baseinterfaces.append(baseiface) + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) + baseinterfaces.reverse() + + allattributes = [] + for baseiface in baseinterfaces: + for member in baseiface.members: + if isinstance(member, xpidl.Attribute): + allattributes.append(member) + allattributes.extend(attributes); + + fd.write("\nclass %s : public %s, public %s\n" % (classname, basename, iface.name)) + fd.write("{\n") + fd.write("public:\n") + fd.write(" %s(mozilla::dom::EventTarget* aOwner, " % classname) + fd.write("nsPresContext* aPresContext = nullptr, nsEvent* aEvent = nullptr);\n"); + fd.write(" virtual ~%s();\n\n" % classname) + fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") + fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) + fd.write(" NS_FORWARD_TO_NSDOMEVENT\n") + + for baseiface in baseinterfaces: + baseimpl = ("%s" % baseiface.name[6:]) + if (baseimpl == "Event"): + baseimpl = "nsDOMEvent" + fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) + + fd.write(" NS_DECL_%s\n" % iface.name.upper()) + fd.write(" virtual nsresult InitFromCtor(const nsAString& aType, JSContext* aCx, jsval* aVal);\n\n") + + hasVariant = False + for a in allattributes: + if a.type == "nsIVariant": + hasVariant = True + break; + fd.write(" static already_AddRefed<%s> Constructor(const GlobalObject& aGlobal, " % eventname) + if hasVariant: + fd.write("JSContext* aCx, ") + fd.write("const nsAString& aType, ") + fd.write("const %sInit& aParam, " % eventname) + fd.write("ErrorResult& aRv);\n\n") + + fd.write(" virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE\n") + fd.write(" {\n") + fd.write(" return mozilla::dom::%sBinding::Wrap(aCx, aScope, this);\n" % eventname) + fd.write(" }\n\n") + + for a in attributes: + """xpidl methods take care of string member variables!""" + firstCapName = firstCap(a.name) + cleanNativeType = a.realtype.nativeType('in').strip('* ') + if a.realtype.nativeType('in').count("nsAString"): + continue + elif a.realtype.nativeType('in').count("nsIVariant"): + fd.write(" JS::Value Get%s(JSContext* aCx, ErrorResult& aRv);\n\n" % firstCapName); + elif a.realtype.nativeType('in').endswith('*'): + fd.write(" already_AddRefed<%s> Get%s()\n" % (xpidl_to_native(cleanNativeType, conf), firstCapName)) + fd.write(" {\n"); + fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(m%s);\n" % (xpidl_to_canonical(cleanNativeType, conf), a.name, firstCapName)) + fd.write(" return %s.forget().downcast<%s>();\n" % (a.name, xpidl_to_native(cleanNativeType, conf))) + fd.write(" }\n\n"); + else: + fd.write(" %s %s()\n" % (cleanNativeType, firstCapName)) + fd.write(" {\n"); + fd.write(" return m%s;\n" % firstCapName) + fd.write(" }\n\n"); + + fd.write(" void ") + fd.write("Init%s(" % eventname) + if hasVariant: + fd.write("JSContext* aCx, ") + fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") + for a in allattributes: + writeNativeAttributeParams(fd, a, conf) + fd.write(", ErrorResult& aRv);\n\n") + + fd.write("protected:\n") + for a in attributes: + fd.write(" %s\n" % attributeVariableTypeAndName(a)) + fd.write("};\n") + def collect_names_and_non_primitive_attribute_types(idl, attrnames, forwards): for p in idl.productions: if p.kind == 'interface' or p.kind == 'dictionary': @@ -114,39 +255,20 @@ def collect_names_and_non_primitive_attribute_types_from_interface(iface, attrna def print_cpp(idl, fd, conf, eventname): for p in idl.productions: if p.kind == 'interface': - write_cpp(eventname, p, fd) + write_cpp(eventname, p, fd, conf) def print_cpp_file(fd, conf): fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") - fd.write('#include "GeneratedEvents.h"\n') + fd.write('#include "GeneratedEventClasses.h"\n') + fd.write('#include "xpcprivate.h"\n'); fd.write('#include "nsDOMClassInfoID.h"\n') fd.write('#include "nsPresContext.h"\n') fd.write('#include "nsGUIEvent.h"\n') fd.write('#include "nsDOMEvent.h"\n'); fd.write('#include "mozilla/dom/EventTarget.h"\n'); - includes = [] - for s in conf.special_includes: - if not s in includes: - includes.append(strip_end(s, ".h")) - - for e in conf.simple_events: - if not e in includes: - includes.append(("nsIDOM%s" % e)) - - attrnames = [] for e in conf.simple_events: idl = loadEventIDL(p, options.incdirs, e) - collect_names_and_non_primitive_attribute_types(idl, attrnames, includes) - - for c in includes: - if not c in conf.exclude_automatic_type_include: - fd.write("#include \"%s.h\"\n" % c) - - for e in conf.simple_events: - idlname = ("nsIDOM%s.idl" % e) - idl = p.parse(open(findIDL(options.incdirs, idlname)).read(), idlname) - idl.resolve(options.incdirs, p) print_cpp(idl, fd, conf, e) def init_value(attribute): @@ -197,9 +319,20 @@ def writeAttributeGetter(fd, classname, a): elif a.realtype.nativeType('in').count("nsACString"): fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) else: - fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) + fd.write(" *a%s = %s();\n" % (firstCap(a.name), firstCap(a.name))) fd.write(" return NS_OK;\n"); fd.write("}\n\n"); + if a.realtype.nativeType('in').count("nsIVariant"): + fd.write("JS::Value\n") + fd.write("%s::Get%s(JSContext* aCx, ErrorResult& aRv)\n" % (classname, firstCap(a.name))) + fd.write("{\n") + fd.write(" JS::Rooted retVal(aCx, JS::NullValue());\n"); + fd.write(" nsresult rv = NS_ERROR_UNEXPECTED;\n") + fd.write(" if (m%s && !XPCVariant::VariantDataToJS(m%s, &rv, retVal.address())) {\n" % (firstCap(a.name), firstCap(a.name))) + fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") + fd.write(" }\n") + fd.write(" return retVal;\n"); + fd.write("}\n\n") def writeAttributeParams(fd, a): if a.realtype.nativeType('in').endswith('*'): @@ -211,9 +344,21 @@ def writeAttributeParams(fd, a): else: fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) -def write_cpp(eventname, iface, fd): - classname = ("nsDOM%s" % eventname) - basename = ("ns%s" % iface.base[3:]) +def writeNativeAttributeParams(fd, a, conf): + if a.type == "nsIVariant": + fd.write(", JS::Value a%s" % firstCap(a.name)); + elif a.realtype.nativeType('in').endswith('*'): + fd.write(", %s* a%s" % (xpidl_to_native(a.realtype.nativeType('in').strip('* '), conf), firstCap(a.name))) + elif a.realtype.nativeType('in').count("nsAString"): + fd.write(", const nsAString& a%s" % firstCap(a.name)) + elif a.realtype.nativeType('in').count("nsACString"): + fd.write(", const nsACString& a%s" % firstCap(a.name)) + else: + fd.write(", %s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) + +def write_cpp(eventname, iface, fd, conf): + classname = ("%s" % eventname) + basename = getBaseName(iface) attributes = [] ccattributes = [] for member in iface.members: @@ -235,31 +380,23 @@ def write_cpp(eventname, iface, fd): if isinstance(member, xpidl.Attribute): baseattributes.append(member) + allattributes = [] + allattributes.extend(baseattributes); + allattributes.extend(attributes); - fd.write("\nclass %s : public %s, public %s\n" % (classname, basename, iface.name)) - fd.write("{\n") - fd.write("public:\n") - fd.write(" %s(mozilla::dom::EventTarget* aOwner, " % classname) - fd.write("nsPresContext* aPresContext = nullptr, nsEvent* aEvent = nullptr)\n"); - fd.write(" : %s(aOwner, aPresContext, aEvent)" % basename) + fd.write("namespace mozilla {\n") + fd.write("namespace dom {\n\n") + + fd.write("%s::%s(mozilla::dom::EventTarget* aOwner, " % (classname, classname)) + fd.write("nsPresContext* aPresContext, nsEvent* aEvent)\n"); + fd.write(": %s(aOwner, aPresContext, aEvent)" % basename) for a in attributes: - fd.write(",\n m%s(%s)" % (firstCap(a.name), init_value(a))) - fd.write("\n {}\n") - fd.write(" virtual ~%s() {}\n\n" % classname) - fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") - fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) - fd.write(" NS_FORWARD_TO_NSDOMEVENT\n") + fd.write(",\n m%s(%s)" % (firstCap(a.name), init_value(a))) + fd.write("\n{\n") + fd.write(" SetIsDOMBinding();\n") + fd.write("}\n\n") - for baseiface in baseinterfaces: - baseimpl = ("ns%s" % baseiface.name[3:]) - fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) - - fd.write(" NS_DECL_%s\n" % iface.name.upper()) - fd.write(" virtual nsresult InitFromCtor(const nsAString& aType, JSContext* aCx, jsval* aVal);\n") - fd.write("protected:\n") - for a in attributes: - fd.write(" %s\n" % attributeVariableTypeAndName(a)) - fd.write("};\n\n") + fd.write("%s::~%s() {}\n\n" % (classname, classname)) fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(%s, %s)\n" % (classname, basename)) for c in ccattributes: @@ -272,8 +409,11 @@ def write_cpp(eventname, iface, fd): fd.write("NS_IMPL_ADDREF_INHERITED(%s, %s)\n" % (classname, basename)) fd.write("NS_IMPL_RELEASE_INHERITED(%s, %s)\n\n" % (classname, basename)) - - fd.write("DOMCI_DATA(%s, %s)\n\n" % (eventname, classname)) + fd.write("} // namespace dom\n") + fd.write("} // namespace mozilla\n\n") + fd.write("DOMCI_DATA(%s, mozilla::dom::%s)\n\n" % (eventname, classname)) + fd.write("namespace mozilla {\n") + fd.write("namespace dom {\n\n") fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(%s)\n" % classname) fd.write(" NS_INTERFACE_MAP_ENTRY(nsIDOM%s)\n" % eventname) @@ -287,22 +427,46 @@ def write_cpp(eventname, iface, fd): fd.write(" nsresult rv = d.Init(aCx, aVal);\n") fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n") fd.write(" return Init%s(aType, d.bubbles, d.cancelable" % eventname) - for a in baseattributes: - fd.write(", d.%s" % a.name) - for a in attributes: + for a in allattributes: fd.write(", d.%s" % a.name) fd.write(");\n") fd.write("}\n\n") + hasVariant = False + for a in allattributes: + if a.type == "nsIVariant": + hasVariant = True + break; + + fd.write("already_AddRefed<%s>\n" % eventname) + fd.write("%s::Constructor(const GlobalObject& aGlobal, " % eventname) + if hasVariant: + fd.write("JSContext* aCx, "); + fd.write("const nsAString& aType, ") + fd.write("const %sInit& aParam, " % eventname) + fd.write("ErrorResult& aRv)\n") + fd.write("{\n") + fd.write(" nsCOMPtr t = do_QueryInterface(aGlobal.Get());\n") + fd.write(" nsRefPtr<%s> e = new %s(t, nullptr, nullptr);\n" % (eventname, eventname)) + fd.write(" bool trusted = e->Init(t);\n") + fd.write(" e->Init%s(" % eventname) + if hasVariant: + fd.write("aCx, "); + fd.write("aType, aParam.mBubbles, aParam.mCancelable") + for a in allattributes: + fd.write(", aParam.m%s" % firstCap(a.name)) + fd.write(", aRv);\n") + fd.write(" e->SetTrusted(trusted);\n") + fd.write(" return e.forget();\n") + fd.write("}\n\n") + fd.write("NS_IMETHODIMP\n") fd.write("%s::Init%s(" % (classname, eventname)) fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") - for a in baseattributes: - writeAttributeParams(fd, a) - for a in attributes: + for a in allattributes: writeAttributeParams(fd, a) fd.write(")\n{\n") - fd.write(" nsresult rv = %s::Init%s(aType, aCanBubble, aCancelable" % (basename, basename[5:])) + fd.write(" nsresult rv = %s::Init%s(aType, aCanBubble, aCancelable" % (basename, ("%s" % iface.base[6:]))) for a in baseattributes: fd.write(", a%s" % firstCap(a.name)) fd.write(");\n"); @@ -312,17 +476,249 @@ def write_cpp(eventname, iface, fd): fd.write(" return NS_OK;\n") fd.write("}\n\n") + fd.write("void\n") + fd.write("%s::Init%s(" % (classname, eventname)) + if hasVariant: + fd.write("JSContext* aCx, ") + fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") + for a in allattributes: + writeNativeAttributeParams(fd, a, conf) + fd.write(", ErrorResult& aRv") + fd.write(")\n") + fd.write("{\n"); + for a in allattributes: + if a.type == "nsIVariant": + fd.write(" nsCOMPtr %s = dont_AddRef(XPCVariant::newVariant(aCx, a%s));\n" % (a.name, firstCap(a.name))) + fd.write(" if (!%s) {\n" % a.name) + fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") + fd.write(" return;\n") + fd.write(" }\n") + elif a.realtype.nativeType('in').endswith('*'): + xpidl_t = a.realtype.nativeType('in').strip('* ') + native_t = xpidl_to_native(xpidl_t, conf) + if xpidl_t != native_t: + fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(static_cast<%s*>(a%s));\n" % (xpidl_t, a.name, xpidl_to_canonical(xpidl_t, conf), firstCap(a.name))) + fd.write(" aRv = Init%s(" % classname); + fd.write("aType, aCanBubble, aCancelable") + for a in allattributes: + if a.realtype.nativeType('in').endswith('*'): + xpidl_t = a.realtype.nativeType('in').strip('* ') + native_t = xpidl_to_native(xpidl_t, conf) + if xpidl_t != native_t or a.type == "nsIVariant": + fd.write(", %s" % a.name) + continue + fd.write(", a%s" % firstCap(a.name)) + fd.write(");\n}\n\n"); + for a in attributes: writeAttributeGetter(fd, classname, a) + fd.write("} // namespace dom\n") + fd.write("} // namespace mozilla\n\n") + fd.write("nsresult\n") fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % eventname) fd.write("mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext = nullptr, nsEvent* aEvent = nullptr)\n") fd.write("{\n") - fd.write(" %s* it = new %s(aOwner, aPresContext, aEvent);\n" % (classname, classname)) + fd.write(" mozilla::dom::%s* it = new mozilla::dom::%s(aOwner, aPresContext, aEvent);\n" % (classname, classname)) fd.write(" return CallQueryInterface(it, aInstance);\n") fd.write("}\n\n") +def toWebIDLType(attribute, inType=False, onlyInterface=False): + if attribute.type == "nsIVariant": + return "any"; + if attribute.type == "nsISupports": + return "%s%s" % (attribute.type, "" if onlyInterface else "?") + if attribute.type.count("nsIDOM"): + return "%s%s" % (attribute.type[6:], "" if onlyInterface else "?") + if attribute.type.count("nsI"): + return "%s%s" % (attribute.type[3:], "" if onlyInterface else "?") + if attribute.realtype.nativeType('in').endswith('*') or attribute.realtype.nativeType('in').count("nsAString"): + return "%s%s" % (attribute.type, "" if onlyInterface else "?") + return attribute.type + +def write_webidl(eventname, iface, fd, conf, idl): + basename = ("%s" % iface.base[6:]) + attributes = [] + ccattributes = [] + consts = [] + hasInit = False + initMethod = "init%s" % eventname; + for member in iface.members: + if isinstance(member, xpidl.Attribute): + attributes.append(member) + if (member.realtype.nativeType('in').endswith('*')): + ccattributes.append(member); + elif isinstance(member, xpidl.Method) and member.name == initMethod: + if not member.noscript and not member.notxpcom: + hasInit = True + elif isinstance(member, xpidl.ConstMember): + consts.append(member); + else: + raise BaseException("Unsupported idl member %s::%s" % (eventname, member.name)) + + baseinterfaces = [] + baseiface = iface.idl.getName(iface.base, iface.location) + while baseiface.name != "nsIDOMEvent": + baseinterfaces.append(baseiface) + baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) + baseinterfaces.reverse() + + allattributes = [] + for baseiface in baseinterfaces: + for member in baseiface.members: + if isinstance(member, xpidl.Attribute): + allattributes.append(member) + allattributes.extend(attributes) + + fd.write( +"""/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ +""") + + neededInterfaces = [] + for a in attributes: + if a.realtype.nativeType('in').endswith('*'): + nativeType = a.realtype.nativeType('in').strip('* ') + mappingForWebIDL = False + for xp in conf.xpidl_to_native: + if xp[0] == nativeType: + mappingForWebIDL = True + break; + if not mappingForWebIDL: + webidlType = toWebIDLType(a, False, True) + if (not webidlType in neededInterfaces and webidlType != "any"): + neededInterfaces.append(webidlType); + + for i in neededInterfaces: + fd.write("interface %s;\n" % i) + + fd.write("\n"); + fd.write("[Constructor(DOMString type, optional %sInit eventInitDict), HeaderFile=\"GeneratedEventClasses.h\"]\n" % eventname); + fd.write("interface %s : %s\n" % (eventname, basename)) + fd.write("{\n") + + for c in consts: + fd.write(" const %s %s = %s;\n" % (c.type, c.name, c.getValue())) + if len(consts): + fd.write("\n") + + for a in attributes: + if a.realtype.nativeType('in').count("nsIVariant"): + fd.write(" [Throws]\n") + fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) + elif a.realtype.nativeType('in').endswith('*') or a.realtype.nativeType('in').count("nsAString"): + fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) + else: + fd.write(" readonly attribute %s %s;\n" % (a.type, a.name)) + if hasInit: + fd.write("\n [Throws]\n") + m = " void %s(" % initMethod + fd.write(m) + indent = "".join(" " for i in range(len(m))) + indent = ",\n%s" % indent + fd.write("DOMString type") + fd.write(indent); + fd.write("boolean canBubble") + fd.write(indent); + fd.write("boolean cancelable") + for a in baseattributes + attributes: + fd.write(indent); + fd.write("%s %s" % (toWebIDLType(a, True), a.name)) + fd.write(");\n"); + fd.write("};\n\n") + + dname = "%sInit" % eventname + for p in idl.productions: + if p.kind == "dictionary" and p.name == dname: + fd.write("dictionary %s : %sInit\n" % (dname, basename)) + fd.write("{\n") + # We want to keep the same ordering what interface has. + for ifaceattribute in attributes: + for member in p.members: + if member.name == ifaceattribute.name: + a = member + if a.realtype.nativeType('in').endswith('*'): + fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) + elif a.realtype.nativeType('in').count("nsAString"): + if a.defvalue is None: + if a.nullable: + fd.write(" %s? %s = null;\n" % (a.type, a.name)) + else: + fd.write(" %s %s = \"\";\n" % (a.type, a.name)) + else: + if a.nullable: + fd.write(" %s? %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) + else: + fd.write(" %s %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) + else: + if a.defvalue is None: + if a.type == "boolean": + fd.write(" %s %s = false;\n" % (a.type, a.name)) + else: + fd.write(" %s %s = 0;\n" % (a.type, a.name)) + # Infinity is not supported by all the types, but + # WebIDL parser will then complain about the wrong values. + elif a.defvalue == "Infinity": + fd.write(" unrestricted %s %s = Infinity;\n" % (a.type, a.name)) + elif a.defvalue == "-Infinity": + fd.write(" unrestricted %s %s = -Infinity;\n" % (a.type, a.name)) + else: + fd.write(" %s %s = %s;\n" % (a.type, a.name, a.defvalue)) + continue + fd.write("};\n") + return + + # There is no dictionary defined in the .idl file. Generate one based on + # the interface. + fd.write("dictionary %s : %sInit\n" % (dname, basename)) + fd.write("{\n") + for a in attributes: + if a.realtype.nativeType('in').endswith('*'): + fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) + elif a.realtype.nativeType('in').count("nsAString"): + fd.write(" %s? %s = \"\";\n" % (a.type, a.name)) + elif a.type == "boolean": + fd.write(" %s %s = false;\n" % (a.type, a.name)) + else: + fd.write(" %s %s = 0;\n" % (a.type, a.name)) + fd.write("};\n") + +def print_webidl_file(idl, fd, conf, eventname): + for p in idl.productions: + if p.kind == 'interface': + write_webidl(eventname, p, fd, conf, idl) + +def xpidl_to_native(xpidl, conf): + for x in conf.xpidl_to_native: + if x[0] == xpidl: + return x[1] + return xpidl + +def xpidl_to_canonical(xpidl, conf): + for x in conf.xpidl_to_native: + if x[0] == xpidl: + return x[2] + return xpidl + +def native_to_xpidl(native, conf): + for x in conf.xpidl_to_native: + if x[1] == native: + return x[0] + return native + +def print_webidl_files(webidlDir, conf): + for e in conf.simple_events: + idl = loadEventIDL(p, options.incdirs, e) + webidl = "%s/%s.webidl" % (webidlDir, e) + if not os.path.exists(webidl): + fd = open(webidl, 'w') + print_webidl_file(idl, fd, conf, e) + fd.close(); + if __name__ == '__main__': from optparse import OptionParser o = OptionParser(usage="usage: %prog [options] configfile") @@ -337,6 +733,10 @@ if __name__ == '__main__': help="gnumake dependencies output file", metavar="FILE") o.add_option('--cachedir', dest='cachedir', default=None, help="Directory in which to cache lex/parse tables.") + o.add_option('--class-declarations', type='string', default=None, + help="Class declarations", metavar="FILE") + o.add_option('--webidltarget', dest='webidltarget', default=None, + help="Directory in which to store generated WebIDL files.") (options, filenames) = o.parse_args() if len(filenames) != 1: o.error("Exactly one config filename is needed.") @@ -352,6 +752,14 @@ if __name__ == '__main__': conf = readConfigFile(filename) + if options.header_output is not None: + outfd = open(options.header_output, 'w') + print_header_file(outfd, conf) + outfd.close() + if options.class_declarations is not None: + outfd = open(options.class_declarations, 'w') + print_classes_file(outfd, conf) + outfd.close() if options.stub_output is not None: makeutils.targets.append(options.stub_output) outfd = open(options.stub_output, 'w') @@ -359,8 +767,7 @@ if __name__ == '__main__': outfd.close() if options.makedepend_output is not None: makeutils.writeMakeDependOutput(options.makedepend_output) - if options.header_output is not None: - outfd = open(options.header_output, 'w') - print_header_file(outfd, conf) - outfd.close() + + if options.webidltarget is not None: + print_webidl_files(options.webidltarget, conf) From f1dc3f5c2d615c28ca6008709933d55861c1ff21 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 18 Jun 2013 12:22:56 -0700 Subject: [PATCH 401/615] Bug 879809 - Don't export MOZBUILD_BACKEND_CHECKED to independent build systems; r=ted --- config/rules.mk | 20 ++++++++++---------- js/src/config/rules.mk | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/config/rules.mk b/config/rules.mk index 5f97168a1a3a..deb86b3e8dce 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -416,15 +416,20 @@ ifdef MOZ_UPDATE_XTERM UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2) ; endif -define SUBMAKE # $(call SUBMAKE,target,directory) +# Static directories are largely independent of our build system. But, they +# could share the same build mechanism (like moz.build files). We need to +# prevent leaking of our backend state to these independent build systems. This +# is why MOZBUILD_BACKEND_CHECKED isn't exported to make invocations for static +# directories. +define SUBMAKE # $(call SUBMAKE,target,directory,static) +@$(UPDATE_TITLE) -+$(MAKE) $(if $(2),-C $(2)) $(1) ++$(if $(3), MOZBUILD_BACKEND_CHECKED=,) $(MAKE) $(if $(2),-C $(2)) $(1) endef # The extra line is important here! don't delete it define TIER_DIR_SUBMAKE @echo "BUILDSTATUS TIERDIR_START $(2)" -$(call SUBMAKE,$(1),$(2)) +$(call SUBMAKE,$(1),$(2),$(3)) @echo "BUILDSTATUS TIERDIR_FINISH $(2)" endef # Ths empty line is important. @@ -441,11 +446,6 @@ LOOP_OVER_PARALLEL_DIRS = \ $(foreach dir,$(PARALLEL_DIRS),$(call SUBMAKE,$@,$(dir))) endif -ifneq (,$(strip $(STATIC_DIRS))) -LOOP_OVER_STATIC_DIRS = \ - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - ifneq (,$(strip $(TOOL_DIRS))) LOOP_OVER_TOOL_DIRS = \ $(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir))) @@ -671,7 +671,7 @@ else default all:: ifneq (,$(strip $(STATIC_DIRS))) - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir))) + $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir),1)) endif $(MAKE) export $(MAKE) libs @@ -715,7 +715,7 @@ endif @echo "BUILDSTATUS DIRS $$($$@_dirs)" ifneq (,$(tier_$(1)_staticdirs)) @echo "BUILDSTATUS SUBTIER_START $(1) static" - $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir))) + $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) @echo "BUILDSTATUS SUBTIER_FINISH $(1) static" endif ifneq (,$(tier_$(1)_dirs)) diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 5f97168a1a3a..deb86b3e8dce 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -416,15 +416,20 @@ ifdef MOZ_UPDATE_XTERM UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(2) ; endif -define SUBMAKE # $(call SUBMAKE,target,directory) +# Static directories are largely independent of our build system. But, they +# could share the same build mechanism (like moz.build files). We need to +# prevent leaking of our backend state to these independent build systems. This +# is why MOZBUILD_BACKEND_CHECKED isn't exported to make invocations for static +# directories. +define SUBMAKE # $(call SUBMAKE,target,directory,static) +@$(UPDATE_TITLE) -+$(MAKE) $(if $(2),-C $(2)) $(1) ++$(if $(3), MOZBUILD_BACKEND_CHECKED=,) $(MAKE) $(if $(2),-C $(2)) $(1) endef # The extra line is important here! don't delete it define TIER_DIR_SUBMAKE @echo "BUILDSTATUS TIERDIR_START $(2)" -$(call SUBMAKE,$(1),$(2)) +$(call SUBMAKE,$(1),$(2),$(3)) @echo "BUILDSTATUS TIERDIR_FINISH $(2)" endef # Ths empty line is important. @@ -441,11 +446,6 @@ LOOP_OVER_PARALLEL_DIRS = \ $(foreach dir,$(PARALLEL_DIRS),$(call SUBMAKE,$@,$(dir))) endif -ifneq (,$(strip $(STATIC_DIRS))) -LOOP_OVER_STATIC_DIRS = \ - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,$@,$(dir))) -endif - ifneq (,$(strip $(TOOL_DIRS))) LOOP_OVER_TOOL_DIRS = \ $(foreach dir,$(TOOL_DIRS),$(call SUBMAKE,$@,$(dir))) @@ -671,7 +671,7 @@ else default all:: ifneq (,$(strip $(STATIC_DIRS))) - $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir))) + $(foreach dir,$(STATIC_DIRS),$(call SUBMAKE,,$(dir),1)) endif $(MAKE) export $(MAKE) libs @@ -715,7 +715,7 @@ endif @echo "BUILDSTATUS DIRS $$($$@_dirs)" ifneq (,$(tier_$(1)_staticdirs)) @echo "BUILDSTATUS SUBTIER_START $(1) static" - $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir))) + $$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1)) @echo "BUILDSTATUS SUBTIER_FINISH $(1) static" endif ifneq (,$(tier_$(1)_dirs)) From 257553f813aea225a7ea1247d4c2032f0fceed2a Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Tue, 18 Jun 2013 15:49:14 -0400 Subject: [PATCH 402/615] Bug 880650 - Clean up hiding/showing VKB in the awesome screen; r=cpeterson --- mobile/android/base/AndroidManifest.xml.in | 2 +- mobile/android/base/AwesomeBar.java | 8 ++------ mobile/android/base/AwesomeBarTabs.java | 1 - .../android/base/resources/layout/awesomebar_search.xml | 1 - 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in index 7104da143c35..e5ec47c8d1b6 100644 --- a/mobile/android/base/AndroidManifest.xml.in +++ b/mobile/android/base/AndroidManifest.xml.in @@ -229,7 +229,7 @@ + android:windowSoftInputMode="stateUnspecified|adjustResize"/> - Date: Tue, 18 Jun 2013 15:49:14 -0400 Subject: [PATCH 403/615] Bug 880650 - Add selectAll call to URL bar initialization; r=cpeterson --- mobile/android/base/AwesomeBar.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/android/base/AwesomeBar.java b/mobile/android/base/AwesomeBar.java index f71a9ce0a6fb..bfc0de266fdd 100644 --- a/mobile/android/base/AwesomeBar.java +++ b/mobile/android/base/AwesomeBar.java @@ -142,6 +142,7 @@ public class AwesomeBar extends GeckoActivity String currentUrl = intent.getStringExtra(CURRENT_URL_KEY); if (currentUrl != null) { mText.setText(currentUrl); + mText.selectAll(); } mTarget = intent.getStringExtra(TARGET_KEY); From d8d660431d7e4088a45e9687f114105839b10285 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Tue, 18 Jun 2013 15:49:14 -0400 Subject: [PATCH 404/615] Bug 880650 - Don't try to dismiss VKB during testBookmarksTab; r=adrian.tamas --- mobile/android/base/tests/BaseTest.java.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/mobile/android/base/tests/BaseTest.java.in b/mobile/android/base/tests/BaseTest.java.in index 21573e996e9c..c6593fcbe784 100644 --- a/mobile/android/base/tests/BaseTest.java.in +++ b/mobile/android/base/tests/BaseTest.java.in @@ -692,7 +692,6 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { mActions.sendKeys(addedText); mSolo.clickOnText("OK"); waitForText("Bookmark updated"); - toggleVKB(); // close the VKB } public boolean checkBookmarkEdit(int bookmarkIndex, String addedText, ListView list) { @@ -712,12 +711,10 @@ abstract class BaseTest extends ActivityInstrumentationTestCase2 { if (mSolo.searchText(addedText)) { clickOnButton("Cancel"); waitForText("about:home"); - toggleVKB(); // close the VKB return true; } else { clickOnButton("Cancel"); waitForText("about:home"); - toggleVKB(); // close the VKB return false; } } From b07368ea2ef4b6959678ae1af1d624bf14b5c754 Mon Sep 17 00:00:00 2001 From: Wan-Teh Chang Date: Tue, 18 Jun 2013 13:01:22 -0700 Subject: [PATCH 405/615] Bug 881841: update to NSS_3_15_1_BETA2. r=wtc. --- security/nss/TAG-INFO | 2 +- security/nss/cmd/certutil/certutil.c | 7 +- security/nss/cmd/checkcert/checkcert.c | 6 +- security/nss/cmd/crlutil/crlutil.c | 6 +- security/nss/cmd/derdump/derdump.c | 2 +- security/nss/cmd/lib/secutil.c | 10 +- security/nss/cmd/lib/secutil.h | 3 +- .../libpkix/pkix/top/test_validatechain_bc.c | 2 +- .../nss/cmd/libpkix/sample_apps/build_chain.c | 2 +- .../nss/cmd/libpkix/sample_apps/dumpcert.c | 2 +- .../nss/cmd/libpkix/sample_apps/dumpcrl.c | 2 +- .../cmd/libpkix/sample_apps/validate_chain.c | 2 +- .../nss/cmd/libpkix/testutil/testutil_nss.c | 4 +- security/nss/cmd/ocspclnt/ocspclnt.c | 2 +- security/nss/cmd/p7content/p7content.c | 2 +- security/nss/cmd/p7sign/p7sign.c | 5 +- security/nss/cmd/p7verify/p7verify.c | 3 +- security/nss/cmd/pk1sign/pk1sign.c | 3 +- security/nss/cmd/pp/pp.c | 2 +- security/nss/cmd/selfserv/selfserv.c | 2 +- security/nss/cmd/shlibsign/shlibsign.c | 8 +- security/nss/cmd/signver/signver.c | 2 +- security/nss/cmd/vfychain/vfychain.c | 2 +- security/nss/coreconf/coreconf.dep | 1 - security/nss/lib/freebl/win_rand.c | 73 +--- .../nss/lib/libpkix/pkix/top/pkix_build.c | 23 +- security/nss/lib/pk11wrap/secmod.h | 2 +- security/nss/lib/ssl/config.mk | 4 - security/nss/lib/ssl/derive.c | 65 +++- security/nss/lib/ssl/ssl3con.c | 335 +++++++++--------- security/nss/lib/ssl/sslimpl.h | 35 +- security/nss/lib/ssl/sslsock.c | 9 +- .../chains/scenarios/nameconstraints.cfg | 22 ++ security/nss/tests/chains/scenarios/scenarios | 1 + .../libpkix/certs/NameConstraints.ca.cert | Bin 0 -> 626 bytes .../certs/NameConstraints.intermediate.cert | Bin 0 -> 662 bytes .../certs/NameConstraints.server1.cert | Bin 0 -> 660 bytes .../certs/NameConstraints.server2.cert | Bin 0 -> 643 bytes .../certs/NameConstraints.server3.cert | Bin 0 -> 660 bytes security/nss/tests/libpkix/certs/make-nc | 103 ++++++ 40 files changed, 450 insertions(+), 304 deletions(-) create mode 100644 security/nss/tests/chains/scenarios/nameconstraints.cfg create mode 100644 security/nss/tests/libpkix/certs/NameConstraints.ca.cert create mode 100644 security/nss/tests/libpkix/certs/NameConstraints.intermediate.cert create mode 100644 security/nss/tests/libpkix/certs/NameConstraints.server1.cert create mode 100644 security/nss/tests/libpkix/certs/NameConstraints.server2.cert create mode 100644 security/nss/tests/libpkix/certs/NameConstraints.server3.cert create mode 100755 security/nss/tests/libpkix/certs/make-nc diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index f5742036e806..4c0a6b7adcd8 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_15_1_BETA1 +NSS_3_15_1_BETA2 diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index ba62799eec88..6603e80e1068 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -3158,7 +3158,8 @@ merge_fail: certutil.commands[cmd_AddEmailCert].activated) { PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated; rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile, - certutil.options[opt_ASCIIForIO].activated); + certutil.options[opt_ASCIIForIO].activated, + PR_TRUE); if (rv) goto shutdown; } @@ -3229,6 +3230,10 @@ merge_fail: if (certutil.commands[cmd_CreateAndAddCert].activated || certutil.commands[cmd_AddCert].activated || certutil.commands[cmd_AddEmailCert].activated) { + if (strstr(certutil.options[opt_Trust].arg, "u")) { + fprintf(stderr, "Notice: Trust flag u is set automatically if the " + "private key is present.\n"); + } rv = AddCert(slot, certHandle, name, certutil.options[opt_Trust].arg, &certDER, diff --git a/security/nss/cmd/checkcert/checkcert.c b/security/nss/cmd/checkcert/checkcert.c index 0cdd2cc28291..63beea5876ed 100644 --- a/security/nss/cmd/checkcert/checkcert.c +++ b/security/nss/cmd/checkcert/checkcert.c @@ -302,7 +302,7 @@ int main(int argc, char **argv) exit(1); } - if (SECU_ReadDERFromFile(&derCert, inFile, ascii) != SECSuccess) { + if (SECU_ReadDERFromFile(&derCert, inFile, ascii, PR_FALSE) != SECSuccess) { printf("Couldn't read input certificate as DER binary or base64\n"); exit(1); } @@ -315,8 +315,8 @@ int main(int argc, char **argv) if (issuerCertFile) { CERTSignedData *issuerCertSD=0; - if (SECU_ReadDERFromFile(&derIssuerCert, issuerCertFile, issuerAscii) - != SECSuccess) { + if (SECU_ReadDERFromFile(&derIssuerCert, issuerCertFile, issuerAscii, + PR_FALSE) != SECSuccess) { printf("Couldn't read issuer certificate as DER binary or base64.\n"); exit(1); } diff --git a/security/nss/cmd/crlutil/crlutil.c b/security/nss/cmd/crlutil/crlutil.c index 301746b5d116..dd9f4932eec2 100644 --- a/security/nss/cmd/crlutil/crlutil.c +++ b/security/nss/cmd/crlutil/crlutil.c @@ -232,7 +232,7 @@ SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, /* Read in the entire file specified with the -f argument */ - rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); @@ -291,7 +291,7 @@ SECStatus DumpCRL(PRFileDesc *inFile) crlDER.data = NULL; /* Read in the entire file specified with the -f argument */ - rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); @@ -386,7 +386,7 @@ CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle, } if (inFile != NULL) { - rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); PORT_FreeArena(modArena, PR_FALSE); diff --git a/security/nss/cmd/derdump/derdump.c b/security/nss/cmd/derdump/derdump.c index 49d415c1ce7a..3184b1b48b9d 100644 --- a/security/nss/cmd/derdump/derdump.c +++ b/security/nss/cmd/derdump/derdump.c @@ -87,7 +87,7 @@ int main(int argc, char **argv) return -1; } - rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE, PR_FALSE); if (rv == SECSuccess) { rv = DER_PrettyPrint(outFile, &der, raw); if (rv == SECSuccess) diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index 4b22702502a2..96273daa0fb9 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -494,7 +494,8 @@ SECU_GetClientAuthData(void *arg, PRFileDesc *fd, } SECStatus -SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) +SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii, + PRBool warnOnPrivateKeyInAsciiFile) { SECStatus rv; if (ascii) { @@ -512,6 +513,11 @@ SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii) return SECFailure; } + if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) { + fprintf(stderr, "Warning: ignoring private key. Consider to use " + "pk12util.\n"); + } + /* check for headers and trailers and remove them */ if ((body = strstr(asc, "-----BEGIN")) != NULL) { char *trailer = NULL; @@ -3551,7 +3557,7 @@ SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle, if (!fd) { return NULL; } - rv = SECU_ReadDERFromFile(&item, fd, ascii); + rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE); PR_Close(fd); if (rv != SECSuccess || !item.len) { PORT_Free(item.data); diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h index 022a4d5a8773..71a7f59b8cf5 100644 --- a/security/nss/cmd/lib/secutil.h +++ b/security/nss/cmd/lib/secutil.h @@ -160,7 +160,8 @@ SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log, /* Read in a DER from a file, may be ascii */ extern SECStatus -SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii); +SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii, + PRBool warnOnPrivateKeyInAsciiFile); /* Print integer value and hex */ extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, diff --git a/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c index 29e483f4f26d..cbbfd73a3146 100644 --- a/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c +++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c @@ -61,7 +61,7 @@ createCert(char *inFileName) pkixTestErrorMsg = "Unable to open cert file"; goto cleanup; } else { - rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; diff --git a/security/nss/cmd/libpkix/sample_apps/build_chain.c b/security/nss/cmd/libpkix/sample_apps/build_chain.c index 11f3005f79af..fa717d9ae5a1 100644 --- a/security/nss/cmd/libpkix/sample_apps/build_chain.c +++ b/security/nss/cmd/libpkix/sample_apps/build_chain.c @@ -66,7 +66,7 @@ createCert(char *inFileName) pkixTestErrorMsg = "Unable to open cert file"; goto cleanup; } else { - rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcert.c b/security/nss/cmd/libpkix/sample_apps/dumpcert.c index 4ee14d695709..55350776356a 100644 --- a/security/nss/cmd/libpkix/sample_apps/dumpcert.c +++ b/security/nss/cmd/libpkix/sample_apps/dumpcert.c @@ -55,7 +55,7 @@ createCert(char *inFileName) printFailure("Unable to open cert file"); goto cleanup; } else { - rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcrl.c b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c index 1f2522ec1a26..cfb84bd4adf6 100644 --- a/security/nss/cmd/libpkix/sample_apps/dumpcrl.c +++ b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c @@ -57,7 +57,7 @@ createCRL(char *inFileName) printFailure("Unable to open crl file"); goto cleanup; } else { - rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)crlDER.data; len = crlDER.len; diff --git a/security/nss/cmd/libpkix/sample_apps/validate_chain.c b/security/nss/cmd/libpkix/sample_apps/validate_chain.c index d9c2a229c2d9..56343a6f6ea4 100644 --- a/security/nss/cmd/libpkix/sample_apps/validate_chain.c +++ b/security/nss/cmd/libpkix/sample_apps/validate_chain.c @@ -65,7 +65,7 @@ createCert(char *inFileName) pkixTestErrorMsg = "Unable to open cert file"; goto cleanup; } else { - rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; diff --git a/security/nss/cmd/libpkix/testutil/testutil_nss.c b/security/nss/cmd/libpkix/testutil/testutil_nss.c index 666190c42c13..4f7cc4096696 100755 --- a/security/nss/cmd/libpkix/testutil/testutil_nss.c +++ b/security/nss/cmd/libpkix/testutil/testutil_nss.c @@ -89,7 +89,7 @@ createCert( pkixTestErrorMsg = "Unable to open cert file"; goto cleanup; } else { - rv = SECU_ReadDERFromFile(&certDER, certFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&certDER, certFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; @@ -154,7 +154,7 @@ createCRL( pkixTestErrorMsg = "Unable to open crl file"; goto cleanup; } else { - rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (!rv){ buf = (void *)crlDER.data; len = crlDER.len; diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c index ea2a4ce3a781..e302bb5b83ed 100644 --- a/security/nss/cmd/ocspclnt/ocspclnt.c +++ b/security/nss/cmd/ocspclnt/ocspclnt.c @@ -485,7 +485,7 @@ find_certificate(CERTCertDBHandle *handle, const char *name, PRBool ascii) return NULL; } - if (SECU_ReadDERFromFile(&der, certFile, ascii) == SECSuccess) { + if (SECU_ReadDERFromFile(&der, certFile, ascii, PR_FALSE) == SECSuccess) { cert = CERT_DecodeCertFromPackage((char*)der.data, der.len); SECITEM_FreeItem(&der, PR_FALSE); } diff --git a/security/nss/cmd/p7content/p7content.c b/security/nss/cmd/p7content/p7content.c index 59c0ff2cc78f..15f725397a56 100644 --- a/security/nss/cmd/p7content/p7content.c +++ b/security/nss/cmd/p7content/p7content.c @@ -78,7 +78,7 @@ DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName) SEC_PKCS7ContentInfo *cinfo = NULL; SEC_PKCS7DecoderContext *dcx; - if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE)) { + if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE, PR_FALSE)) { SECU_PrintError(progName, "error converting der"); return -1; } diff --git a/security/nss/cmd/p7sign/p7sign.c b/security/nss/cmd/p7sign/p7sign.c index df664df1cfc3..d41e1c762b17 100644 --- a/security/nss/cmd/p7sign/p7sign.c +++ b/security/nss/cmd/p7sign/p7sign.c @@ -96,7 +96,8 @@ SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, return -1; /* suck the file in */ - if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess) + if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE, + PR_FALSE) != SECSuccess) return -1; if (!encapsulated) { @@ -147,7 +148,7 @@ main(int argc, char **argv) PRFileDesc *inFile; char *keyName = NULL; CERTCertDBHandle *certHandle; - CERTCertificate *cert; + CERTCertificate *cert = NULL; PRBool encapsulated = PR_FALSE; PLOptState *optstate; PLOptStatus status; diff --git a/security/nss/cmd/p7verify/p7verify.c b/security/nss/cmd/p7verify/p7verify.c index 5394a51891c0..1d87ac39ec83 100644 --- a/security/nss/cmd/p7verify/p7verify.c +++ b/security/nss/cmd/p7verify/p7verify.c @@ -133,7 +133,8 @@ HashDecodeAndVerify(FILE *out, FILE *content, PRFileDesc *signature, SECItem digest; unsigned char buffer[32]; - if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE) != SECSuccess) { + if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE, + PR_FALSE) != SECSuccess) { SECU_PrintError(progName, "error reading signature file"); return -1; } diff --git a/security/nss/cmd/pk1sign/pk1sign.c b/security/nss/cmd/pk1sign/pk1sign.c index 291388bd70cc..5750cdb2d981 100644 --- a/security/nss/cmd/pk1sign/pk1sign.c +++ b/security/nss/cmd/pk1sign/pk1sign.c @@ -116,7 +116,8 @@ SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert) return -1; /* suck the file in */ - if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess) + if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE, + PR_FALSE) != SECSuccess) return -1; privKey = NULL; diff --git a/security/nss/cmd/pp/pp.c b/security/nss/cmd/pp/pp.c index ab58c8747f33..1e84889f6cff 100644 --- a/security/nss/cmd/pp/pp.c +++ b/security/nss/cmd/pp/pp.c @@ -105,7 +105,7 @@ int main(int argc, char **argv) } SECU_RegisterDynamicOids(); - rv = SECU_ReadDERFromFile(&der, inFile, ascii); + rv = SECU_ReadDERFromFile(&der, inFile, ascii, PR_FALSE); if (rv != SECSuccess) { fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName); exit(1); diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index c757a1c28b5c..11f301558d9a 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -1028,7 +1028,7 @@ reload_crl(PRFileDesc *crlFile) return SECFailure; } - rv = SECU_ReadDERFromFile(crlDer, crlFile, PR_FALSE); + rv = SECU_ReadDERFromFile(crlDer, crlFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { errWarn("Unable to read input file."); PORT_Free(crlDer); diff --git a/security/nss/cmd/shlibsign/shlibsign.c b/security/nss/cmd/shlibsign/shlibsign.c index 82087b5db0be..51604414fd10 100644 --- a/security/nss/cmd/shlibsign/shlibsign.c +++ b/security/nss/cmd/shlibsign/shlibsign.c @@ -701,6 +701,7 @@ int main(int argc, char **argv) int i; PRBool verify = PR_FALSE; static PRBool FIPSMODE = PR_FALSE; + PRBool successful = PR_FALSE; #ifdef USES_LINKS int ret; @@ -1245,6 +1246,8 @@ int main(int argc, char **argv) } #endif + successful = PR_TRUE; + cleanup: if (pFunctionList) { /* C_Finalize will automatically logout, close session, */ @@ -1281,5 +1284,8 @@ cleanup: } PR_Cleanup(); - return crv; + if (crv != CKR_OK) + return crv; + + return (successful) ? 0 : 1; } diff --git a/security/nss/cmd/signver/signver.c b/security/nss/cmd/signver/signver.c index cc9aaeb600a7..cd63a3c88d36 100644 --- a/security/nss/cmd/signver/signver.c +++ b/security/nss/cmd/signver/signver.c @@ -204,7 +204,7 @@ int main(int argc, char **argv) /* read in the input files' contents */ rv = SECU_ReadDERFromFile(&pkcs7der, signFile, - signver.options[opt_ASCII].activated); + signver.options[opt_ASCII].activated, PR_FALSE); if (signFile != PR_STDIN) PR_Close(signFile); if (rv != SECSuccess) { diff --git a/security/nss/cmd/vfychain/vfychain.c b/security/nss/cmd/vfychain/vfychain.c index ddbf379cdb1f..4d41be8f55ab 100644 --- a/security/nss/cmd/vfychain/vfychain.c +++ b/security/nss/cmd/vfychain/vfychain.c @@ -184,7 +184,7 @@ getCert(const char *name, PRBool isAscii, const char * progName) return cert; } - rv = SECU_ReadDERFromFile(&item, fd, isAscii); + rv = SECU_ReadDERFromFile(&item, fd, isAscii, PR_FALSE); PR_Close(fd); if (rv != SECSuccess) { fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName); diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 590d1bfaeee3..5182f75552c8 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,4 +10,3 @@ */ #error "Do not include this header file." - diff --git a/security/nss/lib/freebl/win_rand.c b/security/nss/lib/freebl/win_rand.c index 0100ac446ecc..2ddac8d75287 100644 --- a/security/nss/lib/freebl/win_rand.c +++ b/security/nss/lib/freebl/win_rand.c @@ -366,40 +366,6 @@ void RNG_FileForRNG(const char *filename) } -/* - * CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later. - * Until we drop support for Windows 95, we need to emulate some - * definitions and declarations in and look up the - * functions in advapi32.dll at run time. - */ - -#ifndef WIN64 -typedef unsigned long HCRYPTPROV; -#endif - -#define CRYPT_VERIFYCONTEXT 0xF0000000 - -#define PROV_RSA_FULL 1 - -typedef BOOL -(WINAPI *CryptAcquireContextAFn)( - HCRYPTPROV *phProv, - LPCSTR pszContainer, - LPCSTR pszProvider, - DWORD dwProvType, - DWORD dwFlags); - -typedef BOOL -(WINAPI *CryptReleaseContextFn)( - HCRYPTPROV hProv, - DWORD dwFlags); - -typedef BOOL -(WINAPI *CryptGenRandomFn)( - HCRYPTPROV hProv, - DWORD dwLen, - BYTE *pbBuffer); - /* * Windows XP and Windows Server 2003 and later have RtlGenRandom, * which must be looked up by the name SystemFunction036. @@ -413,50 +379,19 @@ size_t RNG_SystemRNG(void *dest, size_t maxLen) { HMODULE hModule; RtlGenRandomFn pRtlGenRandom; - CryptAcquireContextAFn pCryptAcquireContextA; - CryptReleaseContextFn pCryptReleaseContext; - CryptGenRandomFn pCryptGenRandom; - HCRYPTPROV hCryptProv; size_t bytes = 0; usedWindowsPRNG = PR_FALSE; hModule = LoadLibrary("advapi32.dll"); if (hModule == NULL) { - return rng_systemFromNoise(dest,maxLen); + return bytes; } pRtlGenRandom = (RtlGenRandomFn) GetProcAddress(hModule, "SystemFunction036"); - if (pRtlGenRandom) { - if (pRtlGenRandom(dest, maxLen)) { - bytes = maxLen; - usedWindowsPRNG = PR_TRUE; - } else { - bytes = rng_systemFromNoise(dest,maxLen); - } - goto done; + if (pRtlGenRandom && pRtlGenRandom(dest, maxLen)) { + bytes = maxLen; + usedWindowsPRNG = PR_TRUE; } - pCryptAcquireContextA = (CryptAcquireContextAFn) - GetProcAddress(hModule, "CryptAcquireContextA"); - pCryptReleaseContext = (CryptReleaseContextFn) - GetProcAddress(hModule, "CryptReleaseContext"); - pCryptGenRandom = (CryptGenRandomFn) - GetProcAddress(hModule, "CryptGenRandom"); - if (!pCryptAcquireContextA || !pCryptReleaseContext || !pCryptGenRandom) { - bytes = rng_systemFromNoise(dest,maxLen); - goto done; - } - if (pCryptAcquireContextA(&hCryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - if (pCryptGenRandom(hCryptProv, maxLen, dest)) { - bytes = maxLen; - usedWindowsPRNG = PR_TRUE; - } - pCryptReleaseContext(hCryptProv, 0); - } - if (bytes == 0) { - bytes = rng_systemFromNoise(dest,maxLen); - } -done: FreeLibrary(hModule); return bytes; } diff --git a/security/nss/lib/libpkix/pkix/top/pkix_build.c b/security/nss/lib/libpkix/pkix/top/pkix_build.c index 71fa2e984bc5..c35163a480b2 100755 --- a/security/nss/lib/libpkix/pkix/top/pkix_build.c +++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c @@ -1021,9 +1021,11 @@ pkix_Build_ValidationCheckers( PKIX_ProcessingParams *procParams = NULL; PKIX_PL_Cert *trustedCert = NULL; PKIX_PL_PublicKey *trustedPubKey = NULL; + PKIX_PL_CertNameConstraints *trustedNC = NULL; PKIX_CertChainChecker *sigChecker = NULL; PKIX_CertChainChecker *policyChecker = NULL; PKIX_CertChainChecker *userChecker = NULL; + PKIX_CertChainChecker *nameConstraintsChecker = NULL; PKIX_CertChainChecker *checker = NULL; PKIX_CertSelector *certSelector = NULL; PKIX_List *userCheckerExtOIDs = NULL; @@ -1192,7 +1194,7 @@ pkix_Build_ValidationCheckers( } } - /* Inabling post chain building signature check on the certs. */ + /* Enabling post chain building signature check on the certs. */ PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert (anchor, &trustedCert, plContext), PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); @@ -1214,6 +1216,23 @@ pkix_Build_ValidationCheckers( plContext), PKIX_LISTAPPENDITEMFAILED); + /* Enabling post chain building name constraints check on the certs. */ + PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints + (anchor, &trustedNC, plContext), + PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED); + + PKIX_CHECK(pkix_NameConstraintsChecker_Initialize + (trustedNC, numChainCerts, &nameConstraintsChecker, + plContext), + PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (checkers, + (PKIX_PL_Object *)nameConstraintsChecker, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(state->reversedCertChain); PKIX_INCREF(reversedCertChain); state->reversedCertChain = reversedCertChain; @@ -1240,6 +1259,8 @@ cleanup: PKIX_DECREF(trustedPubKey); PKIX_DECREF(certSelector); PKIX_DECREF(sigChecker); + PKIX_DECREF(trustedNC); + PKIX_DECREF(nameConstraintsChecker); PKIX_DECREF(policyChecker); PKIX_DECREF(userChecker); PKIX_DECREF(userCheckerExtOIDs); diff --git a/security/nss/lib/pk11wrap/secmod.h b/security/nss/lib/pk11wrap/secmod.h index c83d7e39fdf4..05573349f43b 100644 --- a/security/nss/lib/pk11wrap/secmod.h +++ b/security/nss/lib/pk11wrap/secmod.h @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _SECMOD_H_ -#define _SEDMOD_H_ +#define _SECMOD_H_ #include "seccomon.h" #include "secmodt.h" #include "prinrval.h" diff --git a/security/nss/lib/ssl/config.mk b/security/nss/lib/ssl/config.mk index 1a717fa908b0..da8b9ef77164 100644 --- a/security/nss/lib/ssl/config.mk +++ b/security/nss/lib/ssl/config.mk @@ -7,10 +7,6 @@ ifdef NISCC_TEST DEFINES += -DNISCC_TEST endif -ifdef NSS_SURVIVE_DOUBLE_BYPASS_FAILURE -DEFINES += -DNSS_SURVIVE_DOUBLE_BYPASS_FAILURE -endif - ifdef NSS_NO_PKCS11_BYPASS DEFINES += -DNO_PKCS11_BYPASS else diff --git a/security/nss/lib/ssl/derive.c b/security/nss/lib/ssl/derive.c index 420e6781ef38..35cfe25122f9 100644 --- a/security/nss/lib/ssl/derive.c +++ b/security/nss/lib/ssl/derive.c @@ -81,9 +81,11 @@ ssl3_KeyAndMacDeriveBypass( unsigned int effKeySize; /* effective size of cipher keys */ unsigned int macSize; /* size of MAC secret */ unsigned int IVSize; /* size of IV */ + PRBool explicitIV = PR_FALSE; SECStatus rv = SECFailure; SECStatus status = SECSuccess; PRBool isFIPS = PR_FALSE; + PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; SECItem srcr; SECItem crsr; @@ -115,7 +117,13 @@ ssl3_KeyAndMacDeriveBypass( if (keySize == 0) { effKeySize = IVSize = 0; /* only MACing */ } - block_needed = 2 * (macSize + effKeySize + ((!isExport) * IVSize)); + if (cipher_def->type == type_block && + pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { + /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ + explicitIV = PR_TRUE; + } + block_needed = + 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize)); /* * clear out our returned keys so we can recover on failure @@ -150,8 +158,13 @@ ssl3_KeyAndMacDeriveBypass( keyblk.data = key_block; keyblk.len = block_needed; - status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, - isFIPS); + if (isTLS12) { + status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem, + "key expansion", &srcr, &keyblk, isFIPS); + } else { + status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, + isFIPS); + } if (status != SECSuccess) { goto key_and_mac_derive_fail; } @@ -239,22 +252,34 @@ ssl3_KeyAndMacDeriveBypass( i += keySize; if (IVSize > 0) { - /* - ** client_write_IV[CipherSpec.IV_size] - */ - buildSSLKey(&key_block[i], IVSize, &pwSpec->client.write_iv_item, \ - "Domestic Client Write IV"); - i += IVSize; + if (explicitIV) { + static unsigned char zero_block[32]; + PORT_Assert(IVSize <= sizeof zero_block); + buildSSLKey(&zero_block[0], IVSize, \ + &pwSpec->client.write_iv_item, \ + "Domestic Client Write IV"); + buildSSLKey(&zero_block[0], IVSize, \ + &pwSpec->server.write_iv_item, \ + "Domestic Server Write IV"); + } else { + /* + ** client_write_IV[CipherSpec.IV_size] + */ + buildSSLKey(&key_block[i], IVSize, \ + &pwSpec->client.write_iv_item, \ + "Domestic Client Write IV"); + i += IVSize; - /* - ** server_write_IV[CipherSpec.IV_size] - */ - buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item, \ - "Domestic Server Write IV"); - i += IVSize; + /* + ** server_write_IV[CipherSpec.IV_size] + */ + buildSSLKey(&key_block[i], IVSize, \ + &pwSpec->server.write_iv_item, \ + "Domestic Server Write IV"); + i += IVSize; + } } PORT_Assert(i <= block_bytes); - } else if (!isTLS) { /* ** Generate SSL3 Export write keys and IVs. @@ -417,6 +442,7 @@ ssl3_MasterKeyDeriveBypass( unsigned char * key_block = pwSpec->key_block; SECStatus rv = SECSuccess; PRBool isFIPS = PR_FALSE; + PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; SECItem crsr; @@ -452,7 +478,12 @@ ssl3_MasterKeyDeriveBypass( master.data = key_block; master.len = SSL3_MASTER_SECRET_LENGTH; - rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); + if (isTLS12) { + rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr, + &master, isFIPS); + } else { + rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); + } if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); } diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 959f65b5133b..f5087be84f3b 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -58,7 +58,6 @@ static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); static SECStatus ssl3_SendServerHello( sslSocket *ss); static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); -static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss); static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, const unsigned char *b, unsigned int l); @@ -1060,6 +1059,9 @@ ssl3_ComputeCommonKeyHash(SECOidTag hashAlg, } else if (hashAlg == SEC_OID_SHA384) { SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen); hashes->len = SHA384_LENGTH; + } else if (hashAlg == SEC_OID_SHA512) { + SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen); + hashes->len = SHA512_LENGTH; } else { PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); return SECFailure; @@ -1523,7 +1525,8 @@ ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec) } #ifndef NO_PKCS11_BYPASS -/* Initialize encryption and MAC contexts for pending spec. +/* Initialize encryption contexts for pending spec. + * MAC contexts are set up when computing the mac, not here. * Master Secret already is derived in spec->msItem * Caller holds Spec write lock. */ @@ -1539,7 +1542,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) unsigned int optArg1 = 0; unsigned int optArg2 = 0; PRBool server_encrypts = ss->sec.isServer; - CK_ULONG macLength; SSLCipherAlgorithm calg; SSLCompressionMethod compression_method; SECStatus rv; @@ -1550,11 +1552,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) pwSpec = ss->ssl3.pwSpec; cipher_def = pwSpec->cipher_def; - macLength = pwSpec->mac_size; - - /* MAC setup is done when computing the mac, not here. - * Now setup the crypto contexts. - */ calg = cipher_def->calg; compression_method = pwSpec->compression_method; @@ -3436,18 +3433,6 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) */ rv = PK11_ExtractKeyValue(pwSpec->master_secret); if (rv != SECSuccess) { -#if defined(NSS_SURVIVE_DOUBLE_BYPASS_FAILURE) - /* The double bypass failed. - * Attempt to revert to an all PKCS#11, non-bypass method. - * Do we need any unacquired locks here? - */ - ss->opt.bypassPKCS11 = 0; - rv = ssl3_NewHandshakeHashes(ss); - if (rv == SECSuccess) { - rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf, - ss->ssl3.hs.messages.len); - } -#endif return rv; } /* This returns the address of the secItem inside the key struct, @@ -3617,34 +3602,90 @@ loser: return SECFailure; } -/* ssl3_InitTLS12HandshakeHash creates a handshake hash context for TLS 1.2, - * if needed, and hashes in any buffered messages in ss->ssl3.hs.messages. */ +/* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in + * buffered messages in ss->ssl3.hs.messages. */ static SECStatus -ssl3_InitTLS12HandshakeHash(sslSocket *ss) +ssl3_InitHandshakeHashes(sslSocket *ss) { - if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2 && - ss->ssl3.hs.tls12_handshake_hash == NULL) { - /* If we ever support ciphersuites where the PRF hash isn't SHA-256 - * then this will need to be updated. */ - ss->ssl3.hs.tls12_handshake_hash = - PK11_CreateDigestContext(SEC_OID_SHA256); - if (!ss->ssl3.hs.tls12_handshake_hash || - PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash) != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); - return SECFailure; + SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); + + PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown); +#ifndef NO_PKCS11_BYPASS + if (ss->opt.bypassPKCS11) { + PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone); + if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { + /* If we ever support ciphersuites where the PRF hash isn't SHA-256 + * then this will need to be updated. */ + ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256); + if (!ss->ssl3.hs.sha_obj) { + ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); + return SECFailure; + } + ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone; + ss->ssl3.hs.hashType = handshake_hash_single; + ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx); + } else { + ss->ssl3.hs.hashType = handshake_hash_combo; + MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); + SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); + } + } else +#endif + { + PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha); + /* + * note: We should probably lookup an SSL3 slot for these + * handshake hashes in hopes that we wind up with the same slots + * that the master secret will wind up in ... + */ + if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { + /* If we ever support ciphersuites where the PRF hash isn't SHA-256 + * then this will need to be updated. */ + ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256); + if (ss->ssl3.hs.sha == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + ss->ssl3.hs.hashType = handshake_hash_single; + + if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); + return SECFailure; + } + } else { + /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or + * created successfully. */ + ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5); + if (ss->ssl3.hs.md5 == NULL) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + return SECFailure; + } + ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); + if (ss->ssl3.hs.sha == NULL) { + PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); + ss->ssl3.hs.md5 = NULL; + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } + ss->ssl3.hs.hashType = handshake_hash_combo; + + if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + return SECFailure; + } + if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return SECFailure; + } } } - if (ss->ssl3.hs.tls12_handshake_hash && ss->ssl3.hs.messages.len > 0) { - if (PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash, - ss->ssl3.hs.messages.buf, - ss->ssl3.hs.messages.len) != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); + if (ss->ssl3.hs.messages.len > 0) { + if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf, + ss->ssl3.hs.messages.len) != + SECSuccess) { return SECFailure; } - } - - if (ss->ssl3.hs.messages.buf && !ss->opt.bypassPKCS11) { PORT_Free(ss->ssl3.hs.messages.buf); ss->ssl3.hs.messages.buf = NULL; ss->ssl3.hs.messages.len = 0; @@ -3659,83 +3700,30 @@ ssl3_RestartHandshakeHashes(sslSocket *ss) { SECStatus rv = SECSuccess; + SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", + SSL_GETPID(), ss->fd )); + ss->ssl3.hs.hashType = handshake_hash_unknown; ss->ssl3.hs.messages.len = 0; #ifndef NO_PKCS11_BYPASS - if (ss->opt.bypassPKCS11) { - MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); - SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); - } else + ss->ssl3.hs.sha_obj = NULL; + ss->ssl3.hs.sha_clone = NULL; #endif - { - if (ss->ssl3.hs.tls12_handshake_hash) { - rv = PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); - return rv; - } - } - rv = PK11_DigestBegin(ss->ssl3.hs.md5); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - return rv; - } - rv = PK11_DigestBegin(ss->ssl3.hs.sha); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - return rv; - } - } - return rv; -} - -static SECStatus -ssl3_NewHandshakeHashes(sslSocket *ss) -{ - PK11Context *md5 = NULL; - PK11Context *sha = NULL; - - /* - * note: We should probably lookup an SSL3 slot for these - * handshake hashes in hopes that we wind up with the same slots - * that the master secret will wind up in ... - */ - SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); - PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); - ss->ssl3.hs.messages.buf = NULL; - ss->ssl3.hs.messages.space = 0; - - ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5); - ss->ssl3.hs.sha = sha = PK11_CreateDigestContext(SEC_OID_SHA1); - ss->ssl3.hs.tls12_handshake_hash = NULL; - if (md5 == NULL) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - goto loser; - } - if (sha == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - goto loser; - } - if (SECSuccess == ssl3_RestartHandshakeHashes(ss)) { - return SECSuccess; - } - -loser: - if (md5 != NULL) { - PK11_DestroyContext(md5, PR_TRUE); + if (ss->ssl3.hs.md5) { + PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); ss->ssl3.hs.md5 = NULL; } - if (sha != NULL) { - PK11_DestroyContext(sha, PR_TRUE); + if (ss->ssl3.hs.sha) { + PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); ss->ssl3.hs.sha = NULL; } - return SECFailure; - + return rv; } /* * Handshake messages */ -/* Called from ssl3_AppendHandshake() +/* Called from ssl3_InitHandshakeHashes() +** ssl3_AppendHandshake() ** ssl3_StartHandshakeHash() ** ssl3_HandleV2ClientHello() ** ssl3_HandleHandshakeMessage() @@ -3749,31 +3737,27 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - PRINT_BUF(90, (NULL, "MD5 & SHA handshake hash input:", b, l)); - - if ((ss->version == 0 || ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) && - !ss->opt.bypassPKCS11 && - ss->ssl3.hs.tls12_handshake_hash == NULL) { - /* For TLS 1.2 connections we need to buffer the handshake messages - * until we have established which PRF hash function to use. */ - rv = sslBuffer_Append(&ss->ssl3.hs.messages, b, l); - if (rv != SECSuccess) { - return rv; - } + /* We need to buffer the handshake messages until we have established + * which handshake hash function to use. */ + if (ss->ssl3.hs.hashType == handshake_hash_unknown) { + return sslBuffer_Append(&ss->ssl3.hs.messages, b, l); } + PRINT_BUF(90, (NULL, "handshake hash input:", b, l)); + #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11) { - MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); - SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); -#if defined(NSS_SURVIVE_DOUBLE_BYPASS_FAILURE) - rv = sslBuffer_Append(&ss->ssl3.hs.messages, b, l); -#endif + if (ss->ssl3.hs.hashType == handshake_hash_single) { + ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l); + } else { + MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); + SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); + } return rv; } #endif - if (ss->ssl3.hs.tls12_handshake_hash) { - rv = PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash, b, l); + if (ss->ssl3.hs.hashType == handshake_hash_single) { + rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); return rv; @@ -3901,10 +3885,6 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s", SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t))); - PRINT_BUF(60, (ss, "MD5 handshake hash:", - (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); - PRINT_BUF(95, (ss, "SHA handshake hash:", - (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); rv = ssl3_AppendHandshakeNumber(ss, t, 1); if (rv != SECSuccess) { @@ -4235,7 +4215,27 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, hashes->hashAlg = SEC_OID_UNKNOWN; #ifndef NO_PKCS11_BYPASS - if (ss->opt.bypassPKCS11) { + if (ss->opt.bypassPKCS11 && + ss->ssl3.hs.hashType == handshake_hash_single) { + /* compute them without PKCS11 */ + PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; + + if (!spec->msItem.data) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } + + ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx); + ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len, + sizeof(hashes->u.raw)); + + PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len)); + + /* If we ever support ciphersuites where the PRF hash isn't SHA-256 + * then this will need to be updated. */ + hashes->hashAlg = SEC_OID_SHA256; + rv = SECSuccess; + } else if (ss->opt.bypassPKCS11) { /* compute them without PKCS11 */ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; @@ -4320,7 +4320,8 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, #undef shacx } else #endif - if (ss->ssl3.hs.tls12_handshake_hash) { + if (ss->ssl3.hs.hashType == handshake_hash_single) { + /* compute hashes with PKCS11 */ PK11Context *h; unsigned int stateLen; unsigned char stackBuf[1024]; @@ -4331,7 +4332,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, return SECFailure; } - h = ss->ssl3.hs.tls12_handshake_hash; + h = ss->ssl3.hs.sha; stateBuf = PK11_SaveContextAlloc(h, stackBuf, sizeof(stackBuf), &stateLen); if (stateBuf == NULL) { @@ -4352,8 +4353,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, tls12_loser: if (stateBuf) { - if (PK11_RestoreContext(ss->ssl3.hs.tls12_handshake_hash, stateBuf, - stateLen) != SECSuccess) { + if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); rv = SECFailure; } @@ -4362,7 +4362,7 @@ tls12_loser: } } } else { - /* compute hases with PKCS11 */ + /* compute hashes with PKCS11 */ PK11Context * md5; PK11Context * sha = NULL; unsigned char *md5StateBuf = NULL; @@ -4527,6 +4527,10 @@ ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) if (rv != SECSuccess) { goto done; /* ssl3_InitState has set the error code. */ } + rv = ssl3_RestartHandshakeHashes(ss); + if (rv != SECSuccess) { + goto done; + } PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); PORT_Memcpy( @@ -4586,8 +4590,6 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) */ PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); - SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", - SSL_GETPID(), ss->fd )); rv = ssl3_RestartHandshakeHashes(ss); if (rv != SECSuccess) { return rv; @@ -5846,12 +5848,8 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SSL_GETPID(), ss->fd)); PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->ssl3.initialized ); - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ - goto alert_loser; - } if (ss->ssl3.hs.ws != wait_server_hello) { errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO; desc = unexpected_message; @@ -5904,7 +5902,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0); - rv = ssl3_InitTLS12HandshakeHash(ss); + rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { desc = internal_error; errCode = PORT_GetError(); @@ -7071,6 +7069,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->ssl3.initialized ); /* Get peer name of client */ rv = ssl_GetPeerInfo(ss); @@ -7098,11 +7097,6 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); ss->statelessResume = PR_FALSE; - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - return rv; /* ssl3_InitState has set the error code. */ - } - if ((ss->ssl3.hs.ws != wait_client_hello) && (ss->ssl3.hs.ws != idle_handshake)) { desc = unexpected_message; @@ -7141,7 +7135,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto alert_loser; } - rv = ssl3_InitTLS12HandshakeHash(ss); + rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { desc = internal_error; errCode = PORT_GetError(); @@ -7868,6 +7862,11 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) ssl_ReleaseSSL3HandshakeLock(ss); return rv; /* ssl3_InitState has set the error code. */ } + rv = ssl3_RestartHandshakeHashes(ss); + if (rv != SECSuccess) { + ssl_ReleaseSSL3HandshakeLock(ss); + return rv; + } if (ss->ssl3.hs.ws != wait_client_hello) { desc = unexpected_message; @@ -7889,7 +7888,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) goto alert_loser; } - rv = ssl3_InitTLS12HandshakeHash(ss); + rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { desc = internal_error; errCode = PORT_GetError(); @@ -8624,6 +8623,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->ssl3.prSpec == ss->ssl3.pwSpec ); enc_pms.data = b; enc_pms.len = length; @@ -9632,7 +9632,12 @@ ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label, inData.len = valLen; outData.data = out; outData.len = outLen; - rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); + if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { + rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData, + &outData, isFIPS); + } else { + rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); + } PORT_Assert(rv != SECSuccess || outData.len == outLen); #endif } @@ -10142,10 +10147,6 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type))); - PRINT_BUF(60, (ss, "MD5 handshake hash:", - (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); - PRINT_BUF(95, (ss, "SHA handshake hash:", - (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); hdr[0] = (PRUint8)ss->ssl3.hs.msg_type; hdr[1] = (PRUint8)(length >> 16); @@ -10154,8 +10155,6 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* Start new handshake hashes when we start a new handshake */ if (ss->ssl3.hs.msg_type == client_hello) { - SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", - SSL_GETPID(), ss->fd )); rv = ssl3_RestartHandshakeHashes(ss); if (rv != SECSuccess) { return rv; @@ -11094,8 +11093,6 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* Called from: ssl3_SendRecord ** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake() ** ssl3_SendClientHello() -** ssl3_HandleServerHello() -** ssl3_HandleClientHello() ** ssl3_HandleV2ClientHello() ** ssl3_HandleRecord() ** @@ -11106,7 +11103,6 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) static SECStatus ssl3_InitState(sslSocket *ss) { - SECStatus rv; PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->ssl3.initialized) @@ -11139,12 +11135,12 @@ ssl3_InitState(sslSocket *ss) dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */ } - rv = ssl3_NewHandshakeHashes(ss); - if (rv == SECSuccess) { - ss->ssl3.initialized = PR_TRUE; - } + PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); + ss->ssl3.hs.messages.buf = NULL; + ss->ssl3.hs.messages.space = 0; - return rv; + ss->ssl3.initialized = PR_TRUE; + return SECSuccess; } /* Returns a reference counted object that contains a key pair. @@ -11439,8 +11435,12 @@ ssl3_DestroySSL3Info(sslSocket *ss) /* clean up handshake */ #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11) { - SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); - MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); + if (ss->ssl3.hs.hashType == handshake_hash_combo) { + SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); + MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); + } else if (ss->ssl3.hs.hashType == handshake_hash_single) { + ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE); + } } #endif if (ss->ssl3.hs.md5) { @@ -11449,9 +11449,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) if (ss->ssl3.hs.sha) { PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); } - if (ss->ssl3.hs.tls12_handshake_hash) { - PK11_DestroyContext(ss->ssl3.hs.tls12_handshake_hash,PR_TRUE); - } if (ss->ssl3.hs.clientSigAndHash) { PORT_Free(ss->ssl3.hs.clientSigAndHash); } diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index b0abfd5972a2..90e9567c172f 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -487,7 +487,9 @@ typedef PRUint16 DTLSEpoch; typedef void (*DTLSTimerCb)(sslSocket *); -#define MAX_MAC_CONTEXT_BYTES 400 +#define MAX_MAC_CONTEXT_BYTES 400 /* 400 is large enough for MD5, SHA-1, and + * SHA-256. For SHA-384 support, increase + * it to 712. */ #define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8) #define MAX_CIPHER_CONTEXT_BYTES 2080 @@ -766,6 +768,12 @@ typedef struct DTLSQueuedMessageStr { PRUint16 len; /* The data length */ } DTLSQueuedMessage; +typedef enum { + handshake_hash_unknown = 0, + handshake_hash_combo = 1, /* The MD5/SHA-1 combination */ + handshake_hash_single = 2 /* A single hash */ +} SSL3HandshakeHashType; + /* ** This is the "hs" member of the "ssl3" struct. ** This entire struct is protected by ssl3HandshakeLock @@ -774,11 +782,31 @@ typedef struct SSL3HandshakeStateStr { SSL3Random server_random; SSL3Random client_random; SSL3WaitState ws; + + /* This group of members is used for handshake running hashes. */ + SSL3HandshakeHashType hashType; + sslBuffer messages; /* Accumulated handshake messages */ +#ifndef NO_PKCS11_BYPASS + /* Bypass mode: + * SSL 3.0 - TLS 1.1 use both |md5_cx| and |sha_cx|. |md5_cx| is used for + * MD5 and |sha_cx| for SHA-1. + * TLS 1.2 and later use only |sha_cx|, for SHA-256. NOTE: When we support + * SHA-384, increase MAX_MAC_CONTEXT_BYTES to 712. */ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; - PK11Context * md5; /* handshake running hashes */ + const SECHashObject * sha_obj; + /* The function prototype of sha_obj->clone() does not match the prototype + * of the freebl _Clone functions, so we need a dedicated function + * pointer for the _Clone function. */ + void (*sha_clone)(void *dest, void *src); +#endif + /* PKCS #11 mode: + * SSL 3.0 - TLS 1.1 use both |md5| and |sha|. |md5| is used for MD5 and + * |sha| for SHA-1. + * TLS 1.2 and later use only |sha|, for SHA-256. */ + PK11Context * md5; PK11Context * sha; - PK11Context * tls12_handshake_hash; + const ssl3KEADef * kea_def; ssl3CipherSuite cipher_suite; const ssl3CipherSuiteDef *suite_def; @@ -796,7 +824,6 @@ const ssl3CipherSuiteDef *suite_def; PRBool sendingSCSV; /* instead of empty RI */ sslBuffer msgState; /* current state for handshake messages*/ /* protected by recvBufLock */ - sslBuffer messages; /* Accumulated handshake messages */ PRUint16 finishedBytes; /* size of single finished below */ union { TLSFinished tFinished[2]; /* client, then server */ diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 2733f5e9dbf9..cd4a7a73e05c 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -782,10 +782,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) rv = SECFailure; } else { if (PR_FALSE != on) { - /* PKCS#11 bypass is not supported with TLS 1.2. */ - if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) { - ss->opt.bypassPKCS11 = PR_FALSE; - } else if (PR_SUCCESS == SSL_BypassSetup() ) { + if (PR_SUCCESS == SSL_BypassSetup() ) { #ifdef NO_PKCS11_BYPASS ss->opt.bypassPKCS11 = PR_FALSE; #else @@ -1880,10 +1877,6 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) ssl_GetSSL3HandshakeLock(ss); ss->vrange = *vrange; - /* PKCS#11 bypass is not supported with TLS 1.2. */ - if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) { - ss->opt.bypassPKCS11 = PR_FALSE; - } ssl_ReleaseSSL3HandshakeLock(ss); ssl_Release1stHandshakeLock(ss); diff --git a/security/nss/tests/chains/scenarios/nameconstraints.cfg b/security/nss/tests/chains/scenarios/nameconstraints.cfg new file mode 100644 index 000000000000..823e83d02022 --- /dev/null +++ b/security/nss/tests/chains/scenarios/nameconstraints.cfg @@ -0,0 +1,22 @@ +# 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/. + +scenario TrustAnchors + +db trustanchors + +import NameConstraints.ca:x:CT,C,C + +verify NameConstraints.server1:x + cert NameConstraints.intermediate:x + result fail + +verify NameConstraints.server2:x + cert NameConstraints.intermediate:x + result fail + +verify NameConstraints.server3:x + cert NameConstraints.intermediate:x + result pass + diff --git a/security/nss/tests/chains/scenarios/scenarios b/security/nss/tests/chains/scenarios/scenarios index 3eda34fd72c7..1aa62d4c317c 100644 --- a/security/nss/tests/chains/scenarios/scenarios +++ b/security/nss/tests/chains/scenarios/scenarios @@ -53,3 +53,4 @@ revoc.cfg ocsp.cfg crldp.cfg trustanchors.cfg +nameconstraints.cfg diff --git a/security/nss/tests/libpkix/certs/NameConstraints.ca.cert b/security/nss/tests/libpkix/certs/NameConstraints.ca.cert new file mode 100644 index 0000000000000000000000000000000000000000..9e859a0aa00112279ac86c30416915f18bccff52 GIT binary patch literal 626 zcmXqLV#+gUV!Xb9nTe5!iILHOmyJ`a&7D}zCbA-4f18*?ZNn=n&ou%WPl zAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJW05CDmD33EF6yN3oV z_yq?WiWmri#F&M-fjotf)Z!8aXGa4$ab81X0~13d0|Ns?Lz5_RUL#~Kom|m4AKCYe ztPISJy$lA8olK353{RMki$w4}^z!simwersx4BC)Kw)b1q#r`(6FX*cJ^I#e5i*$} zd3y83(`}Bo>LPn>tjc)IJJ-0RAD_RuKRU9>J^y-Hj(n1ixkl!W-8zxhi4LLtziwRo zcOm^<;_L0-o_^F$D@uFOBPJuZt=?v1cC&4+_sPh~^PF#7TE!W2ZK^sGGb01zVgmy` zU<7a`w0SVL{cvJrWMN@uVqiDm0S2k8Fbk^zGb7`F18xwHA0)-dhU_6=bTR{d!t-WY zSf(-mk&_<5nHG~$mn~`W{;`}Tp>fiB>phL9J1wLqB)5qCEqcMZg7^2=$ln*Ym6WAD zQ)s>{IxqfK@tIkzzvHg#5;^~wZK7P5S4nD)8Ph(s9-e)H*16Z}JSIsU_ej^{ZoQHG fsk&)9Ut!bH9cQmOtE{(d2*^1eXuX@Y?S>Tq-gCuX literal 0 HcmV?d00001 diff --git a/security/nss/tests/libpkix/certs/NameConstraints.intermediate.cert b/security/nss/tests/libpkix/certs/NameConstraints.intermediate.cert new file mode 100644 index 0000000000000000000000000000000000000000..6fe77d198a640ce72c1b15c1d42235fb749fdc7e GIT binary patch literal 662 zcmXqLVwz;o#Q1vwGZP~d6QhU$FB_*;n@8JsUPeY%RtAFziMiSCW{Srx2EzT5c$0AOI5Q66SRBcMlC# z@Cyz$6fqD2i7^Xv19=J|sl_D<&W;9h;=G2&2BwBa1_lO(h9*(syhg?b#&E7d4wYRY zV;}`_g)qn!o_QsyMY*XdnTaK-AlEd`M-Bx>RtDzAUIv54PNv32hH1-eI_^#Fd}N>!v-NziMtqFBG}SyYF(-P3_X1jeLvmM;l9cFW>&@yZgC(qw4z5t$)pC zT$0!lTeAI~W`k{{`^(j@;^N-z?fG`wpJQ@xiI1z-xBRcsTTa*AxZ}ZBxr@O*zc{-s zt1Z>pR_*o@twjQ7b2S&s&yu>##LURRxY)Ex3jBLoB1x7hD(3giV zrY@4riMYGbXA^JjbE{=1TU*&Dnx4Bgn~&ue_lgRKmsc4#Tzz!o*>~G>wrd@iSsYZC zuy8qla%IKsO&=LtIP0%XO43u>q{1%t$VJ#@zFxIj5`%|T?^5Plaar+kE6M^iwV6B~ htY`nQXM2>kfXqjaui;l`SVZkMRbTLBx&@=ziMiSCW{Srx2EzT5c$0AOI5Q66SRBcMlC# z@Cyz$lrfM3i7^Wc19=Lbc_pbuxv43ci6yBD&W;9h;=G2&24;pv1_lO(h9*(syhg@A z28?TvN@drG8VEyN!&8!4T%wnmR|fP|ib3Oii^c57CTBTUVGNfPdT-~nSJ(&qjOd7aOv!Sr5Y&zTK&A{_6()v%L5)w ze$`Ww^meJ_!R4!8x!)8BRuyr)tNpJ>Nb&gfFEN~*cb4+^33zDj+RFLv;=GF!R)5n{ z>RM=0V58aJ{_OB(*T)zCoZFsV-W2$giJ6gsaj~a?yMZ{+>9T?>0tS3dsLmH;<4kDt zU~K#0#K_3P!py{Wz<>v&R+y3TKMRuqg8?^)#}ATX-hu2>V1zRRy*Sy_SHd7;DpURY zy|EGps}j~d++{l>YnAvV$t|94A2!aJ|FL&Vu*#>6%bqV>`H1Pi0l#6~YnQN@M)wZ1 z#IWmMd~bNzVvR=pg-gqYSDs7WRKT^7ue)Erzpl|E#=9loU7tsaQOY{L{2%+Ffa^b6 ZuY`0bT@(}fTXNR$+2vl*w;vWg0svK?*Cqe} literal 0 HcmV?d00001 diff --git a/security/nss/tests/libpkix/certs/NameConstraints.server2.cert b/security/nss/tests/libpkix/certs/NameConstraints.server2.cert new file mode 100644 index 0000000000000000000000000000000000000000..feac1139294801703731fb01204b5de0165fae2d GIT binary patch literal 643 zcmXqLVyZW2VtlcHnTe5!iBZ#lmyJ`a&7D}zCfA-4f18*?ZNn=n&ou%WPl zAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJW05CDmD33EF6yN3oV z_yq?W${0w2#F&MJfjkAzypq(S+|-oJ#FA76XGa4$ab81X12aP-0|Ns?Lz5_RUL#{5 z1I9JTrLt>e4Wz-Y;Sov9%P+}DEs8HmEiTc^%qs)>F2$g6K5}p{vNA9?_A(eWb}}_K zGHjZk;&iZY#zN*77b*{O#1)5}zT@^#?bnSp5~|7#(<=VCh$HN}_wJY(~IZCsV5ziMiSCW{Srx2EzT5c$0AOI5Q66SRBcMlC# z@Cyz$lrfM3i7^Wc19=Lbc_pbuxv43ci6yBD&W;9h;=G2&24;pv1_lO(h9*(syhg@A z28?TvN@drG8VEyN!&8!4T%wm+k(gVMlWNd7A2}EpSs9ocdl?KGJDD0A8J=m`=w-Bf ziqDREYj?Haug7i{o6=3&cQ|D4I3*e35j4wTuK%g+x1E@3og6+yDj05l$EJJK%3)WH zdeNgLx0c>jK6d`e68no+C4-x%aWrW?^kMNXF7;W^rKFrT*VMw`fNN-ge2&eoyvQ@L zf7_jGpC>Qwh(Bf1f5B_lg8NDLP6V%KVrFDuT pwfile + +certutil -d . -N -f pwfile + +certutil -S -z noise -g 1024 -d . -n ca -s "CN=NSS Test CA,O=BOGUS NSS,L=Mountain View,ST=California,C=US" -t C,C,C -x -m 1 -w -2 -v 120 -1 -2 -5 < NameConstraints.ca.cert +certutil -d . -L -n ica -r > NameConstraints.intermediate.cert +certutil -d . -L -n server1 -r > NameConstraints.server1.cert +certutil -d . -L -n server2 -r > NameConstraints.server2.cert +certutil -d . -L -n server3 -r > NameConstraints.server3.cert + +echo "Created multiple files in subdirectory tmp: NameConstraints.ca.cert NameConstraints.intermediate.cert NameConstraints.server1.cert NameConstraints.server2.cert NameConstraints.server3.cert" From 44d26ad07a8d0564f9f7e48fa54d4d0a3630f091 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Wed, 12 Jun 2013 23:57:51 -0400 Subject: [PATCH 406/615] Bug 880836. Add MaskSurface() to Azure. r=bas This gives a substantial performance improvement over the more general Mask(): Test (MaskSurface10x10): 1.93042ms +/- 0.305028 Test (MaskSurface100x100): 2.33435ms +/- 1.00807 Test (MaskSurface500x500): 28.0472ms +/- 0.820744 Test (MaskSurface1000x1000): 107.656ms +/- 6.44615 Test (Mask10x10): 13.5237ms +/- 0.0932034 Test (Mask100x100): 14.0742ms +/- 1.21005 Test (Mask500x500): 96.5596ms +/- 1.81415 Test (Mask1000x1000): 356.891ms +/- 9.30592 --HG-- extra : rebase_source : a3031305302fb4abe93aa480df35ed0936d68cd8 --- gfx/2d/2D.h | 15 ++++ gfx/2d/DrawTargetCG.cpp | 32 +++++++ gfx/2d/DrawTargetCG.h | 4 + gfx/2d/DrawTargetCairo.cpp | 49 +++++++++++ gfx/2d/DrawTargetD2D.cpp | 140 +++++++++++++++++++----------- gfx/2d/DrawTargetD2D.h | 8 ++ gfx/2d/DrawTargetDual.cpp | 12 +++ gfx/2d/DrawTargetDual.h | 7 +- gfx/thebes/gfxContext.cpp | 9 +- layout/reftests/bugs/reftest.list | 2 +- 10 files changed, 220 insertions(+), 58 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 423820279205..f0ccef614ae9 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -706,6 +706,21 @@ public: const Pattern &aMask, const DrawOptions &aOptions = DrawOptions()) = 0; + /* + * This takes a source pattern and a mask, and composites the source pattern + * onto the destination surface using the alpha channel of the mask source. + * The operation is bound by the extents of the mask. + * + * aSource Source pattern + * aMask Mask surface + * aOffset a transformed offset that the surface is masked at + * aOptions Drawing options + */ + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); }; + /* * Push a clip to the DrawTarget. * diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index f0785504728d..2777f250ced5 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -300,6 +300,38 @@ DrawTargetCG::DrawSurface(SourceSurface *aSurface, CGImageRelease(subimage); } +void +DrawTargetCG::MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aDrawOptions) +{ + MarkChanged(); + + CGImageRef image; + CGContextSaveGState(mCg); + + CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp)); + UnboundnessFixer fixer; + CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp); + CGContextSetAlpha(cg, aDrawOptions.mAlpha); + + CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform)); + image = GetImageFromSourceSurface(aMask); + + CGContextScaleCTM(cg, 1, -1); + + IntSize size = aMask->GetSize(); + CGContextClipToMask(cg, CGRectMake(aOffset.x, aOffset.y, size.width, size.height), image); + + FillRect(Rect(0, 0, size.width, size.height), aSource, aDrawOptions); + + fixer.Fix(mCg); + + CGContextRestoreGState(mCg); + +} + static CGColorRef ColorToCGColor(CGColorSpaceRef aColorSpace, const Color& aColor) { CGFloat components[4] = {aColor.r, aColor.g, aColor.b, aColor.a}; diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index e952a6ed6da8..9ddf29bbdcb9 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -96,6 +96,10 @@ public: const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), const DrawOptions &aOptions = DrawOptions()); + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()); virtual void FillRect(const Rect &aRect, const Pattern &aPattern, diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 2918ce6d6ed7..6e7f6efe0ad3 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -676,6 +676,55 @@ DrawTargetCairo::Mask(const Pattern &aSource, cairo_pattern_destroy(mask); cairo_pattern_destroy(source); } +#if 0 +DrawTargetCairo::MaskSurface(SourceSurface *aSurface, + const Rect &aDest, + const Rect &aSource, + const DrawSurfaceOptions &aSurfOptions, + const DrawOptions &aOptions) +{ + AutoPrepareForDrawing prep(this, mContext); + + float sx = aSource.Width() / aDest.Width(); + float sy = aSource.Height() / aDest.Height(); + + cairo_matrix_t src_mat; + cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y()); + cairo_matrix_scale(&src_mat, sx, sy); + + cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface); + cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf); + cairo_surface_destroy(surf); + + cairo_pattern_set_matrix(pat, &src_mat); + cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter)); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); + + cairo_translate(mContext, aDest.X(), aDest.Y()); + + if (IsOperatorBoundByMask(aOptions.mCompositionOp)) { + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height()); + cairo_clip(mContext); + cairo_set_source(mContext, pat); + } else { + cairo_push_group(mContext); + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height()); + cairo_set_source(mContext, pat); + cairo_fill(mContext); + cairo_pop_group_to_source(mContext); + } + + cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp)); + DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL); + + cairo_paint_with_alpha(mContext, aOptions.mAlpha); + + cairo_pattern_destroy(pat); +} + +#endif void DrawTargetCairo::PushClip(const Path *aPath) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index a38e1a41cf02..d41883fa5d8a 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -257,6 +257,63 @@ DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource) } } +TemporaryRef +DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, + Rect &aSource) +{ + RefPtr bitmap; + + switch (aSurface->GetType()) { + + case SURFACE_D2D1_BITMAP: + { + SourceSurfaceD2D *srcSurf = static_cast(aSurface); + bitmap = srcSurf->GetBitmap(); + } + break; + case SURFACE_D2D1_DRAWTARGET: + { + SourceSurfaceD2DTarget *srcSurf = static_cast(aSurface); + bitmap = srcSurf->GetBitmap(mRT); + AddDependencyOnSource(srcSurf); + } + break; + default: + { + RefPtr srcSurf = aSurface->GetDataSurface(); + + if (!srcSurf) { + gfxDebug() << "Not able to deal with non-data source surface."; + return nullptr; + } + + if (aSource.width > mRT->GetMaximumBitmapSize() || + aSource.height > mRT->GetMaximumBitmapSize()) { + gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail."; + // Don't know how to deal with this yet. + return nullptr; + } + + int stride = srcSurf->Stride(); + + unsigned char *data = srcSurf->GetData() + + (uint32_t)aSource.y * stride + + (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat()); + + D2D1_BITMAP_PROPERTIES props = + D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat()))); + mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap)); + + // subtract the integer part leaving the fractional part + aSource.x -= (uint32_t)aSource.x; + aSource.y -= (uint32_t)aSource.y; + } + break; + } + + return bitmap; +} + void DrawTargetD2D::DrawSurface(SourceSurface *aSurface, const Rect &aDest, @@ -274,62 +331,45 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface, Rect srcRect = aSource; - switch (aSurface->GetType()) { - - case SURFACE_D2D1_BITMAP: - { - SourceSurfaceD2D *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(); - - if (!bitmap) { - return; - } - } - break; - case SURFACE_D2D1_DRAWTARGET: - { - SourceSurfaceD2DTarget *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(mRT); - AddDependencyOnSource(srcSurf); - } - break; - default: - { - RefPtr srcSurf = aSurface->GetDataSurface(); - - if (!srcSurf) { - gfxDebug() << "Not able to deal with non-data source surface."; - return; - } - - if (aSource.width > rt->GetMaximumBitmapSize() || - aSource.height > rt->GetMaximumBitmapSize()) { - gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail."; - // Don't know how to deal with this yet. - return; - } - - int stride = srcSurf->Stride(); - - unsigned char *data = srcSurf->GetData() + - (uint32_t)aSource.y * stride + - (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat()); - - D2D1_BITMAP_PROPERTIES props = - D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat()))); - mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap)); - - srcRect.x -= (uint32_t)aSource.x; - srcRect.y -= (uint32_t)aSource.y; - } - break; + bitmap = GetBitmapForSurface(aSurface, srcRect); + if (!bitmap) { + return; } - + rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect)); FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest); } +void +DrawTargetD2D::MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions) +{ + RefPtr bitmap; + + ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color())); + + PrepareForDrawing(rt); + + // FillOpacityMask only works if the antialias mode is MODE_ALIASED + rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); + + IntSize size = aMask->GetSize(); + Rect maskRect = Rect(0.f, 0.f, size.width, size.height); + bitmap = GetBitmapForSurface(aMask, maskRect); + if (!bitmap) { + return; + } + + Rect dest = Rect(aOffset.x, aOffset.y, size.width, size.height); + RefPtr brush = CreateBrushForPattern(aSource, aOptions.mAlpha); + rt->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect)); + + FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), dest); +} + void DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index 1e8ed6350d7c..83048a418df5 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -63,6 +63,11 @@ public: Float aSigma, CompositionOp aOperator); virtual void ClearRect(const Rect &aRect); + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()); + virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, @@ -142,6 +147,9 @@ public: static uint64_t mVRAMUsageSS; private: + TemporaryRef + DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, + Rect &aSource); friend class AutoSaveRestoreClippedOut; friend class SourceSurfaceD2DTarget; diff --git a/gfx/2d/DrawTargetDual.cpp b/gfx/2d/DrawTargetDual.cpp index 1235a85fd102..1ee556cd4db6 100644 --- a/gfx/2d/DrawTargetDual.cpp +++ b/gfx/2d/DrawTargetDual.cpp @@ -97,6 +97,18 @@ DrawTargetDual::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDes mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp); } +void +DrawTargetDual::MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions) +{ + DualPattern source(aSource); + DualSurface mask(aMask); + mA->MaskSurface(*source.mA, mask.mA, aOffset, aOptions); + mB->MaskSurface(*source.mB, mask.mA, aOffset, aOptions); +} + void DrawTargetDual::CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, const IntPoint &aDestination) diff --git a/gfx/2d/DrawTargetDual.h b/gfx/2d/DrawTargetDual.h index b2fb0b3a5153..8f519603a199 100644 --- a/gfx/2d/DrawTargetDual.h +++ b/gfx/2d/DrawTargetDual.h @@ -59,7 +59,12 @@ public: virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect & aSource, const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions); - + + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()); + virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, Float aSigma, CompositionOp aOp); diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 70683a33ba30..3913637dd934 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -1397,7 +1397,6 @@ gfxContext::GetPattern() // masking - void gfxContext::Mask(gfxPattern *pattern) { @@ -1463,12 +1462,10 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset) gfxPoint pt = surface->GetDeviceOffset(); // We clip here to bind to the mask surface bounds, see above. - mDT->PushClipRect(Rect(offset.x - pt.x, offset.y - pt.y, sourceSurf->GetSize().width, sourceSurf->GetSize().height)); - mDT->Mask(GeneralPattern(this), - SurfacePattern(sourceSurf, EXTEND_CLAMP, - Matrix(1.0f, 0, 0, 1.0f, Float(offset.x - pt.x), Float(offset.y - pt.y))), + mDT->MaskSurface(GeneralPattern(this), + sourceSurf, + Point(offset.x - pt.x, offset.y - pt.y), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode)); - mDT->PopClip(); } } diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index d3d7c09d45e3..adda9f35751a 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1716,7 +1716,7 @@ skip-if(B2G) == 751012-1b.html 751012-1-ref.html random-if(Android) == 753329-1.html about:blank == 758561-1.html 758561-1-ref.html fuzzy-if(true,1,19) fails-if(d2d) == 759036-1.html 759036-1-ref.html -fuzzy-if(true,17,5859) == 759036-2.html 759036-2-ref.html +fuzzy-if(true,17,5860) == 759036-2.html 759036-2-ref.html == 776265-1a.html 776265-1-ref.html == 776265-1b.html 776265-1-ref.html == 776265-1c.html 776265-1-ref.html From 2bb34972bfc07375350f538baee5a1e768e15a01 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 18 Jun 2013 09:27:45 -0400 Subject: [PATCH 407/615] Bug 882120 - Apply rounding to the layer-pixel rect in Java to fix robopan regression. r=kentuckyfriedtakahe --- mobile/android/base/gfx/GeckoLayerClient.java | 9 ++++++--- mobile/android/base/gfx/RectUtils.java | 9 +++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/mobile/android/base/gfx/GeckoLayerClient.java b/mobile/android/base/gfx/GeckoLayerClient.java index b62013ddbf92..e4a33ae817d5 100644 --- a/mobile/android/base/gfx/GeckoLayerClient.java +++ b/mobile/android/base/gfx/GeckoLayerClient.java @@ -560,10 +560,12 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget Tab tab = Tabs.getInstance().getSelectedTab(); RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom); + RectF pageRect = RectUtils.scaleAndRound(cssPageRect, zoom); + final ImmutableViewportMetrics newMetrics = currentMetrics .setViewportOrigin(offsetX, offsetY) .setZoomFactor(zoom) - .setPageRect(RectUtils.scale(cssPageRect, zoom), cssPageRect) + .setPageRect(pageRect, cssPageRect) .setIsRTL(tab.getIsRTL()); // Since we have switched to displaying a different document, we need to update any // viewport-related state we have lying around. This includes mGeckoViewport and @@ -610,9 +612,10 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget */ public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) { synchronized (getLock()) { - RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom); float ourZoom = getViewportMetrics().zoomFactor; - setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect); + RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom); + RectF pageRect = RectUtils.scaleAndRound(cssPageRect, ourZoom); + setPageRect(pageRect, cssPageRect); // Here the page size of the document has changed, but the document being displayed // is still the same. Therefore, we don't need to send anything to browser.js; any // changes we need to make to the display port will get sent the next time we call diff --git a/mobile/android/base/gfx/RectUtils.java b/mobile/android/base/gfx/RectUtils.java index 81657f003f04..b68288256851 100644 --- a/mobile/android/base/gfx/RectUtils.java +++ b/mobile/android/base/gfx/RectUtils.java @@ -74,6 +74,15 @@ public final class RectUtils { y + (rect.height() * scale)); } + public static RectF scaleAndRound(RectF rect, float scale) { + float left = rect.left * scale; + float top = rect.top * scale; + return new RectF(Math.round(left), + Math.round(top), + Math.round(left + (rect.width() * scale)), + Math.round(top + (rect.height() * scale))); + } + /** Returns the nearest integer rect of the given rect. */ public static Rect round(RectF rect) { Rect r = new Rect(); From f70912e0ecd887443a12d90ee45bdc91674d492e Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Tue, 18 Jun 2013 09:59:20 -0400 Subject: [PATCH 408/615] Bug 883894 - upload a new talos.zip to capture tscroll and tsvg fixes. r=kmoir --- testing/talos/talos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 8cf64949a31e..4dbb4ba3bc5d 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -1,6 +1,6 @@ { "talos.zip": { - "url": "http://build.mozilla.org/talos/zips/talos.dfe08f329e2c.zip", + "url": "http://build.mozilla.org/talos/zips/talos.8cf5b862d113.zip", "path": "" } } From f810a607cb77ec0e97ecbe9fe8030a2588507146 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Tue, 18 Jun 2013 23:02:53 +0900 Subject: [PATCH 409/615] Bug 883855 - Add "delete" value support to AddHandlerValues and AddDDEHandlerValues. r=bbondy --- toolkit/mozapps/installer/windows/nsis/common.nsh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh index 2dad82d7f57a..6e2b66eff487 100755 --- a/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -1153,6 +1153,8 @@ * The display name for the handler. If emtpy no value will be set. * @param _ISPROTOCOL * Sets protocol handler specific registry values when "true". + * Deletes protocol handler specific registry values when "delete". + * Otherwise doesn't touch handler specific registry values. * @param _ISDDE * Sets DDE specific registry values when "true". * @@ -1194,6 +1196,8 @@ StrCmp "$R8" "true" +1 +2 WriteRegStr SHCTX "$R4" "URL Protocol" "" + StrCmp "$R8" "delete" +1 +2 + DeleteRegValue SHCTX "$R4" "URL Protocol" StrCpy $R3 "" ReadRegDWord $R3 SHCTX "$R4" "EditFlags" StrCmp $R3 "" +1 +3 ; Only add EditFlags if a value doesn't exist @@ -1297,6 +1301,8 @@ * The display name for the handler. If emtpy no value will be set. * @param _ISPROTOCOL * Sets protocol handler specific registry values when "true". + * Deletes protocol handler specific registry values when "delete". + * Otherwise doesn't touch handler specific registry values. * @param _DDE_APPNAME * Sets DDE specific registry values when not an empty string. * @@ -1347,6 +1353,8 @@ StrCmp "$R6" "true" +1 +2 WriteRegStr SHCTX "$R0\$R2" "URL Protocol" "" + StrCmp "$R6" "delete" +1 +2 + DeleteRegValue SHCTX "$R0\$R2" "URL Protocol" StrCpy $R1 "" ReadRegDWord $R1 SHCTX "$R0\$R2" "EditFlags" StrCmp $R1 "" +1 +3 ; Only add EditFlags if a value doesn't exist From 32dbe991d685a905bbcc4b78fb7fa8fb1aa0ba8f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Wed, 12 Jun 2013 23:57:51 -0400 Subject: [PATCH 410/615] Bug 880836. Add MaskSurface() to Azure. r=bas This gives a substantial performance improvement over the more general Mask(): Test (MaskSurface10x10): 1.93042ms +/- 0.305028 Test (MaskSurface100x100): 2.33435ms +/- 1.00807 Test (MaskSurface500x500): 28.0472ms +/- 0.820744 Test (MaskSurface1000x1000): 107.656ms +/- 6.44615 Test (Mask10x10): 13.5237ms +/- 0.0932034 Test (Mask100x100): 14.0742ms +/- 1.21005 Test (Mask500x500): 96.5596ms +/- 1.81415 Test (Mask1000x1000): 356.891ms +/- 9.30592 --HG-- rename : layout/reftests/svg/text/dynamic-non-scaling-stroke-ref.svg => layout/reftests/svg/non-scaling-stroke-03-ref.svg rename : layout/reftests/svg/text/dynamic-non-scaling-stroke.svg => layout/reftests/svg/non-scaling-stroke-03.svg extra : rebase_source : a1218b8bc5cdcec7d4dd94561d841fb6e2a8ce5d --- gfx/2d/2D.h | 15 ++++ gfx/2d/DrawTargetCG.cpp | 32 +++++++ gfx/2d/DrawTargetCG.h | 4 + gfx/2d/DrawTargetCairo.cpp | 49 +++++++++++ gfx/2d/DrawTargetD2D.cpp | 140 +++++++++++++++++++----------- gfx/2d/DrawTargetD2D.h | 8 ++ gfx/thebes/gfxContext.cpp | 9 +- layout/reftests/bugs/reftest.list | 2 +- 8 files changed, 202 insertions(+), 57 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 423820279205..f0ccef614ae9 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -706,6 +706,21 @@ public: const Pattern &aMask, const DrawOptions &aOptions = DrawOptions()) = 0; + /* + * This takes a source pattern and a mask, and composites the source pattern + * onto the destination surface using the alpha channel of the mask source. + * The operation is bound by the extents of the mask. + * + * aSource Source pattern + * aMask Mask surface + * aOffset a transformed offset that the surface is masked at + * aOptions Drawing options + */ + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()) { MOZ_ASSERT(0); }; + /* * Push a clip to the DrawTarget. * diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index f0785504728d..2777f250ced5 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -300,6 +300,38 @@ DrawTargetCG::DrawSurface(SourceSurface *aSurface, CGImageRelease(subimage); } +void +DrawTargetCG::MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aDrawOptions) +{ + MarkChanged(); + + CGImageRef image; + CGContextSaveGState(mCg); + + CGContextSetBlendMode(mCg, ToBlendMode(aDrawOptions.mCompositionOp)); + UnboundnessFixer fixer; + CGContextRef cg = fixer.Check(mCg, aDrawOptions.mCompositionOp); + CGContextSetAlpha(cg, aDrawOptions.mAlpha); + + CGContextConcatCTM(cg, GfxMatrixToCGAffineTransform(mTransform)); + image = GetImageFromSourceSurface(aMask); + + CGContextScaleCTM(cg, 1, -1); + + IntSize size = aMask->GetSize(); + CGContextClipToMask(cg, CGRectMake(aOffset.x, aOffset.y, size.width, size.height), image); + + FillRect(Rect(0, 0, size.width, size.height), aSource, aDrawOptions); + + fixer.Fix(mCg); + + CGContextRestoreGState(mCg); + +} + static CGColorRef ColorToCGColor(CGColorSpaceRef aColorSpace, const Color& aColor) { CGFloat components[4] = {aColor.r, aColor.g, aColor.b, aColor.a}; diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index e952a6ed6da8..9ddf29bbdcb9 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -96,6 +96,10 @@ public: const Rect &aSource, const DrawSurfaceOptions &aSurfOptions = DrawSurfaceOptions(), const DrawOptions &aOptions = DrawOptions()); + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()); virtual void FillRect(const Rect &aRect, const Pattern &aPattern, diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 2918ce6d6ed7..6e7f6efe0ad3 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -676,6 +676,55 @@ DrawTargetCairo::Mask(const Pattern &aSource, cairo_pattern_destroy(mask); cairo_pattern_destroy(source); } +#if 0 +DrawTargetCairo::MaskSurface(SourceSurface *aSurface, + const Rect &aDest, + const Rect &aSource, + const DrawSurfaceOptions &aSurfOptions, + const DrawOptions &aOptions) +{ + AutoPrepareForDrawing prep(this, mContext); + + float sx = aSource.Width() / aDest.Width(); + float sy = aSource.Height() / aDest.Height(); + + cairo_matrix_t src_mat; + cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y()); + cairo_matrix_scale(&src_mat, sx, sy); + + cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface); + cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf); + cairo_surface_destroy(surf); + + cairo_pattern_set_matrix(pat, &src_mat); + cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter)); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); + + cairo_translate(mContext, aDest.X(), aDest.Y()); + + if (IsOperatorBoundByMask(aOptions.mCompositionOp)) { + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height()); + cairo_clip(mContext); + cairo_set_source(mContext, pat); + } else { + cairo_push_group(mContext); + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height()); + cairo_set_source(mContext, pat); + cairo_fill(mContext); + cairo_pop_group_to_source(mContext); + } + + cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp)); + DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL); + + cairo_paint_with_alpha(mContext, aOptions.mAlpha); + + cairo_pattern_destroy(pat); +} + +#endif void DrawTargetCairo::PushClip(const Path *aPath) diff --git a/gfx/2d/DrawTargetD2D.cpp b/gfx/2d/DrawTargetD2D.cpp index a38e1a41cf02..d41883fa5d8a 100644 --- a/gfx/2d/DrawTargetD2D.cpp +++ b/gfx/2d/DrawTargetD2D.cpp @@ -257,6 +257,63 @@ DrawTargetD2D::AddDependencyOnSource(SourceSurfaceD2DTarget* aSource) } } +TemporaryRef +DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, + Rect &aSource) +{ + RefPtr bitmap; + + switch (aSurface->GetType()) { + + case SURFACE_D2D1_BITMAP: + { + SourceSurfaceD2D *srcSurf = static_cast(aSurface); + bitmap = srcSurf->GetBitmap(); + } + break; + case SURFACE_D2D1_DRAWTARGET: + { + SourceSurfaceD2DTarget *srcSurf = static_cast(aSurface); + bitmap = srcSurf->GetBitmap(mRT); + AddDependencyOnSource(srcSurf); + } + break; + default: + { + RefPtr srcSurf = aSurface->GetDataSurface(); + + if (!srcSurf) { + gfxDebug() << "Not able to deal with non-data source surface."; + return nullptr; + } + + if (aSource.width > mRT->GetMaximumBitmapSize() || + aSource.height > mRT->GetMaximumBitmapSize()) { + gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail."; + // Don't know how to deal with this yet. + return nullptr; + } + + int stride = srcSurf->Stride(); + + unsigned char *data = srcSurf->GetData() + + (uint32_t)aSource.y * stride + + (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat()); + + D2D1_BITMAP_PROPERTIES props = + D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat()))); + mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap)); + + // subtract the integer part leaving the fractional part + aSource.x -= (uint32_t)aSource.x; + aSource.y -= (uint32_t)aSource.y; + } + break; + } + + return bitmap; +} + void DrawTargetD2D::DrawSurface(SourceSurface *aSurface, const Rect &aDest, @@ -274,62 +331,45 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface, Rect srcRect = aSource; - switch (aSurface->GetType()) { - - case SURFACE_D2D1_BITMAP: - { - SourceSurfaceD2D *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(); - - if (!bitmap) { - return; - } - } - break; - case SURFACE_D2D1_DRAWTARGET: - { - SourceSurfaceD2DTarget *srcSurf = static_cast(aSurface); - bitmap = srcSurf->GetBitmap(mRT); - AddDependencyOnSource(srcSurf); - } - break; - default: - { - RefPtr srcSurf = aSurface->GetDataSurface(); - - if (!srcSurf) { - gfxDebug() << "Not able to deal with non-data source surface."; - return; - } - - if (aSource.width > rt->GetMaximumBitmapSize() || - aSource.height > rt->GetMaximumBitmapSize()) { - gfxDebug() << "Bitmap source larger than texture size specified. DrawBitmap will silently fail."; - // Don't know how to deal with this yet. - return; - } - - int stride = srcSurf->Stride(); - - unsigned char *data = srcSurf->GetData() + - (uint32_t)aSource.y * stride + - (uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat()); - - D2D1_BITMAP_PROPERTIES props = - D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(srcSurf->GetFormat()), AlphaMode(srcSurf->GetFormat()))); - mRT->CreateBitmap(D2D1::SizeU(UINT32(aSource.width), UINT32(aSource.height)), data, stride, props, byRef(bitmap)); - - srcRect.x -= (uint32_t)aSource.x; - srcRect.y -= (uint32_t)aSource.y; - } - break; + bitmap = GetBitmapForSurface(aSurface, srcRect); + if (!bitmap) { + return; } - + rt->DrawBitmap(bitmap, D2DRect(aDest), aOptions.mAlpha, D2DFilter(aSurfOptions.mFilter), D2DRect(srcRect)); FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), aDest); } +void +DrawTargetD2D::MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions) +{ + RefPtr bitmap; + + ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, ColorPattern(Color())); + + PrepareForDrawing(rt); + + // FillOpacityMask only works if the antialias mode is MODE_ALIASED + rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); + + IntSize size = aMask->GetSize(); + Rect maskRect = Rect(0.f, 0.f, size.width, size.height); + bitmap = GetBitmapForSurface(aMask, maskRect); + if (!bitmap) { + return; + } + + Rect dest = Rect(aOffset.x, aOffset.y, size.width, size.height); + RefPtr brush = CreateBrushForPattern(aSource, aOptions.mAlpha); + rt->FillOpacityMask(bitmap, brush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS, D2DRect(dest), D2DRect(maskRect)); + + FinalizeRTForOperation(aOptions.mCompositionOp, ColorPattern(Color()), dest); +} + void DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index 1e8ed6350d7c..83048a418df5 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -63,6 +63,11 @@ public: Float aSigma, CompositionOp aOperator); virtual void ClearRect(const Rect &aRect); + virtual void MaskSurface(const Pattern &aSource, + SourceSurface *aMask, + Point aOffset, + const DrawOptions &aOptions = DrawOptions()); + virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect, @@ -142,6 +147,9 @@ public: static uint64_t mVRAMUsageSS; private: + TemporaryRef + DrawTargetD2D::GetBitmapForSurface(SourceSurface *aSurface, + Rect &aSource); friend class AutoSaveRestoreClippedOut; friend class SourceSurfaceD2DTarget; diff --git a/gfx/thebes/gfxContext.cpp b/gfx/thebes/gfxContext.cpp index 70683a33ba30..3913637dd934 100644 --- a/gfx/thebes/gfxContext.cpp +++ b/gfx/thebes/gfxContext.cpp @@ -1397,7 +1397,6 @@ gfxContext::GetPattern() // masking - void gfxContext::Mask(gfxPattern *pattern) { @@ -1463,12 +1462,10 @@ gfxContext::Mask(gfxASurface *surface, const gfxPoint& offset) gfxPoint pt = surface->GetDeviceOffset(); // We clip here to bind to the mask surface bounds, see above. - mDT->PushClipRect(Rect(offset.x - pt.x, offset.y - pt.y, sourceSurf->GetSize().width, sourceSurf->GetSize().height)); - mDT->Mask(GeneralPattern(this), - SurfacePattern(sourceSurf, EXTEND_CLAMP, - Matrix(1.0f, 0, 0, 1.0f, Float(offset.x - pt.x), Float(offset.y - pt.y))), + mDT->MaskSurface(GeneralPattern(this), + sourceSurf, + Point(offset.x - pt.x, offset.y - pt.y), DrawOptions(1.0f, CurrentState().op, CurrentState().aaMode)); - mDT->PopClip(); } } diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index d3d7c09d45e3..adda9f35751a 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1716,7 +1716,7 @@ skip-if(B2G) == 751012-1b.html 751012-1-ref.html random-if(Android) == 753329-1.html about:blank == 758561-1.html 758561-1-ref.html fuzzy-if(true,1,19) fails-if(d2d) == 759036-1.html 759036-1-ref.html -fuzzy-if(true,17,5859) == 759036-2.html 759036-2-ref.html +fuzzy-if(true,17,5860) == 759036-2.html 759036-2-ref.html == 776265-1a.html 776265-1-ref.html == 776265-1b.html 776265-1-ref.html == 776265-1c.html 776265-1-ref.html From 39f3f03008b702ecdb4b68a19c3deda15523f310 Mon Sep 17 00:00:00 2001 From: Albert Crespell Date: Thu, 13 Jun 2013 16:37:36 +0200 Subject: [PATCH 411/615] Bug 879790 - Fix data usage lost during the very first start-up of Gecko. r=gene.lian --- dom/network/src/NetworkStatsDB.jsm | 26 +++++++++++++++++++++++-- dom/network/src/NetworkStatsService.jsm | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/dom/network/src/NetworkStatsDB.jsm b/dom/network/src/NetworkStatsDB.jsm index 2ef3bd758aec..c7dd3e475c0e 100644 --- a/dom/network/src/NetworkStatsDB.jsm +++ b/dom/network/src/NetworkStatsDB.jsm @@ -25,10 +25,11 @@ const VALUES_MAX_LENGTH = 6 * 30; // Constant defining the rate of the samples. Daily. const SAMPLE_RATE = 1000 * 60 * 60 * 24; -this.NetworkStatsDB = function NetworkStatsDB(aGlobal) { +this.NetworkStatsDB = function NetworkStatsDB(aGlobal, aConnectionTypes) { if (DEBUG) { debug("Constructor"); } + this._connectionTypes = aConnectionTypes; this.initDBHelper(DB_NAME, DB_VERSION, [STORE_NAME], aGlobal); } @@ -67,11 +68,32 @@ NetworkStatsDB.prototype = { if (DEBUG) { debug("Created object stores and indexes"); } + + // There could be a time delay between the point when the network + // interface comes up and the point when the database is initialized. + // In this short interval some traffic data are generated but are not + // registered by the first sample. The initialization of the database + // should make up the missing sample. + let stats = []; + for (let connection in this._connectionTypes) { + let connectionType = this._connectionTypes[connection].name; + let timestamp = this.normalizeDate(new Date()); + stats.push({ connectionType: connectionType, + timestamp: timestamp, + rxBytes: 0, + txBytes: 0, + rxTotalBytes: 0, + txTotalBytes: 0 }); + } + this._saveStats(aTransaction, objectStore, stats); + if (DEBUG) { + debug("Database initialized"); + } } } }, - normalizeDate: function normalizeDate(aDate) { + normalizeDate: function normalizeDate(aDate) { // Convert to UTC according to timezone and // filter timestamp to get SAMPLE_RATE precission let timestamp = aDate.getTime() - (new Date()).getTimezoneOffset() * 60 * 1000; diff --git a/dom/network/src/NetworkStatsService.jsm b/dom/network/src/NetworkStatsService.jsm index 03efc46c7b00..790d9831a3e4 100644 --- a/dom/network/src/NetworkStatsService.jsm +++ b/dom/network/src/NetworkStatsService.jsm @@ -68,7 +68,7 @@ this.NetworkStatsService = { }, this); gIDBManager.initWindowless(myGlobal); - this._db = new NetworkStatsDB(myGlobal); + this._db = new NetworkStatsDB(myGlobal, this._connectionTypes); // Stats for all interfaces are updated periodically this.timer.initWithCallback(this, this._db.sampleRate, From fd534fc41a712b089d45f6353e5a576f9b72082f Mon Sep 17 00:00:00 2001 From: Stefan Mirea Date: Thu, 13 Jun 2013 18:36:21 -0700 Subject: [PATCH 412/615] Bug 852411 - Migrating from promise.js to Promise.jsm; r=gps --HG-- extra : rebase_source : d03cdae978479605df0a7ea728916ba78a272ffb --- .../browser_datareporting_notification.js | 1 - .../browser_urlbar_search_healthreport.js | 4 +- .../search/test/browser_healthreport.js | 2 +- services/common/bagheeraclient.js | 2 +- services/common/utils.js | 2 +- services/datareporting/policy.jsm | 17 ++-- .../tests/xpcshell/test_policy.js | 78 +++++++------------ .../tests/xpcshell/test_session_recorder.js | 2 +- services/healthreport/healthreporter.jsm | 2 +- .../healthreport/modules-testing/utils.jsm | 2 +- services/healthreport/profile.jsm | 2 +- services/healthreport/providers.jsm | 2 +- .../tests/xpcshell/test_healthreporter.js | 2 +- .../tests/xpcshell/test_profile.js | 2 +- .../tests/xpcshell/test_provider_sessions.js | 2 +- services/metrics/dataprovider.jsm | 2 +- services/metrics/modules-testing/mocks.jsm | 2 +- services/metrics/providermanager.jsm | 2 +- services/metrics/storage.jsm | 2 +- .../xpcshell/test_metrics_provider_manager.js | 2 +- .../tests/xpcshell/test_metrics_storage.js | 2 +- .../sync/tests/unit/test_bookmark_engine.js | 2 +- services/sync/tests/unit/test_corrupt_keys.js | 2 +- 23 files changed, 59 insertions(+), 79 deletions(-) diff --git a/browser/base/content/test/browser_datareporting_notification.js b/browser/base/content/test/browser_datareporting_notification.js index 51c3bdeb7535..b892bd00922f 100644 --- a/browser/base/content/test/browser_datareporting_notification.js +++ b/browser/base/content/test/browser_datareporting_notification.js @@ -23,7 +23,6 @@ function sendNotifyRequest(name) { service.healthReporter.onInit().then(function onInit() { is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy."); - is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for notification response."); }); return policy; diff --git a/browser/base/content/test/browser_urlbar_search_healthreport.js b/browser/base/content/test/browser_urlbar_search_healthreport.js index 215aa63141bc..4315a98649ed 100644 --- a/browser/base/content/test/browser_urlbar_search_healthreport.js +++ b/browser/base/content/test/browser_urlbar_search_healthreport.js @@ -45,7 +45,7 @@ function test() { gURLBar.value = "firefox health report"; gURLBar.handleCommand(); - executeSoon(function afterSearch() { + executeSoon(() => executeSoon(() => { gBrowser.removeTab(tab); m.getValues().then(function onData(data) { @@ -58,7 +58,7 @@ function test() { is(newCount, oldCount + 1, "Exactly one search has been recorded."); finish(); }); - }); + })); }); }); } diff --git a/browser/components/search/test/browser_healthreport.js b/browser/components/search/test/browser_healthreport.js index d70191560df0..58dc9d881ab5 100644 --- a/browser/components/search/test/browser_healthreport.js +++ b/browser/components/search/test/browser_healthreport.js @@ -66,7 +66,7 @@ function test() { } EventUtils.synthesizeKey("VK_RETURN", {}); - executeSoon(afterSearch); + executeSoon(() => executeSoon(afterSearch)); }); }); } diff --git a/services/common/bagheeraclient.js b/services/common/bagheeraclient.js index 67295de9875a..ef889915268a 100644 --- a/services/common/bagheeraclient.js +++ b/services/common/bagheeraclient.js @@ -22,7 +22,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/rest.js"); diff --git a/services/common/utils.js b/services/common/utils.js index e07c31731c89..fb441cd65a72 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -6,7 +6,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; this.EXPORTED_SYMBOLS = ["CommonUtils"]; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm") diff --git a/services/datareporting/policy.jsm b/services/datareporting/policy.jsm index 32e99fe282f9..ac93644277b2 100644 --- a/services/datareporting/policy.jsm +++ b/services/datareporting/policy.jsm @@ -26,7 +26,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); @@ -69,12 +69,12 @@ const OLDEST_ALLOWED_YEAR = 2012; * * @param policy * (DataReportingPolicy) The policy instance this request came from. - * @param promise + * @param deferred * (deferred) The promise that will be fulfilled when display occurs. */ -function NotifyPolicyRequest(policy, promise) { +function NotifyPolicyRequest(policy, deferred) { this.policy = policy; - this.promise = promise; + this.deferred = deferred; } NotifyPolicyRequest.prototype = { /** @@ -84,7 +84,8 @@ NotifyPolicyRequest.prototype = { * acceptance of the data policy. */ onUserNotifyComplete: function onUserNotified() { - this.promise.resolve(); + this.deferred.resolve(); + return this.deferred.promise; }, /** @@ -94,7 +95,7 @@ NotifyPolicyRequest.prototype = { * (Error) Explains what went wrong. */ onUserNotifyFailed: function onUserNotifyFailed(error) { - this.promise.reject(error); + this.deferred.reject(error); }, /** @@ -158,6 +159,7 @@ DataSubmissionRequest.prototype = { onNoDataAvailable: function onNoDataAvailable() { this.state = this.NO_DATA_AVAILABLE; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -173,6 +175,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_SUCCESS; this.submissionDate = date; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -188,6 +191,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_SOFT; this.reason = reason; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -204,6 +208,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_HARD; this.reason = reason; this.promise.resolve(this); + return this.promise.promise; }, }; diff --git a/services/datareporting/tests/xpcshell/test_policy.js b/services/datareporting/tests/xpcshell/test_policy.js index 4cc9ad607332..a36add0ae80f 100644 --- a/services/datareporting/tests/xpcshell/test_policy.js +++ b/services/datareporting/tests/xpcshell/test_policy.js @@ -138,7 +138,7 @@ add_test(function test_notify_state_prefs() { run_next_test(); }); -add_test(function test_initial_submission_notification() { +add_task(function test_initial_submission_notification() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("initial_submission_notification"); do_check_eq(listener.notifyUserCount, 0); @@ -160,14 +160,12 @@ add_test(function test_initial_submission_notification() { policy.SUBMISSION_NOTIFY_INTERVAL_MSEC)); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_true(policy._dataSubmissionPolicyNotifiedDate instanceof Date); do_check_true(policy.dataSubmissionPolicyNotifiedDate.getTime() > 0); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), policy._dataSubmissionPolicyNotifiedDate.getTime()); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); - - run_next_test(); }); add_test(function test_bypass_acceptance() { @@ -183,7 +181,7 @@ add_test(function test_bypass_acceptance() { run_next_test(); }); -add_test(function test_notification_implicit_acceptance() { +add_task(function test_notification_implicit_acceptance() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_implicit_acceptance"); let now = new Date(policy.nextDataSubmissionDate.getTime() - @@ -191,7 +189,7 @@ add_test(function test_notification_implicit_acceptance() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.dataSubmissionPolicyResponseType, "none-recorded"); do_check_true(5000 < policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC); @@ -208,11 +206,9 @@ add_test(function test_notification_implicit_acceptance() { do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), policy.now().getTime()); do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-implicit-time-elapsed"); - - run_next_test(); }); -add_test(function test_notification_rejected() { +add_task(function test_notification_rejected() { // User notification failed. We should not record it as being presented. let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_failed"); @@ -221,22 +217,20 @@ add_test(function test_notification_rejected() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); + yield listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); do_check_null(policy._dataSubmissionPolicyNotifiedDate); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED); - - run_next_test(); }); -add_test(function test_notification_accepted() { +add_task(function test_notification_accepted() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_accepted"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserNotifyComplete(); @@ -245,18 +239,16 @@ add_test(function test_notification_accepted() { do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-foo-bar"); do_check_true(policy.dataSubmissionPolicyAccepted); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), now.getTime()); - - run_next_test(); }); -add_test(function test_notification_rejected() { +add_task(function test_notification_rejected() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_rejected"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserReject(); @@ -268,8 +260,6 @@ add_test(function test_notification_rejected() { defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime() + 10000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 0); - - run_next_test(); }); add_test(function test_submission_kill_switch() { @@ -331,7 +321,7 @@ add_test(function test_data_submission_no_data() { run_next_test(); }); -add_test(function test_data_submission_submit_failure_hard() { +add_task(function test_data_submission_submit_failure_hard() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_submit_failure_hard"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -342,7 +332,7 @@ add_test(function test_data_submission_submit_failure_hard() { policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); - listener.lastDataRequest.onSubmissionFailureHard(); + yield listener.lastDataRequest.onSubmissionFailureHard(); do_check_eq(listener.lastDataRequest.state, listener.lastDataRequest.SUBMISSION_FAILURE_HARD); @@ -352,11 +342,9 @@ add_test(function test_data_submission_submit_failure_hard() { defineNow(policy, new Date(now.getTime() + 10)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); - - run_next_test(); }); -add_test(function test_data_submission_submit_try_again() { +add_task(function test_data_submission_submit_try_again() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_failure_soft"); policy.recordUserAcceptance(); @@ -364,14 +352,12 @@ add_test(function test_data_submission_submit_try_again() { let now = new Date(policy.nextDataSubmissionDate.getTime()); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.nextDataSubmissionDate.getTime(), nextDataSubmissionDate.getTime() + 15 * 60 * 1000); - - run_next_test(); }); -add_test(function test_submission_daily_scheduling() { +add_task(function test_submission_daily_scheduling() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_daily_scheduling"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -387,7 +373,7 @@ add_test(function test_submission_daily_scheduling() { let finishedDate = new Date(now.getTime() + 250); defineNow(policy, new Date(finishedDate.getTime() + 50)); - listener.lastDataRequest.onSubmissionSuccess(finishedDate); + yield listener.lastDataRequest.onSubmissionSuccess(finishedDate); do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), finishedDate.getTime()); // Next scheduled submission should be exactly 1 day after the reported @@ -404,11 +390,9 @@ add_test(function test_submission_daily_scheduling() { defineNow(policy, nextScheduled); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 2); - listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); + yield listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(nextScheduled.getTime() + 24 * 60 * 60 * 1000 + 200).getTime()); - - run_next_test(); }); add_test(function test_submission_far_future_scheduling() { @@ -435,7 +419,7 @@ add_test(function test_submission_far_future_scheduling() { run_next_test(); }); -add_test(function test_submission_backoff() { +add_task(function test_submission_backoff() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_backoff"); do_check_eq(policy.FAILURE_BACKOFF_INTERVALS.length, 2); @@ -453,7 +437,7 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On first soft failure we should back off by scheduled interval. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 1); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[0]).getTime()); @@ -475,7 +459,7 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On second failure we should back off by more. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 2); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[1]).getTime()); @@ -489,12 +473,10 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On 3rd failure we should back off by a whole day. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 0); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + 24 * 60 * 60 * 1000).getTime()); - - run_next_test(); }); // Ensure that only one submission request can be active at a time. @@ -521,7 +503,7 @@ add_test(function test_submission_expiring() { run_next_test(); }); -add_test(function test_delete_remote_data() { +add_task(function test_delete_remote_data() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data"); do_check_false(policy.pendingDeleteRemoteData); @@ -540,10 +522,8 @@ add_test(function test_delete_remote_data() { do_check_true(listener.lastRemoteDeleteRequest.isDelete); defineNow(policy, policy._futureDate(1000)); - listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); + yield listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); do_check_false(policy.pendingDeleteRemoteData); - - run_next_test(); }); // Ensure that deletion requests take priority over regular data submission. @@ -601,7 +581,7 @@ add_test(function test_delete_remote_data_backoff() { // If we request delete while an upload is in progress, delete should be // scheduled immediately after upload. -add_test(function test_delete_remote_data_in_progress_upload() { +add_task(function test_delete_remote_data_in_progress_upload() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_in_progress_upload"); let now = new Date(); @@ -621,14 +601,12 @@ add_test(function test_delete_remote_data_in_progress_upload() { // Now wait a little bit and finish the request. defineNow(policy, policy._futureDate(10 * 1000)); - listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); + yield listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); defineNow(policy, policy._futureDate(5000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); do_check_eq(listener.requestRemoteDeleteCount, 1); - - run_next_test(); }); add_test(function test_polling() { @@ -747,7 +725,7 @@ add_test(function test_polling_implicit_acceptance() { policy.startPolling(); }); -add_test(function test_record_health_report_upload_enabled() { +add_task(function test_record_health_report_upload_enabled() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("record_health_report_upload_enabled"); // Preconditions. @@ -763,15 +741,13 @@ add_test(function test_record_health_report_upload_enabled() { do_check_eq(listener.requestRemoteDeleteCount, 1); // Fulfilling it should make it go away. - listener.lastRemoteDeleteRequest.onNoDataAvailable(); + yield listener.lastRemoteDeleteRequest.onNoDataAvailable(); do_check_false(policy.pendingDeleteRemoteData); // User intent to enable should get us back to default state. policy.recordHealthReportUploadEnabled(true, "testing 1 2 3"); do_check_false(policy.pendingDeleteRemoteData); do_check_true(policy.healthReportUploadEnabled); - - run_next_test(); }); add_test(function test_pref_change_initiates_deletion() { diff --git a/services/datareporting/tests/xpcshell/test_session_recorder.js b/services/datareporting/tests/xpcshell/test_session_recorder.js index 0ea3919a6cbc..1e8b04233d66 100644 --- a/services/datareporting/tests/xpcshell/test_session_recorder.js +++ b/services/datareporting/tests/xpcshell/test_session_recorder.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/services/datareporting/sessions.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/healthreport/healthreporter.jsm b/services/healthreport/healthreporter.jsm index b776f881bda0..3fdc91250d35 100644 --- a/services/healthreport/healthreporter.jsm +++ b/services/healthreport/healthreporter.jsm @@ -20,7 +20,7 @@ Cu.import("resource://services-common/bagheeraclient.js"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/modules-testing/utils.jsm b/services/healthreport/modules-testing/utils.jsm index f1f90c965f08..bf0a4cc713f2 100644 --- a/services/healthreport/modules-testing/utils.jsm +++ b/services/healthreport/modules-testing/utils.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); diff --git a/services/healthreport/profile.jsm b/services/healthreport/profile.jsm index cd4457cec9ea..e3aa031d2978 100644 --- a/services/healthreport/profile.jsm +++ b/services/healthreport/profile.jsm @@ -22,7 +22,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); const DEFAULT_PROFILE_MEASUREMENT_NAME = "age"; const REQUIRED_UINT32_TYPE = {type: "TYPE_UINT32"}; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm") Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/healthreport/providers.jsm b/services/healthreport/providers.jsm index b65d0d6191a1..85a50c8f29cd 100644 --- a/services/healthreport/providers.jsm +++ b/services/healthreport/providers.jsm @@ -34,7 +34,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_healthreporter.js b/services/healthreport/tests/xpcshell/test_healthreporter.js index 265e066e64de..022521216bc1 100644 --- a/services/healthreport/tests/xpcshell/test_healthreporter.js +++ b/services/healthreport/tests/xpcshell/test_healthreporter.js @@ -7,7 +7,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://services-common/observers.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_profile.js b/services/healthreport/tests/xpcshell/test_profile.js index d17a53832fb3..ef4a51b6f04e 100644 --- a/services/healthreport/tests/xpcshell/test_profile.js +++ b/services/healthreport/tests/xpcshell/test_profile.js @@ -12,7 +12,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; let profile_creation_lower = Date.now() - MILLISECONDS_PER_DAY; do_get_profile(); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/services/healthreport/profile.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_provider_sessions.js b/services/healthreport/tests/xpcshell/test_provider_sessions.js index 07f90ce8f495..59e190d0eb78 100644 --- a/services/healthreport/tests/xpcshell/test_provider_sessions.js +++ b/services/healthreport/tests/xpcshell/test_provider_sessions.js @@ -6,7 +6,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/services-common/utils.js"); diff --git a/services/metrics/dataprovider.jsm b/services/metrics/dataprovider.jsm index 0be60e46c105..d6d2ca90c597 100644 --- a/services/metrics/dataprovider.jsm +++ b/services/metrics/dataprovider.jsm @@ -17,7 +17,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/modules-testing/mocks.jsm b/services/metrics/modules-testing/mocks.jsm index ba4bf4142beb..032f167a9620 100644 --- a/services/metrics/modules-testing/mocks.jsm +++ b/services/metrics/modules-testing/mocks.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/metrics/providermanager.jsm b/services/metrics/providermanager.jsm index 44d10d8f1693..631df1f568cf 100644 --- a/services/metrics/providermanager.jsm +++ b/services/metrics/providermanager.jsm @@ -12,7 +12,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm"); #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); diff --git a/services/metrics/storage.jsm b/services/metrics/storage.jsm index 60b84ad60948..241518f3c195 100644 --- a/services/metrics/storage.jsm +++ b/services/metrics/storage.jsm @@ -19,7 +19,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Sqlite.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js index 4137a06f2782..232753e201ec 100644 --- a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js +++ b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js @@ -5,7 +5,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://testing-common/services/metrics/mocks.jsm"); diff --git a/services/metrics/tests/xpcshell/test_metrics_storage.js b/services/metrics/tests/xpcshell/test_metrics_storage.js index 6c59fb127b4c..42763dd32fa4 100644 --- a/services/metrics/tests/xpcshell/test_metrics_storage.js +++ b/services/metrics/tests/xpcshell/test_metrics_storage.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index aa486c3e0471..fda9260e0a43 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -10,7 +10,7 @@ Cu.import("resource://services-sync/engines/bookmarks.js"); Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Service.engineManager.register(BookmarksEngine); var syncTesting = new SyncTestingInfrastructure(); diff --git a/services/sync/tests/unit/test_corrupt_keys.js b/services/sync/tests/unit/test_corrupt_keys.js index ecbad7546201..9ee0f34b3f30 100644 --- a/services/sync/tests/unit/test_corrupt_keys.js +++ b/services/sync/tests/unit/test_corrupt_keys.js @@ -11,7 +11,7 @@ Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/status.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); add_task(function test_locally_changed_keys() { let passphrase = "abcdeabcdeabcdeabcdeabcdea"; From 50a0ee935592a710504db97567e8e07efbdbaf67 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:39 -0500 Subject: [PATCH 413/615] Bug 872735, part 1 - Remove isEmptySemicolon from the ParseHandler protocol. It was only used for a warning about "if (foo);". r=Waldo. --- js/src/frontend/FullParseHandler.h | 3 --- js/src/frontend/Parser.cpp | 12 ++++++------ js/src/frontend/SyntaxParseHandler.h | 1 - 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 6588bd3e1997..0ee046106b8d 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -292,9 +292,6 @@ class FullParseHandler } return NULL; } - bool isEmptySemicolon(ParseNode *pn) { - return pn->isKind(PNK_SEMI) && !pn->pn_kid; - } inline ParseNode *makeAssignment(ParseNode *pn, ParseNode *rhs); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index b1202e146c92..2e3eafe416f9 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4582,18 +4582,18 @@ Parser::statement() if (!cond) return null(); + if (tokenStream.peekToken() == TOK_SEMI && + !report(ParseExtraWarning, false, null(), JSMSG_EMPTY_CONSEQUENT)) + { + return null(); + } + StmtInfoPC stmtInfo(context); PushStatementPC(pc, &stmtInfo, STMT_IF); Node thenBranch = statement(); if (!thenBranch) return null(); - if (handler.isEmptySemicolon(thenBranch) && - !report(ParseExtraWarning, false, null(), JSMSG_EMPTY_CONSEQUENT)) - { - return null(); - } - Node elseBranch; if (tokenStream.matchToken(TOK_ELSE, TSF_OPERAND)) { stmtInfo.type = STMT_ELSE; diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index a4e963f28318..088a41ffa4fc 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -174,7 +174,6 @@ class SyntaxParseHandler } return NULL; } - bool isEmptySemicolon(Node pn) { return false; } Node makeAssignment(Node pn, Node rhs) { return NodeGeneric; } From 56565de69be4df7f338d2610cf5240b8b777a870 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:39 -0500 Subject: [PATCH 414/615] Bug 872735, part 2 - Remove noteLValue from the handler protocol. The main point of this change is to remove the noteLValue method from SyntaxParseHandler, because who knows what that is supposed to mean (anyway it is never called). r=Waldo. --- js/src/frontend/FullParseHandler.h | 12 +----------- js/src/frontend/ParseNode.h | 10 ++++++++++ js/src/frontend/Parser.cpp | 10 +++++----- js/src/frontend/SyntaxParseHandler.h | 1 - 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 0ee046106b8d..3c21af0d9296 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -213,7 +213,6 @@ class FullParseHandler return pn->isKind(kind) && !pn->isInParens(); } - inline void noteLValue(ParseNode *pn); inline bool finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op); void setBeginPosition(ParseNode *pn, ParseNode *oth) { @@ -416,15 +415,6 @@ FullParseHandler::newLexicalScope(ObjectBox *blockbox) return pn; } -inline void -FullParseHandler::noteLValue(ParseNode *pn) -{ - if (pn->isUsed()) - pn->pn_lexdef->pn_dflags |= PND_ASSIGNED; - - pn->pn_dflags |= PND_ASSIGNED; -} - inline bool FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JSOp op) { @@ -442,7 +432,7 @@ FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JS ? JSOP_SETCONST : JSOP_SETNAME); - noteLValue(pn); + pn->noteLValue(); /* The declarator's position must include the initializer. */ pn->pn_pos.end = init->pn_pos.end; diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index c3e0b2b79b55..014e3d03177a 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -738,6 +738,8 @@ struct ParseNode { } #endif + inline void noteLValue(); + /* * Compute a pointer to the last element in a singly-linked list. NB: list * must be non-empty for correct PN_LAST usage -- this is asserted! @@ -1268,6 +1270,14 @@ ParseNode::test(unsigned flag) const return !!(pn_dflags & flag); } +inline void +ParseNode::noteLValue() +{ + if (isUsed()) + pn_lexdef->pn_dflags |= PND_ASSIGNED; + pn_dflags |= PND_ASSIGNED; +} + inline Definition * ParseNode::resolve() { diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 2e3eafe416f9..c4ae0d4eb052 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2997,7 +2997,7 @@ Parser::bindDestructuringVar(BindData *data, if (data->op == JSOP_DEFCONST) pn->pn_dflags |= PND_CONST; - handler.noteLValue(pn); + pn->noteLValue(); return true; } @@ -3025,7 +3025,7 @@ Parser::bindDestructuringLHS(ParseNode *pn) { switch (pn->getKind()) { case PNK_NAME: - handler.noteLValue(pn); + pn->noteLValue(); /* FALL THROUGH */ case PNK_DOT: @@ -3920,7 +3920,7 @@ Parser::forStatement() switch (pn2->getKind()) { case PNK_NAME: /* Beware 'for (arguments in ...)' with or without a 'var'. */ - handler.noteLValue(pn2); + pn2->noteLValue(); break; #if JS_HAS_DESTRUCTURING @@ -5216,7 +5216,7 @@ Parser::setAssignmentLhsOps(ParseNode *pn, JSOp op) if (!checkStrictAssignment(pn)) return false; pn->setOp(pn->isOp(JSOP_GETLOCAL) ? JSOP_SETLOCAL : JSOP_SETNAME); - handler.noteLValue(pn); + pn->noteLValue(); break; case PNK_DOT: pn->setOp(JSOP_SETPROP); @@ -5357,7 +5357,7 @@ Parser::setIncOpKid(ParseNode *pn, ParseNode *kid, TokenKind t switch (kid->getKind()) { case PNK_NAME: - handler.noteLValue(kid); + kid->noteLValue(); break; case PNK_CALL: diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 088a41ffa4fc..27d586f36dcb 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -129,7 +129,6 @@ class SyntaxParseHandler return false; } - void noteLValue(Node pn) {} bool finishInitializerAssignment(Node pn, Node init, JSOp op) { return true; } void setBeginPosition(Node pn, Node oth) {} From 12bf3bb1a051601b8d127618c0931e492ee0fcf8 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:39 -0500 Subject: [PATCH 415/615] Bug 872735, part 2a - Rename ParseNode::noteLValue -> markAsAssigned and add an assertion about pn_op, as requested in review. rs=Waldo. --- js/src/frontend/FullParseHandler.h | 2 +- js/src/frontend/ParseNode.h | 5 +++-- js/src/frontend/Parser.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 3c21af0d9296..3fa30cf8935c 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -432,7 +432,7 @@ FullParseHandler::finishInitializerAssignment(ParseNode *pn, ParseNode *init, JS ? JSOP_SETCONST : JSOP_SETNAME); - pn->noteLValue(); + pn->markAsAssigned(); /* The declarator's position must include the initializer. */ pn->pn_pos.end = init->pn_pos.end; diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 014e3d03177a..0ae7d83d752b 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -738,7 +738,7 @@ struct ParseNode { } #endif - inline void noteLValue(); + inline void markAsAssigned(); /* * Compute a pointer to the last element in a singly-linked list. NB: list @@ -1271,8 +1271,9 @@ ParseNode::test(unsigned flag) const } inline void -ParseNode::noteLValue() +ParseNode::markAsAssigned() { + JS_ASSERT(js_CodeSpec[pn_op].format & JOF_NAME); if (isUsed()) pn_lexdef->pn_dflags |= PND_ASSIGNED; pn_dflags |= PND_ASSIGNED; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index c4ae0d4eb052..43b54df39fd4 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2997,7 +2997,7 @@ Parser::bindDestructuringVar(BindData *data, if (data->op == JSOP_DEFCONST) pn->pn_dflags |= PND_CONST; - pn->noteLValue(); + pn->markAsAssigned(); return true; } @@ -3025,7 +3025,7 @@ Parser::bindDestructuringLHS(ParseNode *pn) { switch (pn->getKind()) { case PNK_NAME: - pn->noteLValue(); + pn->markAsAssigned(); /* FALL THROUGH */ case PNK_DOT: @@ -3920,7 +3920,7 @@ Parser::forStatement() switch (pn2->getKind()) { case PNK_NAME: /* Beware 'for (arguments in ...)' with or without a 'var'. */ - pn2->noteLValue(); + pn2->markAsAssigned(); break; #if JS_HAS_DESTRUCTURING @@ -5216,7 +5216,7 @@ Parser::setAssignmentLhsOps(ParseNode *pn, JSOp op) if (!checkStrictAssignment(pn)) return false; pn->setOp(pn->isOp(JSOP_GETLOCAL) ? JSOP_SETLOCAL : JSOP_SETNAME); - pn->noteLValue(); + pn->markAsAssigned(); break; case PNK_DOT: pn->setOp(JSOP_SETPROP); @@ -5357,7 +5357,7 @@ Parser::setIncOpKid(ParseNode *pn, ParseNode *kid, TokenKind t switch (kid->getKind()) { case PNK_NAME: - kid->noteLValue(); + kid->markAsAssigned(); break; case PNK_CALL: From dca3ea32f8a600c667f046e394a7509a28f81f3e Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:40 -0500 Subject: [PATCH 416/615] Bug 872735, part 3 - Add PNK_LABEL for labeled statement nodes. Remove ForgetUse. r=Waldo. --- js/src/frontend/BytecodeEmitter.cpp | 14 ++- js/src/frontend/FullParseHandler.h | 14 +-- js/src/frontend/ParseNode.h | 99 ++++++++++++++++----- js/src/frontend/Parser.cpp | 91 ++++++++----------- js/src/frontend/Parser.h | 1 + js/src/frontend/SyntaxParseHandler.h | 4 +- js/src/ion/AsmJS.cpp | 10 +-- js/src/jit-test/tests/modules/nonkeyword.js | 2 + js/src/jsreflect.cpp | 4 +- js/src/tests/ecma_2/Statements/label-003.js | 15 ++++ 10 files changed, 148 insertions(+), 106 deletions(-) create mode 100644 js/src/tests/ecma_2/Statements/label-003.js diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 2bb049b3b434..8c019a8a7a47 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -5281,16 +5281,14 @@ EmitIncOrDec(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) * the comment on EmitSwitch. */ MOZ_NEVER_INLINE static bool -EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) +EmitLabeledStatement(JSContext *cx, BytecodeEmitter *bce, const LabeledStatement *pn) { /* * Emit a JSOP_LABEL instruction. The argument is the offset to the statement * following the labeled statement. */ - JSAtom *atom = pn->pn_atom; - jsatomid index; - if (!bce->makeAtomIndex(atom, &index)) + if (!bce->makeAtomIndex(pn->label(), &index)) return false; ptrdiff_t top = EmitJump(cx, bce, JSOP_LABEL, 0); @@ -5300,8 +5298,8 @@ EmitLabel(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) /* Emit code for the labeled statement. */ StmtInfoBCE stmtInfo(cx); PushStatementBCE(bce, &stmtInfo, STMT_LABEL, bce->offset()); - stmtInfo.label = atom; - if (!EmitTree(cx, bce, pn->expr())) + stmtInfo.label = pn->label(); + if (!EmitTree(cx, bce, pn->statement())) return false; if (!PopStatementBCE(cx, bce)) return false; @@ -5833,8 +5831,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) ok = EmitStatement(cx, bce, pn); break; - case PNK_COLON: - ok = EmitLabel(cx, bce, pn); + case PNK_LABEL: + ok = EmitLabeledStatement(cx, bce, &pn->as()); break; case PNK_COMMA: diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index 3fa30cf8935c..b6172b4339e3 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -174,6 +174,10 @@ class FullParseHandler return new_(kind, op, first, second, third); } + ParseNode *newLabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) { + return new_(label, stmt, begin); + } + ParseNode *newBreak(PropertyName *label, uint32_t begin, uint32_t end) { return new_(label, begin, end); } @@ -193,8 +197,6 @@ class FullParseHandler inline bool addCatchBlock(ParseNode *catchList, ParseNode *letBlock, ParseNode *catchName, ParseNode *catchGuard, ParseNode *catchBody); - inline void morphNameIntoLabel(ParseNode *name, ParseNode *statement); - inline void setLeaveBlockResult(ParseNode *block, ParseNode *kid, bool leaveBlockExpr); inline void setLastFunctionArgumentDefault(ParseNode *funcpn, ParseNode *pn); @@ -363,14 +365,6 @@ FullParseHandler::addCatchBlock(ParseNode *catchList, ParseNode *letBlock, return true; } -inline void -FullParseHandler::morphNameIntoLabel(ParseNode *name, ParseNode *statement) -{ - name->setKind(PNK_COLON); - name->pn_pos.end = statement->pn_pos.end; - name->pn_expr = statement; -} - inline void FullParseHandler::setLeaveBlockResult(ParseNode *block, ParseNode *kid, bool leaveBlockExpr) { diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 0ae7d83d752b..044074edd3f0 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -76,6 +76,7 @@ class UpvarCookie F(ELEM) \ F(ARRAY) \ F(STATEMENTLIST) \ + F(LABEL) \ F(OBJECT) \ F(CALL) \ F(NAME) \ @@ -181,7 +182,8 @@ class UpvarCookie * * The long comment after this enum block describes the kinds in detail. */ -enum ParseNodeKind { +enum ParseNodeKind +{ #define EMIT_ENUM(name) PNK_##name, FOR_EACH_PARSE_NODE_KIND(EMIT_ENUM) #undef EMIT_ENUM @@ -284,7 +286,7 @@ enum ParseNodeKind { * pn_prologue: true if Directive Prologue member * in original source, not introduced via * constant folding or other tree rewriting - * PNK_COLON name pn_atom: label, pn_expr: labeled statement + * PNK_LABEL name pn_atom: label, pn_expr: labeled statement * * * All left-associated binary trees of the same type are optimized into lists @@ -392,7 +394,8 @@ enum ParseNodeKind { * pn_kid: array comprehension expression * PNK_NOP nullary */ -enum ParseNodeArity { +enum ParseNodeArity +{ PN_NULLARY, /* 0 kids, only pn_atom/pn_dval/etc. */ PN_UNARY, /* one kid, plus a couple of scalars */ PN_BINARY, /* two kids, plus a couple of scalars */ @@ -404,6 +407,7 @@ enum ParseNodeArity { struct Definition; +class LabeledStatement; class LoopControlStatement; class BreakStatement; class ContinueStatement; @@ -411,7 +415,8 @@ class ConditionalExpression; class PropertyAccess; class ModuleBox; -struct ParseNode { +struct ParseNode +{ private: uint32_t pn_type : 16, /* PNK_* type */ pn_op : 8, /* see JSOp enum and jsopcode.tbl */ @@ -815,7 +820,8 @@ struct ParseNode { #endif }; -struct NullaryNode : public ParseNode { +struct NullaryNode : public ParseNode +{ static inline NullaryNode *create(ParseNodeKind kind, FullParseHandler *handler) { return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, handler); } @@ -829,7 +835,8 @@ struct NullaryNode : public ParseNode { #endif }; -struct UnaryNode : public ParseNode { +struct UnaryNode : public ParseNode +{ UnaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *kid) : ParseNode(kind, op, PN_UNARY, pos) { @@ -849,7 +856,8 @@ struct UnaryNode : public ParseNode { #endif }; -struct BinaryNode : public ParseNode { +struct BinaryNode : public ParseNode +{ BinaryNode(ParseNodeKind kind, JSOp op, const TokenPos &pos, ParseNode *left, ParseNode *right) : ParseNode(kind, op, PN_BINARY, pos) { @@ -877,7 +885,8 @@ struct BinaryNode : public ParseNode { #endif }; -struct TernaryNode : public ParseNode { +struct TernaryNode : public ParseNode +{ TernaryNode(ParseNodeKind kind, JSOp op, ParseNode *kid1, ParseNode *kid2, ParseNode *kid3) : ParseNode(kind, op, PN_TERNARY, TokenPos::make((kid1 ? kid1 : kid2 ? kid2 : kid3)->pn_pos.begin, @@ -923,7 +932,8 @@ struct ListNode : public ParseNode #endif }; -struct CodeNode : public ParseNode { +struct CodeNode : public ParseNode +{ static inline CodeNode *create(ParseNodeKind kind, FullParseHandler *handler) { return (CodeNode *) ParseNode::create(kind, PN_CODE, handler); } @@ -937,7 +947,8 @@ struct CodeNode : public ParseNode { #endif }; -struct NameNode : public ParseNode { +struct NameNode : public ParseNode +{ static NameNode *create(ParseNodeKind kind, JSAtom *atom, FullParseHandler *handler, ParseContext *pc); @@ -952,13 +963,41 @@ struct NameNode : public ParseNode { #endif }; -struct LexicalScopeNode : public ParseNode { +struct LexicalScopeNode : public ParseNode +{ static inline LexicalScopeNode *create(ParseNodeKind kind, FullParseHandler *handler) { return (LexicalScopeNode *) ParseNode::create(kind, PN_NAME, handler); } }; -class LoopControlStatement : public ParseNode { +class LabeledStatement : public ParseNode +{ + public: + LabeledStatement(PropertyName *label, ParseNode *stmt, uint32_t begin) + : ParseNode(PNK_LABEL, JSOP_NOP, PN_NAME, TokenPos::make(begin, stmt->pn_pos.end)) + { + pn_atom = label; + pn_expr = stmt; + } + + PropertyName *label() const { + return pn_atom->asPropertyName(); + } + + ParseNode *statement() const { + return pn_expr; + } + + static bool test(const ParseNode &node) { + bool match = node.isKind(PNK_LABEL); + JS_ASSERT_IF(match, node.isArity(PN_NAME)); + JS_ASSERT_IF(match, node.isOp(JSOP_NOP)); + return match; + } +}; + +class LoopControlStatement : public ParseNode +{ protected: LoopControlStatement(ParseNodeKind kind, PropertyName *label, uint32_t begin, uint32_t end) : ParseNode(kind, JSOP_NOP, PN_NULLARY, TokenPos::make(begin, end)) @@ -981,7 +1020,8 @@ class LoopControlStatement : public ParseNode { } }; -class BreakStatement : public LoopControlStatement { +class BreakStatement : public LoopControlStatement +{ public: BreakStatement(PropertyName *label, uint32_t begin, uint32_t end) : LoopControlStatement(PNK_BREAK, label, begin, end) @@ -995,7 +1035,8 @@ class BreakStatement : public LoopControlStatement { } }; -class ContinueStatement : public LoopControlStatement { +class ContinueStatement : public LoopControlStatement +{ public: ContinueStatement(PropertyName *label, uint32_t begin, uint32_t end) : LoopControlStatement(PNK_CONTINUE, label, begin, end) @@ -1009,14 +1050,16 @@ class ContinueStatement : public LoopControlStatement { } }; -class DebuggerStatement : public ParseNode { +class DebuggerStatement : public ParseNode +{ public: DebuggerStatement(const TokenPos &pos) : ParseNode(PNK_DEBUGGER, JSOP_NOP, PN_NULLARY, pos) { } }; -class ConditionalExpression : public ParseNode { +class ConditionalExpression : public ParseNode +{ public: ConditionalExpression(ParseNode *condition, ParseNode *thenExpr, ParseNode *elseExpr) : ParseNode(PNK_CONDITIONAL, JSOP_NOP, PN_TERNARY, @@ -1050,24 +1093,28 @@ class ConditionalExpression : public ParseNode { } }; -class ThisLiteral : public ParseNode { +class ThisLiteral : public ParseNode +{ public: ThisLiteral(const TokenPos &pos) : ParseNode(PNK_THIS, JSOP_THIS, PN_NULLARY, pos) { } }; -class NullLiteral : public ParseNode { +class NullLiteral : public ParseNode +{ public: NullLiteral(const TokenPos &pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { } }; -class BooleanLiteral : public ParseNode { +class BooleanLiteral : public ParseNode +{ public: BooleanLiteral(bool b, const TokenPos &pos) : ParseNode(b ? PNK_TRUE : PNK_FALSE, b ? JSOP_TRUE : JSOP_FALSE, PN_NULLARY, pos) { } }; -class PropertyAccess : public ParseNode { +class PropertyAccess : public ParseNode +{ public: PropertyAccess(ParseNode *lhs, PropertyName *name, uint32_t begin, uint32_t end) : ParseNode(PNK_DOT, JSOP_GETPROP, PN_NAME, TokenPos::make(begin, end)) @@ -1093,7 +1140,8 @@ class PropertyAccess : public ParseNode { } }; -class PropertyByValue : public ParseNode { +class PropertyByValue : public ParseNode +{ public: PropertyByValue(ParseNode *lhs, ParseNode *propExpr, uint32_t begin, uint32_t end) : ParseNode(PNK_ELEM, JSOP_GETELEM, PN_BINARY, TokenPos::make(begin, end)) @@ -1241,7 +1289,8 @@ struct Definition : public ParseNode } }; -class ParseNodeAllocator { +class ParseNodeAllocator +{ public: explicit ParseNodeAllocator(JSContext *cx) : cx(cx), freelist(NULL) {} @@ -1306,7 +1355,8 @@ ParseNode::isConstant() } } -class ObjectBox { +class ObjectBox +{ public: JSObject *object; @@ -1327,7 +1377,8 @@ class ObjectBox { ObjectBox(Module *module, ObjectBox *traceLink); }; -enum ParseReportKind { +enum ParseReportKind +{ ParseError, ParseWarning, ParseExtraWarning, diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 43b54df39fd4..e7f4585f93b5 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1079,27 +1079,6 @@ Parser::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ return pn; } -static void -ForgetUse(ParseNode *pn) -{ - if (!pn->isUsed()) { - JS_ASSERT(!pn->isDefn()); - return; - } - - ParseNode **pnup = &pn->lexdef()->dn_uses; - ParseNode *pnu; - while ((pnu = *pnup) != pn) - pnup = &pnu->pn_link; - *pnup = pn->pn_link; - pn->setUsed(false); -} - -static void -ForgetUse(SyntaxParseHandler::Node pn) -{ -} - /* See comment for use in Parser::functionDef. */ template <> bool @@ -4515,6 +4494,35 @@ Parser::letStatement() #endif // JS_HAS_BLOCK_SCOPE +template +typename ParseHandler::Node +Parser::labeledStatement() +{ + uint32_t begin = tokenStream.currentToken().pos.begin; + RootedPropertyName label(context, tokenStream.currentToken().name()); + for (StmtInfoPC *stmt = pc->topStmt; stmt; stmt = stmt->down) { + if (stmt->type == STMT_LABEL && stmt->label == label) { + report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL); + return null(); + } + } + + tokenStream.consumeKnownToken(TOK_COLON); + + /* Push a label struct and parse the statement. */ + StmtInfoPC stmtInfo(context); + PushStatementPC(pc, &stmtInfo, STMT_LABEL); + stmtInfo.label = label; + Node pn = statement(); + if (!pn) + return null(); + + /* Pop the label, set pn_expr, and return early. */ + PopStatementPC(context, pc); + + return handler.newLabeledStatement(label, pn, begin); +} + template typename ParseHandler::Node Parser::expressionStatement() @@ -4524,37 +4532,6 @@ Parser::expressionStatement() if (!pn2) return null(); - if (tokenStream.peekToken() == TOK_COLON) { - RootedAtom label(context, handler.isName(pn2)); - if (!label) { - report(ParseError, false, null(), JSMSG_BAD_LABEL); - return null(); - } - for (StmtInfoPC *stmt = pc->topStmt; stmt; stmt = stmt->down) { - if (stmt->type == STMT_LABEL && stmt->label == label) { - report(ParseError, false, null(), JSMSG_DUPLICATE_LABEL); - return null(); - } - } - ForgetUse(pn2); - - (void) tokenStream.getToken(); - - /* Push a label struct and parse the statement. */ - StmtInfoPC stmtInfo(context); - PushStatementPC(pc, &stmtInfo, STMT_LABEL); - stmtInfo.label = label; - Node pn = statement(); - if (!pn) - return null(); - - /* Pop the label, set pn_expr, and return early. */ - PopStatementPC(context, pc); - - handler.morphNameIntoLabel(pn2, pn); - return pn2; - } - Node pn = handler.newUnary(PNK_SEMI, pn2); /* Check termination of this primitive statement. */ @@ -4843,12 +4820,16 @@ Parser::statement() case TOK_ERROR: return null(); - case TOK_NAME: - if (tokenStream.currentToken().name() == context->names().module && - tokenStream.peekTokenSameLine(TSF_OPERAND) == TOK_STRING) + case TOK_NAME: { + if (tokenStream.peekToken() == TOK_COLON) + return labeledStatement(); + if (tokenStream.currentToken().name() == context->names().module + && tokenStream.peekTokenSameLine() == TOK_STRING) { return moduleDecl(); } + } + /* FALL THROUGH */ default: return expressionStatement(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 4a041f553c47..da2372de7ce2 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -425,6 +425,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter Node switchStatement(); Node forStatement(); + Node labeledStatement(); Node tryStatement(); Node withStatement(); #if JS_HAS_BLOCK_SCOPE diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 27d586f36dcb..9dd7da639a86 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -96,6 +96,9 @@ class SyntaxParseHandler return NodeGeneric; } + Node newLabeledStatement(PropertyName *label, Node stmt, uint32_t begin) { + return NodeGeneric; + } Node newBreak(PropertyName *label, uint32_t begin, uint32_t end) { return NodeGeneric; } @@ -113,7 +116,6 @@ class SyntaxParseHandler bool addCatchBlock(Node catchList, Node letBlock, Node catchName, Node catchGuard, Node catchBody) { return true; } - void morphNameIntoLabel(Node name, Node statement) {} void setLeaveBlockResult(Node block, Node kid, bool leaveBlockExpr) {} void setLastFunctionArgumentDefault(Node funcpn, Node pn) {} diff --git a/js/src/ion/AsmJS.cpp b/js/src/ion/AsmJS.cpp index 2c599d191413..c54d503f36fc 100644 --- a/js/src/ion/AsmJS.cpp +++ b/js/src/ion/AsmJS.cpp @@ -167,15 +167,13 @@ LoopControlMaybeLabel(ParseNode *pn) static inline PropertyName * LabeledStatementLabel(ParseNode *pn) { - JS_ASSERT(pn->isKind(PNK_COLON)); - return pn->pn_atom->asPropertyName(); + return pn->as().label(); } static inline ParseNode * LabeledStatementStatement(ParseNode *pn) { - JS_ASSERT(pn->isKind(PNK_COLON)); - return pn->expr(); + return pn->as().statement(); } static double @@ -4351,7 +4349,7 @@ CheckDoWhile(FunctionCompiler &f, ParseNode *whileStmt, const LabelVector *maybe static bool CheckLabel(FunctionCompiler &f, ParseNode *labeledStmt, LabelVector *maybeLabels) { - JS_ASSERT(labeledStmt->isKind(PNK_COLON)); + JS_ASSERT(labeledStmt->isKind(PNK_LABEL)); PropertyName *label = LabeledStatementLabel(labeledStmt); ParseNode *stmt = LabeledStatementStatement(labeledStmt); @@ -4622,7 +4620,7 @@ CheckStatement(FunctionCompiler &f, ParseNode *stmt, LabelVector *maybeLabels) case PNK_WHILE: return CheckWhile(f, stmt, maybeLabels); case PNK_FOR: return CheckFor(f, stmt, maybeLabels); case PNK_DOWHILE: return CheckDoWhile(f, stmt, maybeLabels); - case PNK_COLON: return CheckLabel(f, stmt, maybeLabels); + case PNK_LABEL: return CheckLabel(f, stmt, maybeLabels); case PNK_IF: return CheckIf(f, stmt); case PNK_SWITCH: return CheckSwitch(f, stmt); case PNK_RETURN: return CheckReturn(f, stmt); diff --git a/js/src/jit-test/tests/modules/nonkeyword.js b/js/src/jit-test/tests/modules/nonkeyword.js index deab3bb8025c..40dae8e5328d 100644 --- a/js/src/jit-test/tests/modules/nonkeyword.js +++ b/js/src/jit-test/tests/modules/nonkeyword.js @@ -4,3 +4,5 @@ module = {}; module.p = 0; assertEq(this.module.p, 0); +assertEq(eval('module \n "hello"'), "hello"); +assertEq(eval('module \n "world" \n {}'), "world"); diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index a76d8cc26cae..4798f73835ea 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -2147,12 +2147,12 @@ ASTSerializer::statement(ParseNode *pn, MutableHandleValue dst) : builder.continueStatement(label, &pn->pn_pos, dst)); } - case PNK_COLON: + case PNK_LABEL: { JS_ASSERT(pn->pn_pos.encloses(pn->pn_expr->pn_pos)); RootedValue label(cx), stmt(cx); - RootedAtom pnAtom(cx, pn->pn_atom); + RootedAtom pnAtom(cx, pn->as().label()); return identifier(pnAtom, NULL, &label) && statement(pn->pn_expr, &stmt) && builder.labeledStatement(label, stmt, &pn->pn_pos, dst); diff --git a/js/src/tests/ecma_2/Statements/label-003.js b/js/src/tests/ecma_2/Statements/label-003.js new file mode 100644 index 000000000000..d3ed464f5f8b --- /dev/null +++ b/js/src/tests/ecma_2/Statements/label-003.js @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +// The colon for a labeled statement may be on a separate line. +var x; +label +: { + x = 1; + break label; + x = 2; +} +assertEq(x, 1); +reportCompare(0, 0, 'ok'); From 0fd058b9679b87169de631ca3275ec9bb60fb97a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:40 -0500 Subject: [PATCH 417/615] Bug 872735, part 4 - Remove setBinaryRHS from the ParseHandler protocol. It was only used in parsing switch statements. It is replaced by a newCaseOrDefault method. r=Waldo. --- js/src/frontend/FullParseHandler.h | 11 ++++++----- js/src/frontend/Parser.cpp | 27 +++++++++++++-------------- js/src/frontend/SyntaxParseHandler.h | 4 +++- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index b6172b4339e3..e44243a87587 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -162,11 +162,6 @@ class FullParseHandler ParseContext *pc, JSOp op = JSOP_NOP) { return ParseNode::newBinaryOrAppend(kind, op, left, right, this, pc, foldConstants); } - void setBinaryRHS(ParseNode *pn, ParseNode *rhs) { - JS_ASSERT(pn->isArity(PN_BINARY)); - pn->pn_right = rhs; - pn->pn_pos.end = rhs->pn_pos.end; - } ParseNode *newTernary(ParseNodeKind kind, ParseNode *first, ParseNode *second, ParseNode *third, @@ -178,12 +173,18 @@ class FullParseHandler return new_(label, stmt, begin); } + ParseNode *newCaseOrDefault(uint32_t begin, ParseNode *expr, ParseNode *body) { + TokenPos pos = TokenPos::make(begin, body->pn_pos.end); + return new_(expr ? PNK_CASE : PNK_DEFAULT, JSOP_NOP, pos, expr, body); + } + ParseNode *newBreak(PropertyName *label, uint32_t begin, uint32_t end) { return new_(label, begin, end); } ParseNode *newContinue(PropertyName *label, uint32_t begin, uint32_t end) { return new_(label, begin, end); } + ParseNode *newDebuggerStatement(const TokenPos &pos) { return new_(pos); } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index e7f4585f93b5..fd717fea7677 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3525,7 +3525,10 @@ Parser::switchStatement() bool seenDefault = false; TokenKind tt; while ((tt = tokenStream.getToken()) != TOK_RC) { - Node casepn; + uint32_t caseBegin = tokenStream.currentToken().pos.begin; + + ParseNodeKind caseKind; + Node caseExpr; switch (tt) { case TOK_DEFAULT: if (seenDefault) { @@ -3533,21 +3536,16 @@ Parser::switchStatement() return null(); } seenDefault = true; - casepn = handler.newBinary(PNK_DEFAULT); - if (!casepn) - return null(); + caseKind = PNK_DEFAULT; + caseExpr = null(); break; case TOK_CASE: - { - Node left = expr(); - if (!left) - return null(); - casepn = handler.newBinary(PNK_CASE, left); - if (!casepn) + caseKind = PNK_CASE; + caseExpr = expr(); + if (!caseExpr) return null(); break; - } case TOK_ERROR: return null(); @@ -3557,8 +3555,6 @@ Parser::switchStatement() return null(); } - handler.addList(caseList, casepn); - MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE); Node body = handler.newList(PNK_STATEMENTLIST); @@ -3576,7 +3572,10 @@ Parser::switchStatement() handler.addList(body, stmt); } - handler.setBinaryRHS(casepn, body); + Node casepn = handler.newCaseOrDefault(caseBegin, caseExpr, body); + if (!casepn) + return null(); + handler.addList(caseList, casepn); } /* diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 9dd7da639a86..7a237c0196e8 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -90,7 +90,6 @@ class SyntaxParseHandler ParseContext *pc, JSOp op = JSOP_NOP) { return NodeGeneric; } - void setBinaryRHS(Node pn, Node rhs) {} Node newTernary(ParseNodeKind kind, Node first, Node second, Node third, JSOp op = JSOP_NOP) { return NodeGeneric; @@ -99,6 +98,9 @@ class SyntaxParseHandler Node newLabeledStatement(PropertyName *label, Node stmt, uint32_t begin) { return NodeGeneric; } + Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { + return NodeGeneric; + } Node newBreak(PropertyName *label, uint32_t begin, uint32_t end) { return NodeGeneric; } From e232f66483e8d63c3b35c5cf1bbbb22c208da0c3 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:40 -0500 Subject: [PATCH 418/615] Bug 872735, part 5 - Remove newNullary from the ParseHandler protocol. It is only used for array holes; replace it with a newElision method. Add PNK_ELISION to distinguish elisions from sequence expressions (which use PNK_COMMA). r=Waldo. --- js/src/frontend/BytecodeEmitter.cpp | 12 ++++++------ js/src/frontend/FullParseHandler.h | 12 ++++++++---- js/src/frontend/ParseNode.cpp | 2 +- js/src/frontend/ParseNode.h | 11 +++++------ js/src/frontend/Parser.cpp | 6 ++---- js/src/frontend/SyntaxParseHandler.h | 2 +- js/src/jsreflect.cpp | 7 ++----- 7 files changed, 25 insertions(+), 27 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 8c019a8a7a47..8d6fbb7be16b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -2688,7 +2688,7 @@ EmitDestructuringDecls(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, Parse if (pn->isKind(PNK_ARRAY)) { for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) { - if (pn2->isKind(PNK_COMMA)) + if (pn2->isKind(PNK_ELISION)) continue; emitter = (pn2->isKind(PNK_NAME)) ? EmitDestructuringDecl @@ -2908,8 +2908,8 @@ EmitDestructuringOpsHelper(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JS_ASSERT(bce->stackDepth >= stackDepth + 1); } - /* Nullary comma node makes a hole in the array destructurer. */ - if (pn3->isKind(PNK_COMMA) && pn3->isArity(PN_NULLARY)) { + /* Elision node makes a hole in the array destructurer. */ + if (pn3->isKind(PNK_ELISION)) { JS_ASSERT(pn->isKind(PNK_ARRAY)); JS_ASSERT(pn2 == pn3); if (Emit1(cx, bce, JSOP_POP) < 0) @@ -2984,7 +2984,7 @@ EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, } /* MaybeEmitGroupAssignment won't call us if rhs is holey. */ - JS_ASSERT(!(pn->isKind(PNK_COMMA) && pn->isArity(PN_NULLARY))); + JS_ASSERT(!pn->isKind(PNK_ELISION)); if (!EmitTree(cx, bce, pn)) return false; ++limit; @@ -3001,7 +3001,7 @@ EmitGroupAssignment(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, if (!EmitUnaliasedVarOp(cx, JSOP_GETLOCAL, slot, bce)) return false; - if (pn->isKind(PNK_COMMA) && pn->isArity(PN_NULLARY)) { + if (pn->isKind(PNK_ELISION)) { if (Emit1(cx, bce, JSOP_POP) < 0) return false; } else { @@ -5542,7 +5542,7 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) if (nspread && !EmitNumberOp(cx, 0, bce)) return false; for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) { - if (pn2->isKind(PNK_COMMA) && pn2->isArity(PN_NULLARY)) { + if (pn2->isKind(PNK_ELISION)) { if (Emit1(cx, bce, JSOP_HOLE) < 0) return false; } else { diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h index e44243a87587..d4f5c34b0e46 100644 --- a/js/src/frontend/FullParseHandler.h +++ b/js/src/frontend/FullParseHandler.h @@ -49,6 +49,10 @@ class FullParseHandler LazyScript * const lazyOuterFunction_; size_t lazyInnerFunctionIndex; + const TokenPos &pos() { + return tokenStream.currentToken().pos; + } + public: /* @@ -100,7 +104,7 @@ class FullParseHandler return dn; } ParseNode *newAtom(ParseNodeKind kind, JSAtom *atom, JSOp op = JSOP_NOP) { - ParseNode *pn = NullaryNode::create(kind, this); + ParseNode *pn = new_(kind, pos()); if (!pn) return NULL; pn->setOp(op); @@ -108,7 +112,7 @@ class FullParseHandler return pn; } ParseNode *newNumber(double value, DecimalPoint decimalPoint = NoDecimal) { - ParseNode *pn = NullaryNode::create(PNK_NUMBER, this); + ParseNode *pn = new_(PNK_NUMBER, pos()); if (!pn) return NULL; pn->initNumber(value, decimalPoint); @@ -130,8 +134,8 @@ class FullParseHandler return new_(cond, thenExpr, elseExpr); } - ParseNode *newNullary(ParseNodeKind kind) { - return NullaryNode::create(kind, this); + ParseNode *newElision() { + return new_(PNK_ELISION, pos()); } ParseNode *newUnary(ParseNodeKind kind, ParseNode *kid, JSOp op = JSOP_NOP) { diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index fe913db666d5..600d48260b56 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -530,7 +530,7 @@ Parser::cloneLeftHandSide(ParseNode *opn) pn2 = handler.new_(PNK_COLON, JSOP_INITPROP, opn2->pn_pos, tag, target); } else if (opn2->isArity(PN_NULLARY)) { - JS_ASSERT(opn2->isKind(PNK_COMMA)); + JS_ASSERT(opn2->isKind(PNK_ELISION)); pn2 = cloneParseTree(opn2); } else { pn2 = cloneLeftHandSide(opn2); diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 044074edd3f0..474f4a2a048e 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -75,6 +75,7 @@ class UpvarCookie F(DOT) \ F(ELEM) \ F(ARRAY) \ + F(ELISION) \ F(STATEMENTLIST) \ F(LABEL) \ F(OBJECT) \ @@ -359,7 +360,7 @@ enum ParseNodeKind * PNK_GENEXP list Exactly like PNK_CALL, used for the implicit call * in the desugaring of a generator-expression. * PNK_ARRAY list pn_head: list of pn_count array element exprs - * [,,] holes are represented by PNK_COMMA nodes + * [,,] holes are represented by PNK_ELISION nodes * pn_xflags: PN_ENDCOMMA if extra comma at end * PNK_OBJECT list pn_head: list of pn_count binary PNK_COLON nodes * PNK_COLON binary key-value pair in object initializer or @@ -728,11 +729,6 @@ struct ParseNode /* Return true if this node appears in a Directive Prologue. */ bool isDirectivePrologueMember() const { return pn_prologue; } -#ifdef JS_HAS_DESTRUCTURING - /* Return true if this represents a hole in an array literal. */ - bool isArrayHole() const { return isKind(PNK_COMMA) && isArity(PN_NULLARY); } -#endif - #ifdef JS_HAS_GENERATOR_EXPRS ParseNode *generatorExpr() const { JS_ASSERT(isKind(PNK_GENEXP)); @@ -822,6 +818,9 @@ struct ParseNode struct NullaryNode : public ParseNode { + NullaryNode(ParseNodeKind kind, const TokenPos &pos) + : ParseNode(kind, JSOP_NOP, PN_NULLARY, pos) {} + static inline NullaryNode *create(ParseNodeKind kind, FullParseHandler *handler) { return (NullaryNode *) ParseNode::create(kind, PN_NULLARY, handler); } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index fd717fea7677..b18269558ddd 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3088,8 +3088,7 @@ Parser::checkDestructuring(BindData *data, if (left->isKind(PNK_ARRAY)) { for (ParseNode *pn = left->pn_head; pn; pn = pn->pn_next) { - /* Nullary comma is an elision; binary comma is an expression.*/ - if (!pn->isArrayHole()) { + if (!pn->isKind(PNK_ELISION)) { if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) { ok = checkDestructuring(data, pn, false); } else { @@ -6618,9 +6617,8 @@ Parser::primaryExpr(TokenKind tt) break; if (tt == TOK_COMMA) { - /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */ tokenStream.matchToken(TOK_COMMA); - pn2 = handler.newNullary(PNK_COMMA); + pn2 = handler.newElision(); if (!pn2) return null(); handler.setListFlag(pn, PNX_SPECIALARRAYINIT | PNX_NONCONST); diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h index 7a237c0196e8..3a6d17d5aff4 100644 --- a/js/src/frontend/SyntaxParseHandler.h +++ b/js/src/frontend/SyntaxParseHandler.h @@ -71,7 +71,7 @@ class SyntaxParseHandler Node newNullLiteral(const TokenPos &pos) { return NodeGeneric; } Node newConditional(Node cond, Node thenExpr, Node elseExpr) { return NodeGeneric; } - Node newNullary(ParseNodeKind kind) { return NodeGeneric; } + Node newElision() { return NodeGeneric; } Node newUnary(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) { if (kind == PNK_SEMI && kid == NodeString) diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index 4798f73835ea..43fed35235ff 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -2516,7 +2516,7 @@ ASTSerializer::expression(ParseNode *pn, MutableHandleValue dst) for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { JS_ASSERT(pn->pn_pos.encloses(next->pn_pos)); - if (next->isKind(PNK_COMMA) && next->pn_count == 0) { + if (next->isKind(PNK_ELISION)) { elts.infallibleAppend(NullValue()); } else { RootedValue expr(cx); @@ -2696,10 +2696,7 @@ ASTSerializer::arrayPattern(ParseNode *pn, VarDeclKind *pkind, MutableHandleValu return false; for (ParseNode *next = pn->pn_head; next; next = next->pn_next) { - /* Comma expressions can't occur inside patterns, so no need to test pn_count. */ - JS_ASSERT_IF(next->isKind(PNK_COMMA), next->pn_count == 0); - - if (next->isKind(PNK_COMMA)) { + if (next->isKind(PNK_ELISION)) { elts.infallibleAppend(NullValue()); } else { RootedValue patt(cx); From e1a9ad5b6221204a756d6dc61d07bfab8ab060f8 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 14 Jun 2013 16:30:40 -0500 Subject: [PATCH 419/615] Bug 881056 - Remove unused hasFunctionStmt parameter from some Parser methods. r=bhackett. --- js/src/frontend/Parser.cpp | 25 +++++++------------------ js/src/frontend/Parser.h | 4 ++-- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index b18269558ddd..fca697549035 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2486,7 +2486,7 @@ Parser::maybeParseDirective(Node pn, bool *cont) template <> void -Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool *hasFunctionStmt) +Parser::addStatementToList(ParseNode *pn, ParseNode *kid) { JS_ASSERT(pn->isKind(PNK_STATEMENTLIST)); @@ -2495,21 +2495,12 @@ Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool * PNX_FUNCDEFS notifies the emitter that the block contains body- * level function definitions that should be processed before the * rest of nodes. - * - * |hasFunctionStmt| is for the TOK_LC case in Statement. It - * is relevant only for function definitions not at body-level, - * which we call function statements. */ if (pc->atBodyLevel()) { pn->pn_xflags |= PNX_FUNCDEFS; } else { - /* - * General deoptimization was done in functionDef, here we just - * need to tell TOK_LC in Parser::statement to add braces. - */ + /* General deoptimization was done in functionDef. */ JS_ASSERT_IF(pc->sc->isFunctionBox(), pc->sc->asFunctionBox()->hasExtensibleScope()); - if (hasFunctionStmt) - *hasFunctionStmt = true; } } @@ -2519,7 +2510,7 @@ Parser::addStatementToList(ParseNode *pn, ParseNode *kid, bool template <> void -Parser::addStatementToList(Node pn, Node kid, bool *hasFunctionStmt) +Parser::addStatementToList(Node pn, Node kid) { } @@ -2530,11 +2521,9 @@ Parser::addStatementToList(Node pn, Node kid, bool *hasFunct */ template typename ParseHandler::Node -Parser::statements(bool *hasFunctionStmt) +Parser::statements() { JS_CHECK_RECURSION(context, return null()); - if (hasFunctionStmt) - *hasFunctionStmt = false; Node pn = handler.newList(PNK_STATEMENTLIST); if (!pn) @@ -2567,7 +2556,7 @@ Parser::statements(bool *hasFunctionStmt) return null(); } - addStatementToList(pn, next, hasFunctionStmt); + addStatementToList(pn, next); } /* @@ -4794,8 +4783,8 @@ Parser::statement() StmtInfoPC stmtInfo(context); if (!PushBlocklikeStatement(&stmtInfo, STMT_BLOCK, pc)) return null(); - bool hasFunctionStmt; - pn = statements(&hasFunctionStmt); + + pn = statements(); if (!pn) return null(); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index da2372de7ce2..4f7f361984c2 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -421,7 +421,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter Node moduleDecl(); Node functionStmt(); Node functionExpr(); - Node statements(bool *hasFunctionStmt = NULL); + Node statements(); Node switchStatement(); Node forStatement(); @@ -483,7 +483,7 @@ struct Parser : private AutoGCRooter, public StrictModeGetter bool setAssignmentLhsOps(Node pn, JSOp op); bool matchInOrOf(bool *isForOfp); - void addStatementToList(Node pn, Node kid, bool *hasFunctionStmt); + void addStatementToList(Node pn, Node kid); bool checkFunctionArguments(); bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom); bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind, From 4639ab1d14cd83b5eedf9c410727c0102b0eb16b Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Fri, 14 Jun 2013 14:38:29 -0700 Subject: [PATCH 420/615] Backout 9080f6701733 (bug 852411) for hitting weird xpcshell test harness behavior in multiple local builds --- .../browser_datareporting_notification.js | 1 + .../browser_urlbar_search_healthreport.js | 4 +- .../search/test/browser_healthreport.js | 2 +- services/common/bagheeraclient.js | 2 +- services/common/utils.js | 2 +- services/datareporting/policy.jsm | 17 ++-- .../tests/xpcshell/test_policy.js | 78 ++++++++++++------- .../tests/xpcshell/test_session_recorder.js | 2 +- services/healthreport/healthreporter.jsm | 2 +- .../healthreport/modules-testing/utils.jsm | 2 +- services/healthreport/profile.jsm | 2 +- services/healthreport/providers.jsm | 2 +- .../tests/xpcshell/test_healthreporter.js | 2 +- .../tests/xpcshell/test_profile.js | 2 +- .../tests/xpcshell/test_provider_sessions.js | 2 +- services/metrics/dataprovider.jsm | 2 +- services/metrics/modules-testing/mocks.jsm | 2 +- services/metrics/providermanager.jsm | 2 +- services/metrics/storage.jsm | 2 +- .../xpcshell/test_metrics_provider_manager.js | 2 +- .../tests/xpcshell/test_metrics_storage.js | 2 +- .../sync/tests/unit/test_bookmark_engine.js | 2 +- services/sync/tests/unit/test_corrupt_keys.js | 2 +- 23 files changed, 79 insertions(+), 59 deletions(-) diff --git a/browser/base/content/test/browser_datareporting_notification.js b/browser/base/content/test/browser_datareporting_notification.js index b892bd00922f..51c3bdeb7535 100644 --- a/browser/base/content/test/browser_datareporting_notification.js +++ b/browser/base/content/test/browser_datareporting_notification.js @@ -23,6 +23,7 @@ function sendNotifyRequest(name) { service.healthReporter.onInit().then(function onInit() { is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy."); + is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for notification response."); }); return policy; diff --git a/browser/base/content/test/browser_urlbar_search_healthreport.js b/browser/base/content/test/browser_urlbar_search_healthreport.js index 4315a98649ed..215aa63141bc 100644 --- a/browser/base/content/test/browser_urlbar_search_healthreport.js +++ b/browser/base/content/test/browser_urlbar_search_healthreport.js @@ -45,7 +45,7 @@ function test() { gURLBar.value = "firefox health report"; gURLBar.handleCommand(); - executeSoon(() => executeSoon(() => { + executeSoon(function afterSearch() { gBrowser.removeTab(tab); m.getValues().then(function onData(data) { @@ -58,7 +58,7 @@ function test() { is(newCount, oldCount + 1, "Exactly one search has been recorded."); finish(); }); - })); + }); }); }); } diff --git a/browser/components/search/test/browser_healthreport.js b/browser/components/search/test/browser_healthreport.js index 58dc9d881ab5..d70191560df0 100644 --- a/browser/components/search/test/browser_healthreport.js +++ b/browser/components/search/test/browser_healthreport.js @@ -66,7 +66,7 @@ function test() { } EventUtils.synthesizeKey("VK_RETURN", {}); - executeSoon(() => executeSoon(afterSearch)); + executeSoon(afterSearch); }); }); } diff --git a/services/common/bagheeraclient.js b/services/common/bagheeraclient.js index ef889915268a..67295de9875a 100644 --- a/services/common/bagheeraclient.js +++ b/services/common/bagheeraclient.js @@ -22,7 +22,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/rest.js"); diff --git a/services/common/utils.js b/services/common/utils.js index fb441cd65a72..e07c31731c89 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -6,7 +6,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; this.EXPORTED_SYMBOLS = ["CommonUtils"]; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm") diff --git a/services/datareporting/policy.jsm b/services/datareporting/policy.jsm index ac93644277b2..32e99fe282f9 100644 --- a/services/datareporting/policy.jsm +++ b/services/datareporting/policy.jsm @@ -26,7 +26,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); @@ -69,12 +69,12 @@ const OLDEST_ALLOWED_YEAR = 2012; * * @param policy * (DataReportingPolicy) The policy instance this request came from. - * @param deferred + * @param promise * (deferred) The promise that will be fulfilled when display occurs. */ -function NotifyPolicyRequest(policy, deferred) { +function NotifyPolicyRequest(policy, promise) { this.policy = policy; - this.deferred = deferred; + this.promise = promise; } NotifyPolicyRequest.prototype = { /** @@ -84,8 +84,7 @@ NotifyPolicyRequest.prototype = { * acceptance of the data policy. */ onUserNotifyComplete: function onUserNotified() { - this.deferred.resolve(); - return this.deferred.promise; + this.promise.resolve(); }, /** @@ -95,7 +94,7 @@ NotifyPolicyRequest.prototype = { * (Error) Explains what went wrong. */ onUserNotifyFailed: function onUserNotifyFailed(error) { - this.deferred.reject(error); + this.promise.reject(error); }, /** @@ -159,7 +158,6 @@ DataSubmissionRequest.prototype = { onNoDataAvailable: function onNoDataAvailable() { this.state = this.NO_DATA_AVAILABLE; this.promise.resolve(this); - return this.promise.promise; }, /** @@ -175,7 +173,6 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_SUCCESS; this.submissionDate = date; this.promise.resolve(this); - return this.promise.promise; }, /** @@ -191,7 +188,6 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_SOFT; this.reason = reason; this.promise.resolve(this); - return this.promise.promise; }, /** @@ -208,7 +204,6 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_HARD; this.reason = reason; this.promise.resolve(this); - return this.promise.promise; }, }; diff --git a/services/datareporting/tests/xpcshell/test_policy.js b/services/datareporting/tests/xpcshell/test_policy.js index a36add0ae80f..4cc9ad607332 100644 --- a/services/datareporting/tests/xpcshell/test_policy.js +++ b/services/datareporting/tests/xpcshell/test_policy.js @@ -138,7 +138,7 @@ add_test(function test_notify_state_prefs() { run_next_test(); }); -add_task(function test_initial_submission_notification() { +add_test(function test_initial_submission_notification() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("initial_submission_notification"); do_check_eq(listener.notifyUserCount, 0); @@ -160,12 +160,14 @@ add_task(function test_initial_submission_notification() { policy.SUBMISSION_NOTIFY_INTERVAL_MSEC)); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - yield listener.lastNotifyRequest.onUserNotifyComplete(); + listener.lastNotifyRequest.onUserNotifyComplete(); do_check_true(policy._dataSubmissionPolicyNotifiedDate instanceof Date); do_check_true(policy.dataSubmissionPolicyNotifiedDate.getTime() > 0); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), policy._dataSubmissionPolicyNotifiedDate.getTime()); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); + + run_next_test(); }); add_test(function test_bypass_acceptance() { @@ -181,7 +183,7 @@ add_test(function test_bypass_acceptance() { run_next_test(); }); -add_task(function test_notification_implicit_acceptance() { +add_test(function test_notification_implicit_acceptance() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_implicit_acceptance"); let now = new Date(policy.nextDataSubmissionDate.getTime() - @@ -189,7 +191,7 @@ add_task(function test_notification_implicit_acceptance() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - yield listener.lastNotifyRequest.onUserNotifyComplete(); + listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.dataSubmissionPolicyResponseType, "none-recorded"); do_check_true(5000 < policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC); @@ -206,9 +208,11 @@ add_task(function test_notification_implicit_acceptance() { do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), policy.now().getTime()); do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-implicit-time-elapsed"); + + run_next_test(); }); -add_task(function test_notification_rejected() { +add_test(function test_notification_rejected() { // User notification failed. We should not record it as being presented. let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_failed"); @@ -217,20 +221,22 @@ add_task(function test_notification_rejected() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - yield listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); + listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); do_check_null(policy._dataSubmissionPolicyNotifiedDate); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED); + + run_next_test(); }); -add_task(function test_notification_accepted() { +add_test(function test_notification_accepted() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_accepted"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - yield listener.lastNotifyRequest.onUserNotifyComplete(); + listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserNotifyComplete(); @@ -239,16 +245,18 @@ add_task(function test_notification_accepted() { do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-foo-bar"); do_check_true(policy.dataSubmissionPolicyAccepted); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), now.getTime()); + + run_next_test(); }); -add_task(function test_notification_rejected() { +add_test(function test_notification_rejected() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_rejected"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - yield listener.lastNotifyRequest.onUserNotifyComplete(); + listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserReject(); @@ -260,6 +268,8 @@ add_task(function test_notification_rejected() { defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime() + 10000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 0); + + run_next_test(); }); add_test(function test_submission_kill_switch() { @@ -321,7 +331,7 @@ add_test(function test_data_submission_no_data() { run_next_test(); }); -add_task(function test_data_submission_submit_failure_hard() { +add_test(function test_data_submission_submit_failure_hard() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_submit_failure_hard"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -332,7 +342,7 @@ add_task(function test_data_submission_submit_failure_hard() { policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); - yield listener.lastDataRequest.onSubmissionFailureHard(); + listener.lastDataRequest.onSubmissionFailureHard(); do_check_eq(listener.lastDataRequest.state, listener.lastDataRequest.SUBMISSION_FAILURE_HARD); @@ -342,9 +352,11 @@ add_task(function test_data_submission_submit_failure_hard() { defineNow(policy, new Date(now.getTime() + 10)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); + + run_next_test(); }); -add_task(function test_data_submission_submit_try_again() { +add_test(function test_data_submission_submit_try_again() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_failure_soft"); policy.recordUserAcceptance(); @@ -352,12 +364,14 @@ add_task(function test_data_submission_submit_try_again() { let now = new Date(policy.nextDataSubmissionDate.getTime()); defineNow(policy, now); policy.checkStateAndTrigger(); - yield listener.lastDataRequest.onSubmissionFailureSoft(); + listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.nextDataSubmissionDate.getTime(), nextDataSubmissionDate.getTime() + 15 * 60 * 1000); + + run_next_test(); }); -add_task(function test_submission_daily_scheduling() { +add_test(function test_submission_daily_scheduling() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_daily_scheduling"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -373,7 +387,7 @@ add_task(function test_submission_daily_scheduling() { let finishedDate = new Date(now.getTime() + 250); defineNow(policy, new Date(finishedDate.getTime() + 50)); - yield listener.lastDataRequest.onSubmissionSuccess(finishedDate); + listener.lastDataRequest.onSubmissionSuccess(finishedDate); do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), finishedDate.getTime()); // Next scheduled submission should be exactly 1 day after the reported @@ -390,9 +404,11 @@ add_task(function test_submission_daily_scheduling() { defineNow(policy, nextScheduled); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 2); - yield listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); + listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(nextScheduled.getTime() + 24 * 60 * 60 * 1000 + 200).getTime()); + + run_next_test(); }); add_test(function test_submission_far_future_scheduling() { @@ -419,7 +435,7 @@ add_test(function test_submission_far_future_scheduling() { run_next_test(); }); -add_task(function test_submission_backoff() { +add_test(function test_submission_backoff() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_backoff"); do_check_eq(policy.FAILURE_BACKOFF_INTERVALS.length, 2); @@ -437,7 +453,7 @@ add_task(function test_submission_backoff() { defineNow(policy, now); // On first soft failure we should back off by scheduled interval. - yield listener.lastDataRequest.onSubmissionFailureSoft(); + listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 1); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[0]).getTime()); @@ -459,7 +475,7 @@ add_task(function test_submission_backoff() { defineNow(policy, now); // On second failure we should back off by more. - yield listener.lastDataRequest.onSubmissionFailureSoft(); + listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 2); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[1]).getTime()); @@ -473,10 +489,12 @@ add_task(function test_submission_backoff() { defineNow(policy, now); // On 3rd failure we should back off by a whole day. - yield listener.lastDataRequest.onSubmissionFailureSoft(); + listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 0); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + 24 * 60 * 60 * 1000).getTime()); + + run_next_test(); }); // Ensure that only one submission request can be active at a time. @@ -503,7 +521,7 @@ add_test(function test_submission_expiring() { run_next_test(); }); -add_task(function test_delete_remote_data() { +add_test(function test_delete_remote_data() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data"); do_check_false(policy.pendingDeleteRemoteData); @@ -522,8 +540,10 @@ add_task(function test_delete_remote_data() { do_check_true(listener.lastRemoteDeleteRequest.isDelete); defineNow(policy, policy._futureDate(1000)); - yield listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); + listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); do_check_false(policy.pendingDeleteRemoteData); + + run_next_test(); }); // Ensure that deletion requests take priority over regular data submission. @@ -581,7 +601,7 @@ add_test(function test_delete_remote_data_backoff() { // If we request delete while an upload is in progress, delete should be // scheduled immediately after upload. -add_task(function test_delete_remote_data_in_progress_upload() { +add_test(function test_delete_remote_data_in_progress_upload() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_in_progress_upload"); let now = new Date(); @@ -601,12 +621,14 @@ add_task(function test_delete_remote_data_in_progress_upload() { // Now wait a little bit and finish the request. defineNow(policy, policy._futureDate(10 * 1000)); - yield listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); + listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); defineNow(policy, policy._futureDate(5000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); do_check_eq(listener.requestRemoteDeleteCount, 1); + + run_next_test(); }); add_test(function test_polling() { @@ -725,7 +747,7 @@ add_test(function test_polling_implicit_acceptance() { policy.startPolling(); }); -add_task(function test_record_health_report_upload_enabled() { +add_test(function test_record_health_report_upload_enabled() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("record_health_report_upload_enabled"); // Preconditions. @@ -741,13 +763,15 @@ add_task(function test_record_health_report_upload_enabled() { do_check_eq(listener.requestRemoteDeleteCount, 1); // Fulfilling it should make it go away. - yield listener.lastRemoteDeleteRequest.onNoDataAvailable(); + listener.lastRemoteDeleteRequest.onNoDataAvailable(); do_check_false(policy.pendingDeleteRemoteData); // User intent to enable should get us back to default state. policy.recordHealthReportUploadEnabled(true, "testing 1 2 3"); do_check_false(policy.pendingDeleteRemoteData); do_check_true(policy.healthReportUploadEnabled); + + run_next_test(); }); add_test(function test_pref_change_initiates_deletion() { diff --git a/services/datareporting/tests/xpcshell/test_session_recorder.js b/services/datareporting/tests/xpcshell/test_session_recorder.js index 1e8b04233d66..0ea3919a6cbc 100644 --- a/services/datareporting/tests/xpcshell/test_session_recorder.js +++ b/services/datareporting/tests/xpcshell/test_session_recorder.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/services/datareporting/sessions.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/healthreport/healthreporter.jsm b/services/healthreport/healthreporter.jsm index 3fdc91250d35..b776f881bda0 100644 --- a/services/healthreport/healthreporter.jsm +++ b/services/healthreport/healthreporter.jsm @@ -20,7 +20,7 @@ Cu.import("resource://services-common/bagheeraclient.js"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/modules-testing/utils.jsm b/services/healthreport/modules-testing/utils.jsm index bf0a4cc713f2..f1f90c965f08 100644 --- a/services/healthreport/modules-testing/utils.jsm +++ b/services/healthreport/modules-testing/utils.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); diff --git a/services/healthreport/profile.jsm b/services/healthreport/profile.jsm index e3aa031d2978..cd4457cec9ea 100644 --- a/services/healthreport/profile.jsm +++ b/services/healthreport/profile.jsm @@ -22,7 +22,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); const DEFAULT_PROFILE_MEASUREMENT_NAME = "age"; const REQUIRED_UINT32_TYPE = {type: "TYPE_UINT32"}; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/osfile.jsm") Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/healthreport/providers.jsm b/services/healthreport/providers.jsm index 85a50c8f29cd..b65d0d6191a1 100644 --- a/services/healthreport/providers.jsm +++ b/services/healthreport/providers.jsm @@ -34,7 +34,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_healthreporter.js b/services/healthreport/tests/xpcshell/test_healthreporter.js index 022521216bc1..265e066e64de 100644 --- a/services/healthreport/tests/xpcshell/test_healthreporter.js +++ b/services/healthreport/tests/xpcshell/test_healthreporter.js @@ -7,7 +7,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://services-common/observers.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_profile.js b/services/healthreport/tests/xpcshell/test_profile.js index ef4a51b6f04e..d17a53832fb3 100644 --- a/services/healthreport/tests/xpcshell/test_profile.js +++ b/services/healthreport/tests/xpcshell/test_profile.js @@ -12,7 +12,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; let profile_creation_lower = Date.now() - MILLISECONDS_PER_DAY; do_get_profile(); -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/services/healthreport/profile.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_provider_sessions.js b/services/healthreport/tests/xpcshell/test_provider_sessions.js index 59e190d0eb78..07f90ce8f495 100644 --- a/services/healthreport/tests/xpcshell/test_provider_sessions.js +++ b/services/healthreport/tests/xpcshell/test_provider_sessions.js @@ -6,7 +6,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/services-common/utils.js"); diff --git a/services/metrics/dataprovider.jsm b/services/metrics/dataprovider.jsm index d6d2ca90c597..0be60e46c105 100644 --- a/services/metrics/dataprovider.jsm +++ b/services/metrics/dataprovider.jsm @@ -17,7 +17,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/modules-testing/mocks.jsm b/services/metrics/modules-testing/mocks.jsm index 032f167a9620..ba4bf4142beb 100644 --- a/services/metrics/modules-testing/mocks.jsm +++ b/services/metrics/modules-testing/mocks.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/metrics/providermanager.jsm b/services/metrics/providermanager.jsm index 631df1f568cf..44d10d8f1693 100644 --- a/services/metrics/providermanager.jsm +++ b/services/metrics/providermanager.jsm @@ -12,7 +12,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm"); #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); diff --git a/services/metrics/storage.jsm b/services/metrics/storage.jsm index 241518f3c195..60b84ad60948 100644 --- a/services/metrics/storage.jsm +++ b/services/metrics/storage.jsm @@ -19,7 +19,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Sqlite.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js index 232753e201ec..4137a06f2782 100644 --- a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js +++ b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js @@ -5,7 +5,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://testing-common/services/metrics/mocks.jsm"); diff --git a/services/metrics/tests/xpcshell/test_metrics_storage.js b/services/metrics/tests/xpcshell/test_metrics_storage.js index 42763dd32fa4..6c59fb127b4c 100644 --- a/services/metrics/tests/xpcshell/test_metrics_storage.js +++ b/services/metrics/tests/xpcshell/test_metrics_storage.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index fda9260e0a43..aa486c3e0471 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -10,7 +10,7 @@ Cu.import("resource://services-sync/engines/bookmarks.js"); Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); Service.engineManager.register(BookmarksEngine); var syncTesting = new SyncTestingInfrastructure(); diff --git a/services/sync/tests/unit/test_corrupt_keys.js b/services/sync/tests/unit/test_corrupt_keys.js index 9ee0f34b3f30..ecbad7546201 100644 --- a/services/sync/tests/unit/test_corrupt_keys.js +++ b/services/sync/tests/unit/test_corrupt_keys.js @@ -11,7 +11,7 @@ Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/status.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); add_task(function test_locally_changed_keys() { let passphrase = "abcdeabcdeabcdeabcdeabcdea"; From 773620d4d84963ba86b4334033b945adf401b65f Mon Sep 17 00:00:00 2001 From: Stefan Mirea Date: Thu, 13 Jun 2013 18:36:21 -0700 Subject: [PATCH 421/615] Bug 852411 - Migrating from promise.js to Promise.jsm; r=gps --- .../browser_datareporting_notification.js | 1 - .../browser_urlbar_search_healthreport.js | 4 +- .../search/test/browser_healthreport.js | 2 +- services/common/bagheeraclient.js | 2 +- services/common/utils.js | 2 +- services/datareporting/policy.jsm | 17 ++-- .../tests/xpcshell/test_policy.js | 78 +++++++------------ .../tests/xpcshell/test_session_recorder.js | 2 +- services/healthreport/healthreporter.jsm | 2 +- .../healthreport/modules-testing/utils.jsm | 2 +- services/healthreport/profile.jsm | 2 +- services/healthreport/providers.jsm | 2 +- .../tests/xpcshell/test_healthreporter.js | 9 ++- .../tests/xpcshell/test_profile.js | 2 +- .../tests/xpcshell/test_provider_crashes.js | 7 +- .../tests/xpcshell/test_provider_sessions.js | 2 +- services/metrics/dataprovider.jsm | 2 +- services/metrics/modules-testing/mocks.jsm | 2 +- services/metrics/providermanager.jsm | 2 +- services/metrics/storage.jsm | 2 +- .../xpcshell/test_metrics_provider_manager.js | 2 +- .../tests/xpcshell/test_metrics_storage.js | 2 +- .../sync/tests/unit/test_bookmark_engine.js | 2 +- services/sync/tests/unit/test_corrupt_keys.js | 2 +- 24 files changed, 71 insertions(+), 81 deletions(-) diff --git a/browser/base/content/test/browser_datareporting_notification.js b/browser/base/content/test/browser_datareporting_notification.js index 51c3bdeb7535..b892bd00922f 100644 --- a/browser/base/content/test/browser_datareporting_notification.js +++ b/browser/base/content/test/browser_datareporting_notification.js @@ -23,7 +23,6 @@ function sendNotifyRequest(name) { service.healthReporter.onInit().then(function onInit() { is(policy.ensureNotifyResponse(new Date()), false, "User has not responded to policy."); - is(policy.notifyState, policy.STATE_NOTIFY_WAIT, "Policy is waiting for notification response."); }); return policy; diff --git a/browser/base/content/test/browser_urlbar_search_healthreport.js b/browser/base/content/test/browser_urlbar_search_healthreport.js index 215aa63141bc..4315a98649ed 100644 --- a/browser/base/content/test/browser_urlbar_search_healthreport.js +++ b/browser/base/content/test/browser_urlbar_search_healthreport.js @@ -45,7 +45,7 @@ function test() { gURLBar.value = "firefox health report"; gURLBar.handleCommand(); - executeSoon(function afterSearch() { + executeSoon(() => executeSoon(() => { gBrowser.removeTab(tab); m.getValues().then(function onData(data) { @@ -58,7 +58,7 @@ function test() { is(newCount, oldCount + 1, "Exactly one search has been recorded."); finish(); }); - }); + })); }); }); } diff --git a/browser/components/search/test/browser_healthreport.js b/browser/components/search/test/browser_healthreport.js index d70191560df0..58dc9d881ab5 100644 --- a/browser/components/search/test/browser_healthreport.js +++ b/browser/components/search/test/browser_healthreport.js @@ -66,7 +66,7 @@ function test() { } EventUtils.synthesizeKey("VK_RETURN", {}); - executeSoon(afterSearch); + executeSoon(() => executeSoon(afterSearch)); }); }); } diff --git a/services/common/bagheeraclient.js b/services/common/bagheeraclient.js index 67295de9875a..ef889915268a 100644 --- a/services/common/bagheeraclient.js +++ b/services/common/bagheeraclient.js @@ -22,7 +22,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/rest.js"); diff --git a/services/common/utils.js b/services/common/utils.js index e07c31731c89..fb441cd65a72 100644 --- a/services/common/utils.js +++ b/services/common/utils.js @@ -6,7 +6,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; this.EXPORTED_SYMBOLS = ["CommonUtils"]; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm") diff --git a/services/datareporting/policy.jsm b/services/datareporting/policy.jsm index 32e99fe282f9..ac93644277b2 100644 --- a/services/datareporting/policy.jsm +++ b/services/datareporting/policy.jsm @@ -26,7 +26,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); @@ -69,12 +69,12 @@ const OLDEST_ALLOWED_YEAR = 2012; * * @param policy * (DataReportingPolicy) The policy instance this request came from. - * @param promise + * @param deferred * (deferred) The promise that will be fulfilled when display occurs. */ -function NotifyPolicyRequest(policy, promise) { +function NotifyPolicyRequest(policy, deferred) { this.policy = policy; - this.promise = promise; + this.deferred = deferred; } NotifyPolicyRequest.prototype = { /** @@ -84,7 +84,8 @@ NotifyPolicyRequest.prototype = { * acceptance of the data policy. */ onUserNotifyComplete: function onUserNotified() { - this.promise.resolve(); + this.deferred.resolve(); + return this.deferred.promise; }, /** @@ -94,7 +95,7 @@ NotifyPolicyRequest.prototype = { * (Error) Explains what went wrong. */ onUserNotifyFailed: function onUserNotifyFailed(error) { - this.promise.reject(error); + this.deferred.reject(error); }, /** @@ -158,6 +159,7 @@ DataSubmissionRequest.prototype = { onNoDataAvailable: function onNoDataAvailable() { this.state = this.NO_DATA_AVAILABLE; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -173,6 +175,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_SUCCESS; this.submissionDate = date; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -188,6 +191,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_SOFT; this.reason = reason; this.promise.resolve(this); + return this.promise.promise; }, /** @@ -204,6 +208,7 @@ DataSubmissionRequest.prototype = { this.state = this.SUBMISSION_FAILURE_HARD; this.reason = reason; this.promise.resolve(this); + return this.promise.promise; }, }; diff --git a/services/datareporting/tests/xpcshell/test_policy.js b/services/datareporting/tests/xpcshell/test_policy.js index 4cc9ad607332..a36add0ae80f 100644 --- a/services/datareporting/tests/xpcshell/test_policy.js +++ b/services/datareporting/tests/xpcshell/test_policy.js @@ -138,7 +138,7 @@ add_test(function test_notify_state_prefs() { run_next_test(); }); -add_test(function test_initial_submission_notification() { +add_task(function test_initial_submission_notification() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("initial_submission_notification"); do_check_eq(listener.notifyUserCount, 0); @@ -160,14 +160,12 @@ add_test(function test_initial_submission_notification() { policy.SUBMISSION_NOTIFY_INTERVAL_MSEC)); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_true(policy._dataSubmissionPolicyNotifiedDate instanceof Date); do_check_true(policy.dataSubmissionPolicyNotifiedDate.getTime() > 0); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), policy._dataSubmissionPolicyNotifiedDate.getTime()); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); - - run_next_test(); }); add_test(function test_bypass_acceptance() { @@ -183,7 +181,7 @@ add_test(function test_bypass_acceptance() { run_next_test(); }); -add_test(function test_notification_implicit_acceptance() { +add_task(function test_notification_implicit_acceptance() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_implicit_acceptance"); let now = new Date(policy.nextDataSubmissionDate.getTime() - @@ -191,7 +189,7 @@ add_test(function test_notification_implicit_acceptance() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.dataSubmissionPolicyResponseType, "none-recorded"); do_check_true(5000 < policy.IMPLICIT_ACCEPTANCE_INTERVAL_MSEC); @@ -208,11 +206,9 @@ add_test(function test_notification_implicit_acceptance() { do_check_eq(policy.notifyState, policy.STATE_NOTIFY_COMPLETE); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), policy.now().getTime()); do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-implicit-time-elapsed"); - - run_next_test(); }); -add_test(function test_notification_rejected() { +add_task(function test_notification_rejected() { // User notification failed. We should not record it as being presented. let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_failed"); @@ -221,22 +217,20 @@ add_test(function test_notification_rejected() { defineNow(policy, now); policy.checkStateAndTrigger(); do_check_eq(listener.notifyUserCount, 1); - listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); + yield listener.lastNotifyRequest.onUserNotifyFailed(new Error("testing failed.")); do_check_null(policy._dataSubmissionPolicyNotifiedDate); do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED); - - run_next_test(); }); -add_test(function test_notification_accepted() { +add_task(function test_notification_accepted() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_accepted"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserNotifyComplete(); @@ -245,18 +239,16 @@ add_test(function test_notification_accepted() { do_check_eq(policy.dataSubmissionPolicyResponseType, "accepted-foo-bar"); do_check_true(policy.dataSubmissionPolicyAccepted); do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), now.getTime()); - - run_next_test(); }); -add_test(function test_notification_rejected() { +add_task(function test_notification_rejected() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_rejected"); let now = new Date(policy.nextDataSubmissionDate.getTime() - policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastNotifyRequest.onUserNotifyComplete(); + yield listener.lastNotifyRequest.onUserNotifyComplete(); do_check_eq(policy.notifyState, policy.STATE_NOTIFY_WAIT); do_check_false(policy.dataSubmissionPolicyAccepted); listener.lastNotifyRequest.onUserReject(); @@ -268,8 +260,6 @@ add_test(function test_notification_rejected() { defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime() + 10000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 0); - - run_next_test(); }); add_test(function test_submission_kill_switch() { @@ -331,7 +321,7 @@ add_test(function test_data_submission_no_data() { run_next_test(); }); -add_test(function test_data_submission_submit_failure_hard() { +add_task(function test_data_submission_submit_failure_hard() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_submit_failure_hard"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -342,7 +332,7 @@ add_test(function test_data_submission_submit_failure_hard() { policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); - listener.lastDataRequest.onSubmissionFailureHard(); + yield listener.lastDataRequest.onSubmissionFailureHard(); do_check_eq(listener.lastDataRequest.state, listener.lastDataRequest.SUBMISSION_FAILURE_HARD); @@ -352,11 +342,9 @@ add_test(function test_data_submission_submit_failure_hard() { defineNow(policy, new Date(now.getTime() + 10)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); - - run_next_test(); }); -add_test(function test_data_submission_submit_try_again() { +add_task(function test_data_submission_submit_try_again() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_failure_soft"); policy.recordUserAcceptance(); @@ -364,14 +352,12 @@ add_test(function test_data_submission_submit_try_again() { let now = new Date(policy.nextDataSubmissionDate.getTime()); defineNow(policy, now); policy.checkStateAndTrigger(); - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.nextDataSubmissionDate.getTime(), nextDataSubmissionDate.getTime() + 15 * 60 * 1000); - - run_next_test(); }); -add_test(function test_submission_daily_scheduling() { +add_task(function test_submission_daily_scheduling() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_daily_scheduling"); policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000); @@ -387,7 +373,7 @@ add_test(function test_submission_daily_scheduling() { let finishedDate = new Date(now.getTime() + 250); defineNow(policy, new Date(finishedDate.getTime() + 50)); - listener.lastDataRequest.onSubmissionSuccess(finishedDate); + yield listener.lastDataRequest.onSubmissionSuccess(finishedDate); do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), finishedDate.getTime()); // Next scheduled submission should be exactly 1 day after the reported @@ -404,11 +390,9 @@ add_test(function test_submission_daily_scheduling() { defineNow(policy, nextScheduled); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 2); - listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); + yield listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200)); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(nextScheduled.getTime() + 24 * 60 * 60 * 1000 + 200).getTime()); - - run_next_test(); }); add_test(function test_submission_far_future_scheduling() { @@ -435,7 +419,7 @@ add_test(function test_submission_far_future_scheduling() { run_next_test(); }); -add_test(function test_submission_backoff() { +add_task(function test_submission_backoff() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_backoff"); do_check_eq(policy.FAILURE_BACKOFF_INTERVALS.length, 2); @@ -453,7 +437,7 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On first soft failure we should back off by scheduled interval. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 1); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[0]).getTime()); @@ -475,7 +459,7 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On second failure we should back off by more. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 2); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + policy.FAILURE_BACKOFF_INTERVALS[1]).getTime()); @@ -489,12 +473,10 @@ add_test(function test_submission_backoff() { defineNow(policy, now); // On 3rd failure we should back off by a whole day. - listener.lastDataRequest.onSubmissionFailureSoft(); + yield listener.lastDataRequest.onSubmissionFailureSoft(); do_check_eq(policy.currentDaySubmissionFailureCount, 0); do_check_eq(policy.nextDataSubmissionDate.getTime(), new Date(now.getTime() + 24 * 60 * 60 * 1000).getTime()); - - run_next_test(); }); // Ensure that only one submission request can be active at a time. @@ -521,7 +503,7 @@ add_test(function test_submission_expiring() { run_next_test(); }); -add_test(function test_delete_remote_data() { +add_task(function test_delete_remote_data() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data"); do_check_false(policy.pendingDeleteRemoteData); @@ -540,10 +522,8 @@ add_test(function test_delete_remote_data() { do_check_true(listener.lastRemoteDeleteRequest.isDelete); defineNow(policy, policy._futureDate(1000)); - listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); + yield listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now()); do_check_false(policy.pendingDeleteRemoteData); - - run_next_test(); }); // Ensure that deletion requests take priority over regular data submission. @@ -601,7 +581,7 @@ add_test(function test_delete_remote_data_backoff() { // If we request delete while an upload is in progress, delete should be // scheduled immediately after upload. -add_test(function test_delete_remote_data_in_progress_upload() { +add_task(function test_delete_remote_data_in_progress_upload() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_in_progress_upload"); let now = new Date(); @@ -621,14 +601,12 @@ add_test(function test_delete_remote_data_in_progress_upload() { // Now wait a little bit and finish the request. defineNow(policy, policy._futureDate(10 * 1000)); - listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); + yield listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000)); defineNow(policy, policy._futureDate(5000)); policy.checkStateAndTrigger(); do_check_eq(listener.requestDataUploadCount, 1); do_check_eq(listener.requestRemoteDeleteCount, 1); - - run_next_test(); }); add_test(function test_polling() { @@ -747,7 +725,7 @@ add_test(function test_polling_implicit_acceptance() { policy.startPolling(); }); -add_test(function test_record_health_report_upload_enabled() { +add_task(function test_record_health_report_upload_enabled() { let [policy, policyPrefs, hrPrefs, listener] = getPolicy("record_health_report_upload_enabled"); // Preconditions. @@ -763,15 +741,13 @@ add_test(function test_record_health_report_upload_enabled() { do_check_eq(listener.requestRemoteDeleteCount, 1); // Fulfilling it should make it go away. - listener.lastRemoteDeleteRequest.onNoDataAvailable(); + yield listener.lastRemoteDeleteRequest.onNoDataAvailable(); do_check_false(policy.pendingDeleteRemoteData); // User intent to enable should get us back to default state. policy.recordHealthReportUploadEnabled(true, "testing 1 2 3"); do_check_false(policy.pendingDeleteRemoteData); do_check_true(policy.healthReportUploadEnabled); - - run_next_test(); }); add_test(function test_pref_change_initiates_deletion() { diff --git a/services/datareporting/tests/xpcshell/test_session_recorder.js b/services/datareporting/tests/xpcshell/test_session_recorder.js index 0ea3919a6cbc..1e8b04233d66 100644 --- a/services/datareporting/tests/xpcshell/test_session_recorder.js +++ b/services/datareporting/tests/xpcshell/test_session_recorder.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/services/datareporting/sessions.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/healthreport/healthreporter.jsm b/services/healthreport/healthreporter.jsm index b776f881bda0..3fdc91250d35 100644 --- a/services/healthreport/healthreporter.jsm +++ b/services/healthreport/healthreporter.jsm @@ -20,7 +20,7 @@ Cu.import("resource://services-common/bagheeraclient.js"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/modules-testing/utils.jsm b/services/healthreport/modules-testing/utils.jsm index f1f90c965f08..bf0a4cc713f2 100644 --- a/services/healthreport/modules-testing/utils.jsm +++ b/services/healthreport/modules-testing/utils.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); diff --git a/services/healthreport/profile.jsm b/services/healthreport/profile.jsm index cd4457cec9ea..e3aa031d2978 100644 --- a/services/healthreport/profile.jsm +++ b/services/healthreport/profile.jsm @@ -22,7 +22,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); const DEFAULT_PROFILE_MEASUREMENT_NAME = "age"; const REQUIRED_UINT32_TYPE = {type: "TYPE_UINT32"}; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm") Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/healthreport/providers.jsm b/services/healthreport/providers.jsm index b65d0d6191a1..85a50c8f29cd 100644 --- a/services/healthreport/providers.jsm +++ b/services/healthreport/providers.jsm @@ -34,7 +34,7 @@ Cu.import("resource://gre/modules/Metrics.jsm"); #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Services.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_healthreporter.js b/services/healthreport/tests/xpcshell/test_healthreporter.js index 265e066e64de..a3d30d96e677 100644 --- a/services/healthreport/tests/xpcshell/test_healthreporter.js +++ b/services/healthreport/tests/xpcshell/test_healthreporter.js @@ -7,7 +7,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://services-common/observers.js"); Cu.import("resource://services-common/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); @@ -124,9 +124,14 @@ function getHealthReportProviderValues(reporter, day=null) { } function run_test() { - makeFakeAppDir().then(run_next_test, do_throw); + run_next_test(); } +// run_test() needs to finish synchronously, so we do async init here. +add_task(function test_init() { + yield makeFakeAppDir(); +}); + add_task(function test_constructor() { let reporter = yield getReporter("constructor"); diff --git a/services/healthreport/tests/xpcshell/test_profile.js b/services/healthreport/tests/xpcshell/test_profile.js index d17a53832fb3..ef4a51b6f04e 100644 --- a/services/healthreport/tests/xpcshell/test_profile.js +++ b/services/healthreport/tests/xpcshell/test_profile.js @@ -12,7 +12,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; let profile_creation_lower = Date.now() - MILLISECONDS_PER_DAY; do_get_profile(); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/services/healthreport/profile.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/healthreport/tests/xpcshell/test_provider_crashes.js b/services/healthreport/tests/xpcshell/test_provider_crashes.js index a2cc5997fb56..9b20f9640865 100644 --- a/services/healthreport/tests/xpcshell/test_provider_crashes.js +++ b/services/healthreport/tests/xpcshell/test_provider_crashes.js @@ -15,9 +15,14 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; function run_test() { - makeFakeAppDir().then(run_next_test, do_throw); + run_next_test(); } +// run_test() needs to finish synchronously, so we do async init here. +add_task(function test_init() { + yield makeFakeAppDir(); +}); + let gPending = {}; let gSubmitted = {}; diff --git a/services/healthreport/tests/xpcshell/test_provider_sessions.js b/services/healthreport/tests/xpcshell/test_provider_sessions.js index 07f90ce8f495..59e190d0eb78 100644 --- a/services/healthreport/tests/xpcshell/test_provider_sessions.js +++ b/services/healthreport/tests/xpcshell/test_provider_sessions.js @@ -6,7 +6,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/services-common/utils.js"); diff --git a/services/metrics/dataprovider.jsm b/services/metrics/dataprovider.jsm index 0be60e46c105..d6d2ca90c597 100644 --- a/services/metrics/dataprovider.jsm +++ b/services/metrics/dataprovider.jsm @@ -17,7 +17,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/modules-testing/mocks.jsm b/services/metrics/modules-testing/mocks.jsm index ba4bf4142beb..032f167a9620 100644 --- a/services/metrics/modules-testing/mocks.jsm +++ b/services/metrics/modules-testing/mocks.jsm @@ -15,7 +15,7 @@ this.EXPORTED_SYMBOLS = [ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://gre/modules/Task.jsm"); diff --git a/services/metrics/providermanager.jsm b/services/metrics/providermanager.jsm index 44d10d8f1693..631df1f568cf 100644 --- a/services/metrics/providermanager.jsm +++ b/services/metrics/providermanager.jsm @@ -12,7 +12,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; Cu.import("resource://gre/modules/services/metrics/dataprovider.jsm"); #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); Cu.import("resource://services-common/utils.js"); diff --git a/services/metrics/storage.jsm b/services/metrics/storage.jsm index 60b84ad60948..241518f3c195 100644 --- a/services/metrics/storage.jsm +++ b/services/metrics/storage.jsm @@ -19,7 +19,7 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; #endif -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Sqlite.jsm"); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://services-common/log4moz.js"); diff --git a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js index 4137a06f2782..232753e201ec 100644 --- a/services/metrics/tests/xpcshell/test_metrics_provider_manager.js +++ b/services/metrics/tests/xpcshell/test_metrics_provider_manager.js @@ -5,7 +5,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://testing-common/services/metrics/mocks.jsm"); diff --git a/services/metrics/tests/xpcshell/test_metrics_storage.js b/services/metrics/tests/xpcshell/test_metrics_storage.js index 6c59fb127b4c..42763dd32fa4 100644 --- a/services/metrics/tests/xpcshell/test_metrics_storage.js +++ b/services/metrics/tests/xpcshell/test_metrics_storage.js @@ -5,7 +5,7 @@ const {utils: Cu} = Components; -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Metrics.jsm"); Cu.import("resource://services-common/utils.js"); diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index aa486c3e0471..fda9260e0a43 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -10,7 +10,7 @@ Cu.import("resource://services-sync/engines/bookmarks.js"); Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); Service.engineManager.register(BookmarksEngine); var syncTesting = new SyncTestingInfrastructure(); diff --git a/services/sync/tests/unit/test_corrupt_keys.js b/services/sync/tests/unit/test_corrupt_keys.js index ecbad7546201..9ee0f34b3f30 100644 --- a/services/sync/tests/unit/test_corrupt_keys.js +++ b/services/sync/tests/unit/test_corrupt_keys.js @@ -11,7 +11,7 @@ Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/status.js"); Cu.import("resource://services-sync/util.js"); Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource://gre/modules/Promise.jsm"); add_task(function test_locally_changed_keys() { let passphrase = "abcdeabcdeabcdeabcdeabcdea"; From 4871f173ed0a678e1780d4ff6ff0a3ec5414ecf0 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Thu, 13 Jun 2013 20:46:23 -0700 Subject: [PATCH 422/615] Bug 883501 - Fix -Wreorder warning in xpcom/base/nsConsoleMessage.cpp. r=msucan --- xpcom/base/nsConsoleMessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpcom/base/nsConsoleMessage.cpp b/xpcom/base/nsConsoleMessage.cpp index 6c5c005c8db4..df0c2b3de704 100644 --- a/xpcom/base/nsConsoleMessage.cpp +++ b/xpcom/base/nsConsoleMessage.cpp @@ -14,8 +14,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsConsoleMessage, nsIConsoleMessage) nsConsoleMessage::nsConsoleMessage() - : mMessage(), - mTimeStamp(0) + : mTimeStamp(0), + mMessage() { } From 72eb34d6a2a71a9f1ef2c9713676954adc82cea8 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Thu, 13 Jun 2013 20:57:47 -0700 Subject: [PATCH 423/615] Bug 883729 - Fix -Wnull-conversion warnings in xpcom. r=bsmedberg --- xpcom/build/FileLocation.cpp | 2 +- xpcom/components/nsComponentManager.cpp | 38 ++++++++++++------------- xpcom/glue/nsInterfaceHashtable.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/xpcom/build/FileLocation.cpp b/xpcom/build/FileLocation.cpp index 37c9d3aaa3b4..309f3f0920f1 100644 --- a/xpcom/build/FileLocation.cpp +++ b/xpcom/build/FileLocation.cpp @@ -73,7 +73,7 @@ FileLocation::GetBaseFile() nsRefPtr handler = mBaseZip->GetFD(); if (handler) return handler->mFile.GetBaseFile(); - return NULL; + return nullptr; } nsCOMPtr file = mBaseFile; diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index 64b47687f22a..df16aa4cf373 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -247,14 +247,14 @@ GetLocationFromDirectoryService(const char* prop) getter_AddRefs(directoryService)); if (!directoryService) - return NULL; + return nullptr; nsCOMPtr file; nsresult rv = directoryService->Get(prop, NS_GET_IID(nsIFile), getter_AddRefs(file)); if (NS_FAILED(rv)) - return NULL; + return nullptr; return file.forget(); } @@ -265,7 +265,7 @@ CloneAndAppend(nsIFile* aBase, const nsACString& append) nsCOMPtr f; aBase->Clone(getter_AddRefs(f)); if (!f) - return NULL; + return nullptr; f->AppendNative(append); return f.forget(); @@ -386,10 +386,10 @@ nsresult nsComponentManagerImpl::Init() nsCategoryManager::GetSingleton()->SuppressNotifications(true); - RegisterModule(&kXPCOMModule, NULL); + RegisterModule(&kXPCOMModule, nullptr); for (uint32_t i = 0; i < sStaticModules->Length(); ++i) - RegisterModule((*sStaticModules)[i], NULL); + RegisterModule((*sStaticModules)[i], nullptr); nsRefPtr appOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); if (appOmnijar) { @@ -868,7 +868,7 @@ nsComponentManagerImpl::FindFactory(const nsCID& aClass) { nsFactoryEntry* e = GetFactoryEntry(aClass); if (!e) - return NULL; + return nullptr; return e->GetFactory(); } @@ -879,7 +879,7 @@ nsComponentManagerImpl::FindFactory(const char *contractID, { nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen); if (!entry) - return NULL; + return nullptr; return entry->GetFactory(); } @@ -1113,8 +1113,8 @@ FreeFactoryEntries(const nsID& aCID, nsFactoryEntry* aEntry, void* arg) { - aEntry->mFactory = NULL; - aEntry->mServiceObject = NULL; + aEntry->mFactory = nullptr; + aEntry->mServiceObject = nullptr; return PL_DHASH_NEXT; } @@ -1126,7 +1126,7 @@ nsComponentManagerImpl::FreeServices() if (!gXPCOMShuttingDown) return NS_ERROR_FAILURE; - mFactories.EnumerateRead(FreeFactoryEntries, NULL); + mFactories.EnumerateRead(FreeFactoryEntries, nullptr); return NS_OK; } @@ -1484,7 +1484,7 @@ nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt) loader = do_GetServiceFromCategory("module-loader", PromiseFlatCString(aExt).get()); if (!loader) - return NULL; + return nullptr; mLoaderMap.Put(aExt, loader); } @@ -1673,7 +1673,7 @@ nsComponentManagerImpl::ContractIDToCID(const char *aContractID, return NS_OK; } } - *_retval = NULL; + *_retval = nullptr; return NS_ERROR_FACTORY_NOT_REGISTERED; } @@ -1740,8 +1740,8 @@ nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* entry, } nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory) - : mCIDEntry(NULL) - , mModule(NULL) + : mCIDEntry(nullptr) + , mModule(nullptr) , mFactory(factory) { mozilla::Module::CIDEntry* e = new mozilla::Module::CIDEntry(); @@ -1749,7 +1749,7 @@ nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory) *cid = aCID; e->cid = cid; mCIDEntry = e; -} +} nsFactoryEntry::~nsFactoryEntry() { @@ -1769,10 +1769,10 @@ nsFactoryEntry::GetFactory() // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs // pointing to an unusable nsFactoryEntry. if (!mModule) - return NULL; + return nullptr; if (!mModule->Load()) - return NULL; + return nullptr; // Don't set mFactory directly, it needs to be locked nsCOMPtr factory; @@ -1789,7 +1789,7 @@ nsFactoryEntry::GetFactory() factory = new mozilla::GenericFactory(mCIDEntry->constructorProc); } if (!factory) - return NULL; + return nullptr; SafeMutexAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock); // Threads can race to set mFactory @@ -1859,7 +1859,7 @@ XRE_AddStaticComponent(const mozilla::Module* aComponent) if (nsComponentManagerImpl::gComponentManager && nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus) - nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, NULL); + nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, nullptr); return NS_OK; } diff --git a/xpcom/glue/nsInterfaceHashtable.h b/xpcom/glue/nsInterfaceHashtable.h index ac8e35651523..e29e7569c13b 100644 --- a/xpcom/glue/nsInterfaceHashtable.h +++ b/xpcom/glue/nsInterfaceHashtable.h @@ -135,7 +135,7 @@ nsInterfaceHashtable::Get(KeyType aKey) const { typename base_type::EntryType* ent = this->GetEntry(aKey); if (!ent) - return NULL; + return nullptr; nsCOMPtr copy = ent->mData; return copy.forget(); From 4faa887a85c4ed313fa89fa0e2e44b6a5f91d3d9 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 06:46:23 -0700 Subject: [PATCH 424/615] Bumping gaia.json for 4 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/cee7b9b5a430 Author: Anthony Ricaud Desc: Bug 879773 - Fix linter tests shame=rik ======== https://hg.mozilla.org/integration/gaia-central/rev/d75f7659b62a Author: Chris AtLee Desc: Bug 852321: Update xulrunner SDK to reduce download time. r=ochameau ======== https://hg.mozilla.org/integration/gaia-central/rev/b4bafb96eb0b Author: David Flanagan Desc: Merge pull request #10314 from RudyLu/gallery/Bug880943-correct_init Bug 880943 - Correctly init Gallery app regardless of the timing of r=davidflanagan ======== https://hg.mozilla.org/integration/gaia-central/rev/9528e6c2e59c Author: Rudy Lu Desc: Bug 880943 - Correctly init Gallery app regardless of the timing of localized event. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7220c34dc83b..026a531a30b1 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "4740827fec69f2a87743d0e457a4fd64005fe88b", + "revision": "cee7b9b5a430417658a48d3ceeb78271f34db6f7", "repo_path": "/integration/gaia-central" } From 738dfe5a9e8f592d87bc55ea35f6aae203d031a3 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 07:31:23 -0700 Subject: [PATCH 425/615] Bumping gaia.json for 1 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/0eef3cf5ff44 Author: Chris AtLee Desc: Revert "Bug 852321: Update xulrunner SDK to reduce download time. r=ochameau" This reverts commit 2edbc123567161c4a379268a2714c39dadb3f847. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 026a531a30b1..e50696e07357 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "cee7b9b5a430417658a48d3ceeb78271f34db6f7", + "revision": "0eef3cf5ff4407369e0bfb773672a6e4b5687558", "repo_path": "/integration/gaia-central" } From 34838c08c4d82d880af477e0dd1b21c553bbef7f Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 08:46:22 -0700 Subject: [PATCH 426/615] Bumping gaia.json for 1 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/2e1901cfdc03 Author: Rick Waldron Desc: Bug 882369 - [SMS][MMS] Regression. contactList => contact-list for search results and group view r=borjasalguero https://bugzilla.mozilla.org/show_bug.cgi?id=882369 Signed-off-by: Rick Waldron --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index e50696e07357..097ba94eb5a8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "0eef3cf5ff4407369e0bfb773672a6e4b5687558", + "revision": "2e1901cfdc03745c4531a5a52b6449309c3d4c59", "repo_path": "/integration/gaia-central" } From 0172483b6b89f742467c558b9b3257764c3155c0 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 09:31:22 -0700 Subject: [PATCH 427/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/6cf49c161c55 Author: Dale Harvey Desc: Merge pull request #10142 from daleharvey/837672 Bug 837672 - Add events to track camera startup performance. r=julienw ======== https://hg.mozilla.org/integration/gaia-central/rev/28fcd12f6ef1 Author: Dale Harvey Desc: Bug 837672 - Add events to track camera startup performance --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 097ba94eb5a8..a37a35133325 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "2e1901cfdc03745c4531a5a52b6449309c3d4c59", + "revision": "6cf49c161c55638f87b788756ec15192f085cd3f", "repo_path": "/integration/gaia-central" } From 97d0060a1b03d7b5dfe3eef0aeaa6eac9eacc916 Mon Sep 17 00:00:00 2001 From: Brandon Benvie Date: Fri, 14 Jun 2013 10:42:52 -0700 Subject: [PATCH 428/615] Bug 828680 - Variables view needs a controller of its own, r=vporof, msucan --- .../devtools/debugger/debugger-controller.js | 288 +++----------- .../browser_dbg_bug786070_hide_nonenums.js | 4 +- .../test/browser_dbg_propertyview-03.js | 8 +- .../test/browser_dbg_propertyview-04.js | 6 +- .../test/browser_dbg_propertyview-05.js | 24 +- .../test/browser_dbg_propertyview-06.js | 66 ++-- .../test/browser_dbg_propertyview-data.js | 6 +- .../browser_dbg_propertyview-filter-05.js | 10 +- .../devtools/netmonitor/netmonitor-view.js | 8 +- .../devtools/shared/widgets/VariablesView.jsm | 264 +++++++------ .../widgets/VariablesViewController.jsm | 350 ++++++++++++++++++ browser/devtools/webconsole/webconsole.js | 302 ++++----------- 12 files changed, 677 insertions(+), 659 deletions(-) create mode 100644 browser/devtools/shared/widgets/VariablesViewController.jsm diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index 18a5823653c4..b589f6ce0a32 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -24,6 +24,7 @@ Cu.import("resource:///modules/devtools/LayoutHelpers.jsm"); Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm"); Cu.import("resource:///modules/devtools/SideMenuWidget.jsm"); Cu.import("resource:///modules/devtools/VariablesView.jsm"); +Cu.import("resource:///modules/devtools/VariablesViewController.jsm"); Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Parser", @@ -73,6 +74,24 @@ let DebuggerController = { DebuggerView.initialize(() => { DebuggerView._isInitialized = true; + VariablesViewController.attach(DebuggerView.Variables, { + getGripClient: aObject => { + return this.activeThread.pauseGrip(aObject); + } + }); + + // Relay events from the VariablesView. + DebuggerView.Variables.on("fetched", (aEvent, aType) => { + switch (aType) { + case "variables": + window.dispatchEvent(document, "Debugger:FetchedVariables"); + break; + case "properties": + window.dispatchEvent(document, "Debugger:FetchedProperties"); + break; + } + }); + // Chrome debugging needs to initiate the connection by itself. if (window._isChromeDebugger) { this.connect().then(deferred.resolve); @@ -403,6 +422,7 @@ ThreadState.prototype = { } }; + /** * Keeps the stack frame list up-to-date, using the thread client's * stack frame cache. @@ -413,9 +433,6 @@ function StackFrames() { this._onFrames = this._onFrames.bind(this); this._onFramesCleared = this._onFramesCleared.bind(this); this._afterFramesCleared = this._afterFramesCleared.bind(this); - this._fetchScopeVariables = this._fetchScopeVariables.bind(this); - this._fetchVarProperties = this._fetchVarProperties.bind(this); - this._addVarExpander = this._addVarExpander.bind(this); this.evaluate = this.evaluate.bind(this); } @@ -588,7 +605,12 @@ StackFrames.prototype = { DebuggerView.StackFrames.empty(); for (let frame of this.activeThread.cachedFrames) { - this._addFrame(frame); + let depth = frame.depth; + let { url, line } = frame.where; + let frameLocation = NetworkHelper.convertToUnicode(unescape(url)); + let frameTitle = StackFrameUtils.getFrameTitle(frame); + + DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth); } if (this.currentFrame == null) { DebuggerView.StackFrames.selectedDepth = 0; @@ -661,6 +683,7 @@ StackFrames.prototype = { // Clear existing scopes and create each one dynamically. DebuggerView.Variables.empty(); + // If watch expressions evaluation results are available, create a scope // to contain all the values. if (this.syncedWatchExpressions && watchExpressionsEvaluation) { @@ -684,18 +707,20 @@ StackFrames.prototype = { // Create a scope to contain all the inspected variables. let label = StackFrameUtils.getScopeLabel(environment); let scope = DebuggerView.Variables.addScope(label); + let innermost = environment == frame.environment; - // Handle additions to the innermost scope. - if (environment == frame.environment) { + // Handle special additions to the innermost scope. + if (innermost) { this._insertScopeFrameReferences(scope, frame); - this._addScopeExpander(scope, environment); - // Always expand the innermost scope by default. - scope.expand(); } - // Lazily add nodes for every other environment scope. - else { - this._addScopeExpander(scope, environment); - this.autoScopeExpand && scope.expand(); + + DebuggerView.Variables.controller.addExpander(scope, environment); + + // The innermost scope is always automatically expanded, because it + // contains the variables in the current stack frame which are likely to + // be inspected. + if (innermost || this.autoScopeExpand) { + scope.expand(); } } while ((environment = environment.parent)); @@ -704,49 +729,6 @@ StackFrames.prototype = { DebuggerView.Variables.commitHierarchy(); }, - /** - * Adds an 'onexpand' callback for a scope, lazily handling - * the addition of new variables. - * - * @param Scope aScope - * The scope where the variables will be placed into. - * @param object aEnv - * The scope's environment. - */ - _addScopeExpander: function(aScope, aEnv) { - aScope._sourceEnvironment = aEnv; - - // It's a good idea to be prepared in case of an expansion. - aScope.addEventListener("mouseover", this._fetchScopeVariables, false); - // Make sure that variables are always available on expansion. - aScope.onexpand = this._fetchScopeVariables; - }, - - /** - * Adds an 'onexpand' callback for a variable, lazily handling - * the addition of new properties. - * - * @param Variable aVar - * The variable where the properties will be placed into. - * @param any aGrip - * The grip of the variable. - */ - _addVarExpander: function(aVar, aGrip) { - // No need for expansion for primitive values. - if (VariablesView.isPrimitive({ value: aGrip })) { - return; - } - aVar._sourceGrip = aGrip; - - // Some variables are likely to contain a very large number of properties. - // It's a good idea to be prepared in case of an expansion. - if (aVar.name == "window" || aVar.name == "this") { - aVar.addEventListener("mouseover", this._fetchVarProperties, false); - } - // Make sure that properties are always available on expansion. - aVar.onexpand = this._fetchVarProperties; - }, - /** * Adds the watch expressions evaluation results to a scope in the view. * @@ -770,8 +752,8 @@ StackFrames.prototype = { for (let i = 0; i < totalExpressions; i++) { let name = DebuggerView.WatchExpressions.getExpression(i); let expVal = ownProperties[i].value; - let expRef = aScope.addVar(name, ownProperties[i]); - this._addVarExpander(expRef, expVal); + let expRef = aScope.addItem(name, ownProperties[i]); + DebuggerView.Variables.controller.addExpander(expRef, expVal); // Revert some of the custom watch expressions scope presentation flags. expRef.switch = null; @@ -786,51 +768,6 @@ StackFrames.prototype = { }); }, - /** - * Adds variables to a scope in the view. Triggered when a scope is - * expanded or is hovered. It does not expand the scope. - * - * @param Scope aScope - * The scope where the variables will be placed into. - */ - _fetchScopeVariables: function(aScope) { - // Fetch the variables only once. - if (aScope._fetched) { - return; - } - aScope._fetched = true; - let env = aScope._sourceEnvironment; - - switch (env.type) { - case "with": - case "object": - // Add nodes for every variable in scope. - this.activeThread.pauseGrip(env.object).getPrototypeAndProperties((aResponse) => { - let { ownProperties, safeGetterValues } = aResponse; - this._mergeSafeGetterValues(ownProperties, safeGetterValues); - this._insertScopeVariables(ownProperties, aScope); - - // Signal that variables have been fetched. - window.dispatchEvent(document, "Debugger:FetchedVariables"); - DebuggerView.Variables.commitHierarchy(); - }); - break; - case "block": - case "function": - // Add nodes for every argument and every other variable in scope. - this._insertScopeArguments(env.bindings.arguments, aScope); - this._insertScopeVariables(env.bindings.variables, aScope); - - // No need to signal that variables have been fetched, since - // the scope arguments and variables are already attached to the - // environment bindings, so pausing the active thread is unnecessary. - break; - default: - Cu.reportError("Unknown Debugger.Environment type: " + env.type); - break; - } - }, - /** * Add nodes for special frame references in the innermost scope. * @@ -842,154 +779,21 @@ StackFrames.prototype = { _insertScopeFrameReferences: function(aScope, aFrame) { // Add any thrown exception. if (this.currentException) { - let excRef = aScope.addVar("", { value: this.currentException }); - this._addVarExpander(excRef, this.currentException); + let excRef = aScope.addItem("", { value: this.currentException }); + DebuggerView.Variables.controller.addExpander(excRef, this.currentException); } // Add any returned value. if (this.currentReturnedValue) { - let retRef = aScope.addVar("", { value: this.currentReturnedValue }); - this._addVarExpander(retRef, this.currentReturnedValue); + let retRef = aScope.addItem("", { value: this.currentReturnedValue }); + DebuggerView.Variables.controller.addExpander(retRef, this.currentReturnedValue); } // Add "this". if (aFrame.this) { - let thisRef = aScope.addVar("this", { value: aFrame.this }); - this._addVarExpander(thisRef, aFrame.this); + let thisRef = aScope.addItem("this", { value: aFrame.this }); + DebuggerView.Variables.controller.addExpander(thisRef, aFrame.this); } }, - /** - * Add nodes for every argument in scope. - * - * @param object aArguments - * The map of names to arguments, as specified in the protocol. - * @param Scope aScope - * The scope where the nodes will be placed into. - */ - _insertScopeArguments: function(aArguments, aScope) { - if (!aArguments) { - return; - } - for (let argument of aArguments) { - let name = Object.getOwnPropertyNames(argument)[0]; - let argRef = aScope.addVar(name, argument[name]); - let argVal = argument[name].value; - this._addVarExpander(argRef, argVal); - } - }, - - /** - * Add nodes for every variable in scope. - * - * @param object aVariables - * The map of names to variables, as specified in the protocol. - * @param Scope aScope - * The scope where the nodes will be placed into. - */ - _insertScopeVariables: function(aVariables, aScope) { - if (!aVariables) { - return; - } - let variableNames = Object.keys(aVariables); - - // Sort all of the variables before adding them, if preferred. - if (Prefs.variablesSortingEnabled) { - variableNames.sort(); - } - // Add the variables to the specified scope. - for (let name of variableNames) { - let varRef = aScope.addVar(name, aVariables[name]); - let varVal = aVariables[name].value; - this._addVarExpander(varRef, varVal); - } - }, - - /** - * Adds properties to a variable in the view. Triggered when a variable is - * expanded or certain variables are hovered. It does not expand the variable. - * - * @param Variable aVar - * The variable where the properties will be placed into. - */ - _fetchVarProperties: function(aVar) { - // Fetch the properties only once. - if (aVar._fetched) { - return; - } - aVar._fetched = true; - let grip = aVar._sourceGrip; - - this.activeThread.pauseGrip(grip).getPrototypeAndProperties((aResponse) => { - let { ownProperties, prototype, safeGetterValues } = aResponse; - let sortable = VariablesView.NON_SORTABLE_CLASSES.indexOf(grip.class) == -1; - - this._mergeSafeGetterValues(ownProperties, safeGetterValues); - - // Add all the variable properties. - if (ownProperties) { - aVar.addProperties(ownProperties, { - // Not all variables need to force sorted properties. - sorted: sortable, - // Expansion handlers must be set after the properties are added. - callback: this._addVarExpander - }); - } - - // Add the variable's __proto__. - if (prototype && prototype.type != "null") { - aVar.addProperty("__proto__", { value: prototype }); - // Expansion handlers must be set after the properties are added. - this._addVarExpander(aVar.get("__proto__"), prototype); - } - - // Mark the variable as having retrieved all its properties. - aVar._retrieved = true; - - // Signal that properties have been fetched. - window.dispatchEvent(document, "Debugger:FetchedProperties"); - DebuggerView.Variables.commitHierarchy(); - }); - }, - - /** - * Merge the safe getter values descriptors into the "own properties" object - * that comes from a "prototypeAndProperties" response packet. This is needed - * for Variables View. - * - * @private - * @param object aOwnProperties - * The |ownProperties| object that will get the new safe getter values. - * @param object aSafeGetterValues - * The |safeGetterValues| object. - */ - _mergeSafeGetterValues: function(aOwnProperties, aSafeGetterValues) { - // Merge the safe getter values into one object such that we can use it - // in VariablesView. - for (let name of Object.keys(aSafeGetterValues)) { - if (name in aOwnProperties) { - aOwnProperties[name].getterValue = aSafeGetterValues[name].getterValue; - aOwnProperties[name].getterPrototypeLevel = - aSafeGetterValues[name].getterPrototypeLevel; - } else { - aOwnProperties[name] = aSafeGetterValues[name]; - } - } - }, - - /** - * Adds the specified stack frame to the list. - * - * @param object aFrame - * The new frame to add. - */ - _addFrame: function(aFrame) { - let depth = aFrame.depth; - let { url, line } = aFrame.where; - let frameLocation = NetworkHelper.convertToUnicode(unescape(url)); - let frameTitle = StackFrameUtils.getFrameTitle(aFrame); - - DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth); - }, - /** * Loads more stack frames from the debugger server cache. */ diff --git a/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js b/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js index 2b088728d1b0..9749073d11cb 100644 --- a/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js +++ b/browser/devtools/debugger/test/browser_dbg_bug786070_hide_nonenums.js @@ -24,9 +24,9 @@ function testNonEnumProperties() { Services.tm.currentThread.dispatch({ run: function() { let testScope = gDebugger.DebuggerView.Variables.addScope("test-scope"); - let testVar = testScope.addVar("foo"); + let testVar = testScope.addItem("foo"); - testVar.addProperties({ + testVar.addItems({ foo: { value: "bar", enumerable: true diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-03.js b/browser/devtools/debugger/test/browser_dbg_propertyview-03.js index 5a5f5a8628b6..684af5fb7c3c 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-03.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-03.js @@ -24,8 +24,8 @@ function testSimpleCall() { Services.tm.currentThread.dispatch({ run: function() { let testScope = gDebugger.DebuggerView.Variables.addScope("test-scope"); - let testVar = testScope.addVar("something"); - let duplVar = testScope.addVar("something"); + let testVar = testScope.addItem("something"); + let duplVar = testScope.addItem("something"); info("Scope id: " + testScope.target.id); info("Scope name: " + testScope.target.name); @@ -61,8 +61,8 @@ function testSimpleCall() { "Any new variable should have a details container with no child nodes."); - let properties = testVar.addProperties({ "child": { "value": { "type": "object", - "class": "Object" } } }); + let properties = testVar.addItems({ "child": { "value": { "type": "object", + "class": "Object" } } }); ok(!testVar.expanded, diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-04.js b/browser/devtools/debugger/test/browser_dbg_propertyview-04.js index d77af3470345..47ab452c7d72 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-04.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-04.js @@ -24,9 +24,9 @@ function testSimpleCall() { Services.tm.currentThread.dispatch({ run: function() { let testScope = gDebugger.DebuggerView.Variables.addScope("test"); - let testVar = testScope.addVar("something"); + let testVar = testScope.addItem("something"); - let properties = testVar.addProperties({ + let properties = testVar.addItems({ "child": { "value": { "type": "object", @@ -43,7 +43,7 @@ function testSimpleCall() { "The added detail property should be accessible from the variable."); - let properties2 = testVar.get("child").addProperties({ + let properties2 = testVar.get("child").addItems({ "grandchild": { "value": { "type": "object", diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-05.js b/browser/devtools/debugger/test/browser_dbg_propertyview-05.js index 26a15ade549e..42336079a975 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-05.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-05.js @@ -24,7 +24,7 @@ function testSimpleCall() { Services.tm.currentThread.dispatch({ run: function() { let testScope = gDebugger.DebuggerView.Variables.addScope("test"); - let testVar = testScope.addVar("something"); + let testVar = testScope.addItem("something"); testVar.setGrip(1.618); @@ -44,32 +44,32 @@ function testSimpleCall() { "The information for the variable wasn't set correctly."); - testVar.addProperties({ "helloWorld": { "value": "hello world", "enumerable": true } }); + testVar.addItems({ "helloWorld": { "value": "hello world", "enumerable": true } }); is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 1, "A new detail node should have been added in the variable tree."); - testVar.addProperties({ "helloWorld": { "value": "hello jupiter", "enumerable": true } }); + testVar.addItems({ "helloWorld": { "value": "hello jupiter", "enumerable": true } }); is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 1, "Shouldn't be able to duplicate nodes added in the variable tree."); - testVar.addProperties({ "someProp0": { "value": "random string", "enumerable": true }, - "someProp1": { "value": "another string", "enumerable": true } }); + testVar.addItems({ "someProp0": { "value": "random string", "enumerable": true }, + "someProp1": { "value": "another string", "enumerable": true } }); is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 3, "Two new detail nodes should have been added in the variable tree."); - testVar.addProperties({ "someProp2": { "value": { "type": "null" }, "enumerable": true }, - "someProp3": { "value": { "type": "undefined" }, "enumerable": true }, - "someProp4": { - "value": { "type": "object", "class": "Object" }, - "enumerable": true - } - }); + testVar.addItems({ "someProp2": { "value": { "type": "null" }, "enumerable": true }, + "someProp3": { "value": { "type": "undefined" }, "enumerable": true }, + "someProp4": { + "value": { "type": "object", "class": "Object" }, + "enumerable": true + } + }); is(testVar.target.querySelector(".variables-view-element-details").childNodes.length, 6, "Three new detail nodes should have been added in the variable tree."); diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js index 5624dde63c4a..74dca2359dc9 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js @@ -26,14 +26,14 @@ function testSimpleCall() { let globalScope = gDebugger.DebuggerView.Variables.addScope("Test-Global"); let localScope = gDebugger.DebuggerView.Variables.addScope("Test-Local"); - let windowVar = globalScope.addVar("window"); - let documentVar = globalScope.addVar("document"); - let localVar0 = localScope.addVar("localVariable"); - let localVar1 = localScope.addVar("localVar1"); - let localVar2 = localScope.addVar("localVar2"); - let localVar3 = localScope.addVar("localVar3"); - let localVar4 = localScope.addVar("localVar4"); - let localVar5 = localScope.addVar("localVar5"); + let windowVar = globalScope.addItem("window"); + let documentVar = globalScope.addItem("document"); + let localVar0 = localScope.addItem("localVariable"); + let localVar1 = localScope.addItem("localVar1"); + let localVar2 = localScope.addItem("localVar2"); + let localVar3 = localScope.addItem("localVar3"); + let localVar4 = localScope.addItem("localVar4"); + let localVar5 = localScope.addItem("localVar5"); localVar0.setGrip(42); localVar1.setGrip(true); @@ -43,36 +43,36 @@ function testSimpleCall() { localVar4.setGrip({ "type": "null" }); localVar5.setGrip({ "type": "object", "class": "Object" }); - localVar5.addProperties({ "someProp0": { "value": 42, "enumerable": true }, - "someProp1": { "value": true , "enumerable": true}, - "someProp2": { "value": "nasu", "enumerable": true}, - "someProp3": { "value": { "type": "undefined" }, "enumerable": true}, - "someProp4": { "value": { "type": "null" }, "enumerable": true }, - "someProp5": { - "value": { "type": "object", "class": "Object" }, - "enumerable": true - } - }); + localVar5.addItems({ "someProp0": { "value": 42, "enumerable": true }, + "someProp1": { "value": true , "enumerable": true}, + "someProp2": { "value": "nasu", "enumerable": true}, + "someProp3": { "value": { "type": "undefined" }, "enumerable": true}, + "someProp4": { "value": { "type": "null" }, "enumerable": true }, + "someProp5": { + "value": { "type": "object", "class": "Object" }, + "enumerable": true + } + }); - localVar5.get("someProp5").addProperties({ "someProp0": { "value": 42, "enumerable": true }, - "someProp1": { "value": true, "enumerable": true }, - "someProp2": { "value": "nasu", "enumerable": true }, - "someProp3": { "value": { "type": "undefined" }, "enumerable": true }, - "someProp4": { "value": { "type": "null" }, "enumerable": true }, - "someAccessor": { "get": { "type": "object", "class": "Function" }, - "set": { "type": "undefined" }, - "enumerable": true } }); + localVar5.get("someProp5").addItems({ "someProp0": { "value": 42, "enumerable": true }, + "someProp1": { "value": true, "enumerable": true }, + "someProp2": { "value": "nasu", "enumerable": true }, + "someProp3": { "value": { "type": "undefined" }, "enumerable": true }, + "someProp4": { "value": { "type": "null" }, "enumerable": true }, + "someAccessor": { "get": { "type": "object", "class": "Function" }, + "set": { "type": "undefined" }, "enumerable": true } + }); windowVar.setGrip({ "type": "object", "class": "Window" }); - windowVar.addProperties({ "helloWorld": { "value": "hello world" } }); + windowVar.addItems({ "helloWorld": { "value": "hello world" } }); documentVar.setGrip({ "type": "object", "class": "HTMLDocument" }); - documentVar.addProperties({ "onload": { "value": { "type": "null" } }, - "onunload": { "value": { "type": "null" } }, - "onfocus": { "value": { "type": "null" } }, - "onblur": { "value": { "type": "null" } }, - "onclick": { "value": { "type": "null" } }, - "onkeypress": { "value": { "type": "null" } } }); + documentVar.addItems({ "onload": { "value": { "type": "null" } }, + "onunload": { "value": { "type": "null" } }, + "onfocus": { "value": { "type": "null" } }, + "onblur": { "value": { "type": "null" } }, + "onclick": { "value": { "type": "null" } }, + "onkeypress": { "value": { "type": "null" } } }); ok(windowVar, "The windowVar hasn't been created correctly."); diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-data.js b/browser/devtools/debugger/test/browser_dbg_propertyview-data.js index cd24c7c667f0..6cf2c0560db4 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-data.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-data.js @@ -75,11 +75,11 @@ function testVariablesView() testIntegrity(arr, obj); let fooScope = gVariablesView.addScope("foo"); - let anonymousVar = fooScope.addVar(); + let anonymousVar = fooScope.addItem(); let anonymousScope = gVariablesView.addScope(); - let barVar = anonymousScope.addVar("bar"); - let bazProperty = barVar.addProperty("baz"); + let barVar = anonymousScope.addItem("bar"); + let bazProperty = barVar.addItem("baz"); testAnonymousHeaders(fooScope, anonymousVar, anonymousScope, barVar, bazProperty); testPropertyInheritance(fooScope, anonymousVar, anonymousScope, barVar, bazProperty); diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js index 8cf6cab58470..18245e5bb68f 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-filter-05.js @@ -110,8 +110,9 @@ function testVariablesFiltering() is(gSearchBox.value, "*", "Searchbox value is incorrect after 3 backspaces"); - is(innerScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 3, - "There should be 3 variables displayed in the inner scope"); + // variable count includes `__proto__` for object scopes + is(innerScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 4, + "There should be 4 variables displayed in the inner scope"); isnot(mathScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 0, "There should be some variables displayed in the math scope"); isnot(testScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 0, @@ -140,8 +141,9 @@ function testVariablesFiltering() is(gSearchBox.value, "", "Searchbox value is incorrect after 1 backspace"); - is(innerScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 3, - "There should be 3 variables displayed in the inner scope"); + // variable count includes `__proto__` for object scopes + is(innerScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 4, + "There should be 4 variables displayed in the inner scope"); isnot(mathScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 0, "There should be some variables displayed in the math scope"); isnot(testScope.querySelectorAll(".variables-view-variable:not([non-match])").length, 0, diff --git a/browser/devtools/netmonitor/netmonitor-view.js b/browser/devtools/netmonitor/netmonitor-view.js index 34a0d94a018b..c59dd35809a6 100644 --- a/browser/devtools/netmonitor/netmonitor-view.js +++ b/browser/devtools/netmonitor/netmonitor-view.js @@ -1446,7 +1446,7 @@ NetworkDetailsView.prototype = { headersScope.expanded = true; for (let header of aResponse.headers) { - let headerVar = headersScope.addVar(header.name, { null: true }, true); + let headerVar = headersScope.addItem(header.name, { null: true }, true); gNetwork.getString(header.value).then((aString) => headerVar.setGrip(aString)); } }, @@ -1489,7 +1489,7 @@ NetworkDetailsView.prototype = { cookiesScope.expanded = true; for (let cookie of aResponse.cookies) { - let cookieVar = cookiesScope.addVar(cookie.name, { null: true }, true); + let cookieVar = cookiesScope.addItem(cookie.name, { null: true }, true); gNetwork.getString(cookie.value).then((aString) => cookieVar.setGrip(aString)); // By default the cookie name and value are shown. If this is the only @@ -1591,7 +1591,7 @@ NetworkDetailsView.prototype = { paramsScope.expanded = true; for (let param of paramsArray) { - let headerVar = paramsScope.addVar(param.name, { null: true }, true); + let headerVar = paramsScope.addItem(param.name, { null: true }, true); headerVar.setGrip(param.value); } }, @@ -1634,7 +1634,7 @@ NetworkDetailsView.prototype = { : L10N.getStr("jsonScopeName"); let jsonScope = this._json.addScope(jsonScopeName); - jsonScope.addVar().populate(jsonObject, { expanded: true }); + jsonScope.addItem().populate(jsonObject, { expanded: true }); jsonScope.expanded = true; } // Malformed JSON. diff --git a/browser/devtools/shared/widgets/VariablesView.jsm b/browser/devtools/shared/widgets/VariablesView.jsm index 9a9fad892bdd..f31ddbc25bda 100644 --- a/browser/devtools/shared/widgets/VariablesView.jsm +++ b/browser/devtools/shared/widgets/VariablesView.jsm @@ -20,6 +20,8 @@ const SEARCH_ACTION_MAX_DELAY = 300; // ms Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); +Cu.import("resource:///modules/devtools/shared/event-emitter.js"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper", "resource://gre/modules/devtools/NetworkHelper.jsm"); @@ -74,6 +76,8 @@ this.VariablesView = function VariablesView(aParentNode, aFlags = {}) { for (let name in aFlags) { this[name] = aFlags[name]; } + + EventEmitter.decorate(this); }; VariablesView.prototype = { @@ -86,7 +90,7 @@ VariablesView.prototype = { */ set rawObject(aObject) { this.empty(); - this.addScope().addVar().populate(aObject); + this.addScope().addItem().populate(aObject); }, /** @@ -180,6 +184,11 @@ VariablesView.prototype = { }, aTimeout); }, + /** + * The controller for this VariablesView, if it has one. + */ + controller: null, + /** * The amount of time (in milliseconds) it takes to empty this view lazily. */ @@ -587,7 +596,8 @@ VariablesView.prototype = { */ getScopeForNode: function(aNode) { let item = this._itemsByElement.get(aNode); - if (item && !(item instanceof Variable) && !(item instanceof Property)) { + // Match only Scopes, not Variables or Properties. + if (item && !(item instanceof Variable)) { return item; } return null; @@ -790,9 +800,8 @@ VariablesView.prototype = { case e.DOM_VK_RETURN: case e.DOM_VK_ENTER: - // Start editing the value or name of the variable or property. - if (item instanceof Variable || - item instanceof Property) { + // Start editing the value or name of the Variable or Property. + if (item instanceof Variable) { if (e.metaKey || e.altKey || e.shiftKey) { item._activateNameInput(); } else { @@ -803,9 +812,8 @@ VariablesView.prototype = { case e.DOM_VK_DELETE: case e.DOM_VK_BACK_SPACE: - // Delete the variable or property if allowed. - if (item instanceof Variable || - item instanceof Property) { + // Delete the Variable or Property if allowed. + if (item instanceof Variable) { item._onDelete(e); } return; @@ -902,6 +910,7 @@ VariablesView.NON_SORTABLE_CLASSES = [ "Array", "Int8Array", "Uint8Array", + "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", @@ -910,6 +919,16 @@ VariablesView.NON_SORTABLE_CLASSES = [ "Float64Array" ]; +/** + * Determine whether an object's properties should be sorted based on its class. + * + * @param string aClassName + * The class of the object. + */ +VariablesView.isSortable = function(aClassName) { + return VariablesView.NON_SORTABLE_CLASSES.indexOf(aClassName) == -1; +}; + /** * Generates the string evaluated when performing simple value changes. * @@ -917,11 +936,13 @@ VariablesView.NON_SORTABLE_CLASSES = [ * The current variable or property. * @param string aCurrentString * The trimmed user inputted string. + * @param string aPrefix [optional] + * Prefix for the symbolic name. * @return string * The string to be evaluated. */ -VariablesView.simpleValueEvalMacro = function(aItem, aCurrentString) { - return aItem._symbolicName + "=" + aCurrentString; +VariablesView.simpleValueEvalMacro = function(aItem, aCurrentString, aPrefix = "") { + return aPrefix + aItem._symbolicName + "=" + aCurrentString; }; /** @@ -932,12 +953,14 @@ VariablesView.simpleValueEvalMacro = function(aItem, aCurrentString) { * The current getter or setter property. * @param string aCurrentString * The trimmed user inputted string. + * @param string aPrefix [optional] + * Prefix for the symbolic name. * @return string * The string to be evaluated. */ -VariablesView.overrideValueEvalMacro = function(aItem, aCurrentString) { +VariablesView.overrideValueEvalMacro = function(aItem, aCurrentString, aPrefix = "") { let property = "\"" + aItem._nameString + "\""; - let parent = aItem.ownerView._symbolicName || "this"; + let parent = aPrefix + aItem.ownerView._symbolicName || "this"; return "Object.defineProperty(" + parent + "," + property + "," + "{ value: " + aCurrentString + @@ -954,15 +977,17 @@ VariablesView.overrideValueEvalMacro = function(aItem, aCurrentString) { * The current getter or setter property. * @param string aCurrentString * The trimmed user inputted string. + * @param string aPrefix [optional] + * Prefix for the symbolic name. * @return string * The string to be evaluated. */ -VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString) { +VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString, aPrefix = "") { let type = aItem._nameString; let propertyObject = aItem.ownerView; let parentObject = propertyObject.ownerView; let property = "\"" + propertyObject._nameString + "\""; - let parent = parentObject._symbolicName || "this"; + let parent = aPrefix + parentObject._symbolicName || "this"; switch (aCurrentString) { case "": @@ -976,7 +1001,7 @@ VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString) { if ((type == "set" && propertyObject.getter.type == "undefined") || (type == "get" && propertyObject.setter.type == "undefined")) { // Make sure the right getter/setter to value override macro is applied to the target object. - return propertyObject.evaluationMacro(propertyObject, "undefined"); + return propertyObject.evaluationMacro(propertyObject, "undefined", aPrefix); } // Construct and return the getter/setter removal evaluation string. @@ -995,16 +1020,16 @@ VariablesView.getterOrSetterEvalMacro = function(aItem, aCurrentString) { default: // Wrap statements inside a function declaration if not already wrapped. - if (aCurrentString.indexOf("function") != 0) { + if (!aCurrentString.startsWith("function")) { let header = "function(" + (type == "set" ? "value" : "") + ")"; let body = ""; // If there's a return statement explicitly written, always use the // standard function definition syntax - if (aCurrentString.indexOf("return ") != -1) { + if (aCurrentString.contains("return ")) { body = "{" + aCurrentString + "}"; } // If block syntax is used, use the whole string as the function body. - else if (aCurrentString.indexOf("{") == 0) { + else if (aCurrentString.startsWith("{")) { body = aCurrentString; } // Prefer an expression closure. @@ -1042,6 +1067,7 @@ VariablesView.getterOrSetterDeleteCallback = function(aItem) { return true; // Don't hide the element. }; + /** * A Scope is an object holding Variable instances. * Iterable via "for (let [name, variable] in instance) { }". @@ -1083,12 +1109,31 @@ function Scope(aView, aName, aFlags = {}) { Scope.prototype = { /** - * Adds a variable to contain any inspected properties. + * Whether this Scope should be prefetched when it is remoted. + */ + shouldPrefetch: true, + + /** + * Create a new Variable that is a child of this Scope. * * @param string aName - * The variable's name. + * The name of the new Property. * @param object aDescriptor - * Specifies the value and/or type & class of the variable, + * The variable's descriptor. + * @return Variable + * The newly created child Variable. + */ + _createChild: function(aName, aDescriptor) { + return new Variable(this, aName, aDescriptor); + }, + + /** + * Adds a child to contain any inspected properties. + * + * @param string aName + * The child's name. + * @param object aDescriptor + * Specifies the value and/or type & class of the child, * or 'get' & 'set' accessor properties. If the type is implicit, * it will be inferred from the value. * e.g. - { value: 42 } @@ -1104,17 +1149,56 @@ Scope.prototype = { * @return Variable * The newly created Variable instance, null if it already exists. */ - addVar: function(aName = "", aDescriptor = {}, aRelaxed = false) { + addItem: function(aName = "", aDescriptor = {}, aRelaxed = false) { if (this._store.has(aName) && !aRelaxed) { return null; } - let variable = new Variable(this, aName, aDescriptor); - this._store.set(aName, variable); - this._variablesView._itemsByElement.set(variable._target, variable); - this._variablesView._currHierarchy.set(variable._absoluteName, variable); - variable.header = !!aName; - return variable; + let child = this._createChild(aName, aDescriptor); + this._store.set(aName, child); + this._variablesView._itemsByElement.set(child._target, child); + this._variablesView._currHierarchy.set(child._absoluteName, child); + child.header = !!aName; + return child; + }, + + /** + * Adds items for this variable. + * + * @param object aItems + * An object containing some { name: descriptor } data properties, + * specifying the value and/or type & class of the variable, + * or 'get' & 'set' accessor properties. If the type is implicit, + * it will be inferred from the value. + * e.g. - { someProp0: { value: 42 }, + * someProp1: { value: true }, + * someProp2: { value: "nasu" }, + * someProp3: { value: { type: "undefined" } }, + * someProp4: { value: { type: "null" } }, + * someProp5: { value: { type: "object", class: "Object" } }, + * someProp6: { get: { type: "object", class: "Function" }, + * set: { type: "undefined" } } } + * @param object aOptions [optional] + * Additional options for adding the properties. Supported options: + * - sorted: true to sort all the properties before adding them + * - callback: function invoked after each item is added + */ + addItems: function(aItems, aOptions = {}) { + let names = Object.keys(aItems); + + // Sort all of the properties before adding them, if preferred. + if (aOptions.sorted) { + names.sort(); + } + // Add the properties to the current scope. + for (let name of names) { + let descriptor = aItems[name]; + let item = this.addItem(name, descriptor); + + if (aOptions.callback) { + aOptions.callback(item, descriptor.value); + } + } }, /** @@ -1179,11 +1263,13 @@ Scope.prototype = { if (this.isChildOf(aParent)) { return true; } - if (this.ownerView instanceof Scope || - this.ownerView instanceof Variable || - this.ownerView instanceof Property) { + + // Recurse to parent if it is a Scope, Variable, or Property. + if (this.ownerView instanceof Scope) { return this.ownerView.isDescendantOf(aParent); } + + return false; }, /** @@ -1405,10 +1491,9 @@ Scope.prototype = { } // Check if all parent objects are expanded. let item = this; - while ((item = item.ownerView) && /* Parent object exists. */ - (item instanceof Scope || - item instanceof Variable || - item instanceof Property)) { + + // Recurse while parent is a Scope, Variable, or Property + while ((item = item.ownerView) && item instanceof Scope) { if (!item._isExpanded) { return false; } @@ -1722,14 +1807,11 @@ Scope.prototype = { variable._wasToggled = true; } - // If the variable is contained in another scope (variable or property), + // If the variable is contained in another Scope, Variable, or Property, // the parent may not be a match, thus hidden. It should be visible // ("expand upwards"). - while ((variable = variable.ownerView) && /* Parent object exists. */ - (variable instanceof Scope || - variable instanceof Variable || - variable instanceof Property)) { + variable instanceof Scope) { // Show and expand the parent, as it is certainly accessible. variable._matched = true; @@ -1971,79 +2053,24 @@ function Variable(aScope, aName, aDescriptor) { ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, { /** - * Adds a property for this variable. - * - * @param string aName - * The property's name. - * @param object aDescriptor - * Specifies the value and/or type & class of the property, - * or 'get' & 'set' accessor properties. If the type is implicit, - * it will be inferred from the value. - * e.g. - { value: 42 } - * - { value: true } - * - { value: "nasu" } - * - { value: { type: "undefined" } } - * - { value: { type: "null" } } - * - { value: { type: "object", class: "Object" } } - * - { get: { type: "object", class: "Function" }, - * set: { type: "undefined" } } - * - { get: { type "object", class: "Function" }, - * getterValue: "foo", getterPrototypeLevel: 2 } - * @param boolean aRelaxed - * True if name duplicates should be allowed. - * @return Property - * The newly created Property instance, null if it already exists. + * Whether this Scope should be prefetched when it is remoted. */ - addProperty: function(aName = "", aDescriptor = {}, aRelaxed = false) { - if (this._store.has(aName) && !aRelaxed) { - return null; - } - - let property = new Property(this, aName, aDescriptor); - this._store.set(aName, property); - this._variablesView._itemsByElement.set(property._target, property); - this._variablesView._currHierarchy.set(property._absoluteName, property); - property.header = !!aName; - return property; + get shouldPrefetch(){ + return this.name == "window" || this.name == "this"; }, /** - * Adds properties for this variable. + * Create a new Property that is a child of Variable. * - * @param object aProperties - * An object containing some { name: descriptor } data properties, - * specifying the value and/or type & class of the variable, - * or 'get' & 'set' accessor properties. If the type is implicit, - * it will be inferred from the value. - * e.g. - { someProp0: { value: 42 }, - * someProp1: { value: true }, - * someProp2: { value: "nasu" }, - * someProp3: { value: { type: "undefined" } }, - * someProp4: { value: { type: "null" } }, - * someProp5: { value: { type: "object", class: "Object" } }, - * someProp6: { get: { type: "object", class: "Function" }, - * set: { type: "undefined" } } } - * @param object aOptions [optional] - * Additional options for adding the properties. Supported options: - * - sorted: true to sort all the properties before adding them - * - callback: function invoked after each property is added + * @param string aName + * The name of the new Property. + * @param object aDescriptor + * The property's descriptor. + * @return Property + * The newly created child Property. */ - addProperties: function(aProperties, aOptions = {}) { - let propertyNames = Object.keys(aProperties); - - // Sort all of the properties before adding them, if preferred. - if (aOptions.sorted) { - propertyNames.sort(); - } - // Add the properties to the current scope. - for (let name of propertyNames) { - let descriptor = aProperties[name]; - let property = this.addProperty(name, descriptor); - - if (aOptions.callback) { - aOptions.callback(property, descriptor.value); - } - } + _createChild: function(aName, aDescriptor) { + return new Property(this, aName, aDescriptor); }, /** @@ -2122,7 +2149,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, { let descriptor = Object.create(aDescriptor); descriptor.value = VariablesView.getGrip(aValue); - let propertyItem = this.addProperty(aName, descriptor); + let propertyItem = this.addItem(aName, descriptor); propertyItem._sourceValue = aValue; // Add an 'onexpand' callback for the property, lazily handling @@ -2149,7 +2176,7 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, { descriptor.get = VariablesView.getGrip(aDescriptor.get); descriptor.set = VariablesView.getGrip(aDescriptor.set); - return this.addProperty(aName, descriptor); + return this.addItem(aName, descriptor); }, /** @@ -2311,8 +2338,8 @@ ViewHelpers.create({ constructor: Variable, proto: Scope.prototype }, { this.evaluationMacro = null; } - let getter = this.addProperty("get", { value: descriptor.get }); - let setter = this.addProperty("set", { value: descriptor.set }); + let getter = this.addItem("get", { value: descriptor.get }); + let setter = this.addItem("set", { value: descriptor.set }); getter.evaluationMacro = VariablesView.getterOrSetterEvalMacro; setter.evaluationMacro = VariablesView.getterOrSetterEvalMacro; @@ -2852,9 +2879,8 @@ VariablesView.prototype.commitHierarchy = function() { if (prevVariable) { expanded = prevVariable._isExpanded; - // Only analyze variables and properties for displayed value changes. - if (currVariable instanceof Variable || - currVariable instanceof Property) { + // Only analyze Variables and Properties for displayed value changes. + if (currVariable instanceof Variable) { changed = prevVariable._valueString != currVariable._valueString; } } @@ -2974,6 +3000,16 @@ VariablesView.isFalsy = function(aDescriptor) { return false; }; +/** + * Returns true if the value is an instance of Variable or Property. + * + * @param any aValue + * The value to test. + */ +VariablesView.isVariable = function(aValue) { + return aValue instanceof Variable; +}; + /** * Returns a standard grip for a value. * diff --git a/browser/devtools/shared/widgets/VariablesViewController.jsm b/browser/devtools/shared/widgets/VariablesViewController.jsm new file mode 100644 index 000000000000..56704b2d2ac7 --- /dev/null +++ b/browser/devtools/shared/widgets/VariablesViewController.jsm @@ -0,0 +1,350 @@ +/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* 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"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js"); +Cu.import("resource:///modules/devtools/VariablesView.jsm"); +Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); +Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm"); + +XPCOMUtils.defineLazyGetter(this, "VARIABLES_SORTING_ENABLED", () => + Services.prefs.getBoolPref("devtools.debugger.ui.variables-sorting-enabled") +); + +const MAX_LONG_STRING_LENGTH = 200000; + +this.EXPORTED_SYMBOLS = ["VariablesViewController"]; + + +/** + * Controller for a VariablesView that handles interfacing with the debugger + * protocol. Is able to populate scopes and variables via the protocol as well + * as manage actor lifespans. + * + * @param VariablesView aView + * The view to attach to. + * @param object aOptions + * Options for configuring the controller. Supported options: + * - getGripClient: callback for creating an object grip client + * - getLongStringClient: callback for creating a long string grip client + * - releaseActor: callback for releasing an actor when it's no longer needed + * - overrideValueEvalMacro: callback for creating an overriding eval macro + * - getterOrSetterEvalMacro: callback for creating a getter/setter eval macro + * - simpleValueEvalMacro: callback for creating a simple value eval macro + */ +function VariablesViewController(aView, aOptions) { + this.addExpander = this.addExpander.bind(this); + + this._getGripClient = aOptions.getGripClient; + this._getLongStringClient = aOptions.getLongStringClient; + this._releaseActor = aOptions.releaseActor; + + if (aOptions.overrideValueEvalMacro) { + this._overrideValueEvalMacro = aOptions.overrideValueEvalMacro; + } + if (aOptions.getterOrSetterEvalMacro) { + this._getterOrSetterEvalMacro = aOptions.getterOrSetterEvalMacro; + } + if (aOptions.simpleValueEvalMacro) { + this._simpleValueEvalMacro = aOptions.simpleValueEvalMacro; + } + + this._actors = new Set(); + this.view = aView; + this.view.controller = this; +} + +VariablesViewController.prototype = { + /** + * The default getter/setter evaluation macro. + */ + _getterOrSetterEvalMacro: VariablesView.getterOrSetterEvalMacro, + + /** + * The default override value evaluation macro. + */ + _overrideValueEvalMacro: VariablesView.overrideValueEvalMacro, + + /** + * The default simple value evaluation macro. + */ + _simpleValueEvalMacro: VariablesView.simpleValueEvalMacro, + + /** + * Populate a long string into a target using a grip. + * + * @param Variable aTarget + * The target Variable/Property to put the retrieved string into. + * @param LongStringActor aGrip + * The long string grip that use to retrieve the full string. + * @return Promise + * The promise that will be resolved when the string is retrieved. + */ + _populateFromLongString: function(aTarget, aGrip){ + let deferred = Promise.defer(); + + let from = aGrip.initial.length; + let to = Math.min(aGrip.length, MAX_LONG_STRING_LENGTH); + + this._getLongStringClient(aGrip).substring(from, to, aResponse => { + // Stop tracking the actor because it's no longer needed. + this.releaseActor(aGrip); + + // Replace the preview with the full string and make it non-expandable. + aTarget.onexpand = null; + aTarget.setGrip(aGrip.initial + aResponse.substring); + aTarget.hideArrow(); + + // Mark the string as having retrieved. + aTarget._retrieved = true; + deferred.resolve(); + }); + + return deferred.promise; + }, + + /** + * Adds properties to a Scope, Variable, or Property in the view. Triggered + * when a scope is expanded or certain variables are hovered. + * + * @param Scope aTarget + * The Scope where the properties will be placed into. + * @param object aGrip + * The grip to use to populate the target. + */ + _populateFromObject: function(aTarget, aGrip) { + let deferred = Promise.defer(); + + this._getGripClient(aGrip).getPrototypeAndProperties(aResponse => { + let { ownProperties, prototype, safeGetterValues } = aResponse; + let sortable = VariablesView.isSortable(aGrip.class); + + // Merge the safe getter values into one object such that we can use it + // in VariablesView. + for (let name of Object.keys(safeGetterValues)) { + if (name in ownProperties) { + ownProperties[name].getterValue = safeGetterValues[name].getterValue; + ownProperties[name].getterPrototypeLevel = safeGetterValues[name] + .getterPrototypeLevel; + } else { + ownProperties[name] = safeGetterValues[name]; + } + } + + // Add all the variable properties. + if (ownProperties) { + aTarget.addItems(ownProperties, { + // Not all variables need to force sorted properties. + sorted: sortable, + // Expansion handlers must be set after the properties are added. + callback: this.addExpander + }); + } + + // Add the variable's __proto__. + if (prototype && prototype.type != "null") { + let proto = aTarget.addItem("__proto__", { value: prototype }); + // Expansion handlers must be set after the properties are added. + this.addExpander(proto, prototype); + } + + // Mark the variable as having retrieved all its properties. + aTarget._retrieved = true; + this.view.commitHierarchy(); + deferred.resolve(); + }); + + return deferred.promise; + }, + + /** + * Adds an 'onexpand' callback for a variable, lazily handling + * the addition of new properties. + * + * @param Variable aVar + * The variable where the properties will be placed into. + * @param any aSource + * The source to use to populate the target. + */ + addExpander: function(aTarget, aSource) { + // Attach evaluation macros as necessary. + if (aTarget.getter || aTarget.setter) { + aTarget.evaluationMacro = this._overrideValueEvalMacro; + + let getter = aTarget.get("get"); + if (getter) { + getter.evaluationMacro = this._getterOrSetterEvalMacro; + } + + let setter = aTarget.get("set"); + if (setter) { + setter.evaluationMacro = this._getterOrSetterEvalMacro; + } + } else { + aTarget.evaluationMacro = this._simpleValueEvalMacro; + } + + // If the source is primitive then an expander is not needed. + if (VariablesView.isPrimitive({ value: aSource })) { + return; + } + + // If the source is a long string then show the arrow. + if (WebConsoleUtils.isActorGrip(aSource) && aSource.type == "longString") { + aTarget.showArrow(); + } + + // Make sure that properties are always available on expansion. + aTarget.onexpand = () => this.expand(aTarget, aSource); + + // Some variables are likely to contain a very large number of properties. + // It's a good idea to be prepared in case of an expansion. + if (aTarget.shouldPrefetch) { + aTarget.addEventListener("mouseover", aTarget.onexpand, false); + } + + // Register all the actors that this controller now depends on. + for (let grip of [aTarget.value, aTarget.getter, aTarget.setter]) { + if (WebConsoleUtils.isActorGrip(grip)) { + this._actors.add(grip.actor); + } + } + }, + + /** + * Adds properties to a Scope, Variable, or Property in the view. Triggered + * when a scope is expanded or certain variables are hovered. + * + * @param Scope aTarget + * The Scope to be expanded. + * @param object aSource + * The source to use to populate the target. + * @return Promise + * The promise that is resolved once the target has been expanded. + */ + expand: function(aTarget, aSource) { + // Fetch the variables only once. + if (aTarget._fetched) { + return aTarget._fetched; + } + + let deferred = Promise.defer(); + aTarget._fetched = deferred.promise; + + if (!aSource) { + throw new Error("No actor grip was given for the variable."); + } + + // If the target a Variable or Property then we're fetching properties + if (VariablesView.isVariable(aTarget)) { + this._populateFromObject(aTarget, aSource).then(() => { + deferred.resolve(); + // Signal that properties have been fetched. + this.view.emit("fetched", "properties", aTarget); + }); + return deferred.promise; + } + + switch (aSource.type) { + case "longString": + this._populateFromLongString(aTarget, aSource).then(() => { + deferred.resolve(); + // Signal that a long string has been fetched. + this.view.emit("fetched", "longString", aTarget); + }); + break; + case "with": + case "object": + this._populateFromObject(aTarget, aSource.object).then(() => { + deferred.resolve(); + // Signal that variables have been fetched. + this.view.emit("fetched", "variables", aTarget); + }); + break; + case "block": + case "function": + // Add nodes for every argument and every other variable in scope. + let args = aSource.bindings.arguments; + if (args) { + for (let arg of args) { + let name = Object.getOwnPropertyNames(arg)[0]; + let ref = aTarget.addItem(name, arg[name]); + let val = arg[name].value; + this.addExpander(ref, val); + } + } + + aTarget.addItems(aSource.bindings.variables, { + // Not all variables need to force sorted properties. + sorted: VARIABLES_SORTING_ENABLED, + // Expansion handlers must be set after the properties are added. + callback: this.addExpander + }); + + // No need to signal that variables have been fetched, since + // the scope arguments and variables are already attached to the + // environment bindings, so pausing the active thread is unnecessary. + + deferred.resolve(); + break; + default: + let error = "Unknown Debugger.Environment type: " + aSource.type; + Cu.reportError(error); + deferred.reject(error); + } + + return deferred.promise; + }, + + /** + * Release an actor from the controller. + * + * @param object aActor + * The actor to release. + */ + releaseActor: function(aActor){ + if (this._releaseActor) { + this._releaseActor(aActor); + } + this._actors.delete(aActor); + }, + + /** + * Release all the actors referenced by the controller, optionally filtered. + * + * @param function aFilter [optional] + * Callback to filter which actors are released. + */ + releaseActors: function(aFilter) { + for (let actor of this._actors) { + if (!aFilter || aFilter(actor)) { + this.releaseActor(actor); + } + } + }, +}; + + +/** + * Attaches a VariablesViewController to a VariablesView if it doesn't already + * have one. + * + * @param VariablesView aView + * The view to attach to. + * @param object aOptions + * The options to use in creating the controller. + * @return VariablesViewController + */ +VariablesViewController.attach = function(aView, aOptions) { + if (aView.controller) { + return aView.controller; + } + return new VariablesViewController(aView, aOptions); +}; diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index 291d8531d166..373b5c67743f 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -37,6 +37,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise", XPCOMUtils.defineLazyModuleGetter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "VariablesViewController", + "resource:///modules/devtools/VariablesViewController.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter", "resource:///modules/devtools/shared/event-emitter.js"); @@ -2104,13 +2107,9 @@ WebConsoleFrame.prototype = { } else if (aNode.classList.contains("webconsole-msg-inspector")) { let view = aNode._variablesView; - let actors = view ? - this.jsterm._objectActorsInVariablesViews.get(view) : - new Set(); - for (let actor of actors) { - this._releaseObject(actor); + if (view) { + view.controller.releaseActors(); } - actors.clear(); aNode._variablesView = null; } @@ -2743,6 +2742,35 @@ WebConsoleFrame.prototype = { }, }; + +/** + * @see VariablesView.simpleValueEvalMacro + */ +function simpleValueEvalMacro(aItem, aCurrentString) +{ + return VariablesView.simpleValueEvalMacro(aItem, aCurrentString, "_self"); +}; + + +/** + * @see VariablesView.overrideValueEvalMacro + */ +function overrideValueEvalMacro(aItem, aCurrentString) +{ + return VariablesView.overrideValueEvalMacro(aItem, aCurrentString, "_self"); +}; + + +/** + * @see VariablesView.getterOrSetterEvalMacro + */ +function getterOrSetterEvalMacro(aItem, aCurrentString) +{ + return VariablesView.getterOrSetterEvalMacro(aItem, aCurrentString, "_self"); +} + + + /** * Create a JSTerminal (a JavaScript command line). This is attached to an * existing HeadsUpDisplay (a Web Console instance). This code is responsible @@ -2771,8 +2799,6 @@ function JSTerm(aWebConsoleFrame) this._keyPress = this.keyPress.bind(this); this._inputEventHandler = this.inputEventHandler.bind(this); - this._fetchVarProperties = this._fetchVarProperties.bind(this); - this._fetchVarLongString = this._fetchVarLongString.bind(this); this._onKeypressInVariablesView = this._onKeypressInVariablesView.bind(this); EventEmitter.decorate(this); @@ -3282,7 +3308,27 @@ JSTerm.prototype = { view.searchEnabled = !aOptions.hideFilterInput; view.lazyEmpty = this._lazyVariablesView; view.lazyAppend = this._lazyVariablesView; - this._objectActorsInVariablesViews.set(view, new Set()); + + VariablesViewController.attach(view, { + getGripClient: aGrip => { + return new GripClient(this.hud.proxy.client, aGrip); + }, + getLongStringClient: aGrip => { + return this.webConsoleClient.longString(aGrip); + }, + releaseActor: aActor => { + this.hud._releaseObject(aActor); + }, + simpleValueEvalMacro: simpleValueEvalMacro, + overrideValueEvalMacro: overrideValueEvalMacro, + getterOrSetterEvalMacro: getterOrSetterEvalMacro, + }); + + // Relay events from the VariablesView. + view.on("fetched", (aEvent, aType, aVar) => { + this.emit("variablesview-fetched", aVar); + }); + return view; }, @@ -3304,16 +3350,11 @@ JSTerm.prototype = { view.createHierarchy(); view.empty(); - let actors = this._objectActorsInVariablesViews.get(view); - for (let actor of actors) { - // We need to avoid pruning the object inspection starting point. - // That one is pruned when the console message is removed. - if (view._consoleLastObjectActor != actor) { - this.hud._releaseObject(actor); - } - } - - actors.clear(); + // We need to avoid pruning the object inspection starting point. + // That one is pruned when the console message is removed. + view.controller.releaseActors(aActor => { + return view._consoleLastObjectActor != aActor; + }); if (aOptions.objectActor) { // Make sure eval works in the correct context. @@ -3331,11 +3372,11 @@ JSTerm.prototype = { scope.expanded = true; scope.locked = true; - let container = scope.addVar(); - container.evaluationMacro = this._variablesViewSimpleValueEvalMacro; + let container = scope.addItem(); + container.evaluationMacro = simpleValueEvalMacro; if (aOptions.objectActor) { - this._fetchVarProperties(container, aOptions.objectActor); + view.controller.expand(container, aOptions.objectActor); view._consoleLastObjectActor = aOptions.objectActor.actor; } else if (aOptions.rawObject) { @@ -3374,80 +3415,6 @@ JSTerm.prototype = { this.requestEvaluation(aString, evalOptions).then(onEval, onEval); }, - /** - * Generates the string evaluated when performing simple value changes in the - * variables view. - * - * @private - * @param Variable | Property aItem - * The current variable or property. - * @param string aCurrentString - * The trimmed user inputted string. - * @return string - * The string to be evaluated. - */ - _variablesViewSimpleValueEvalMacro: - function JST__variablesViewSimpleValueEvalMacro(aItem, aCurrentString) - { - return "_self" + aItem.symbolicName + "=" + aCurrentString; - }, - - - /** - * Generates the string evaluated when overriding getters and setters with - * plain values in the variables view. - * - * @private - * @param Property aItem - * The current getter or setter property. - * @param string aCurrentString - * The trimmed user inputted string. - * @return string - * The string to be evaluated. - */ - _variablesViewOverrideValueEvalMacro: - function JST__variablesViewOverrideValueEvalMacro(aItem, aCurrentString) - { - let parent = aItem.ownerView; - let symbolicName = parent.symbolicName; - if (symbolicName.indexOf("_self") != 0) { - parent._symbolicName = "_self" + symbolicName; - } - - let result = VariablesView.overrideValueEvalMacro.apply(this, arguments); - - parent._symbolicName = symbolicName; - - return result; - }, - - /** - * Generates the string evaluated when performing getters and setters changes - * in the variables view. - * - * @private - * @param Property aItem - * The current getter or setter property. - * @param string aCurrentString - * The trimmed user inputted string. - * @return string - * The string to be evaluated. - */ - _variablesViewGetterOrSetterEvalMacro: - function JST__variablesViewGetterOrSetterEvalMacro(aItem, aCurrentString) - { - let propertyObject = aItem.ownerView; - let parentObject = propertyObject.ownerView; - let parent = parentObject.symbolicName; - parentObject._symbolicName = "_self" + parent; - - let result = VariablesView.getterOrSetterEvalMacro.apply(this, arguments); - - parentObject._symbolicName = parent; - - return result; - }, - /** * The property deletion function used by the variables view when a property * is deleted. @@ -3556,144 +3523,7 @@ JSTerm.prototype = { aCallback && aCallback(aResponse); }, - /** - * Adds properties to a variable in the view. Triggered when a variable is - * expanded. It does not expand the variable. - * - * @param object aVar - * The VariablseView Variable instance where the properties get added. - * @param object [aGrip] - * Optional, the object actor grip of the variable. If the grip is not - * provided, then the aVar.value is used as the object actor grip. - */ - _fetchVarProperties: function JST__fetchVarProperties(aVar, aGrip) - { - // Retrieve the properties only once. - if (aVar._fetched) { - return; - } - aVar._fetched = true; - let grip = aGrip || aVar.value; - if (!grip) { - throw new Error("No object actor grip was given for the variable."); - } - - let view = aVar._variablesView; - let actors = this._objectActorsInVariablesViews.get(view); - - function addActorForDescriptor(aGrip) { - if (WebConsoleUtils.isActorGrip(aGrip)) { - actors.add(aGrip.actor); - } - } - - let onNewProperty = (aProperty) => { - if (aProperty.getter || aProperty.setter) { - aProperty.evaluationMacro = this._variablesViewOverrideValueEvalMacro; - let getter = aProperty.get("get"); - let setter = aProperty.get("set"); - if (getter) { - getter.evaluationMacro = this._variablesViewGetterOrSetterEvalMacro; - } - if (setter) { - setter.evaluationMacro = this._variablesViewGetterOrSetterEvalMacro; - } - } - else { - aProperty.evaluationMacro = this._variablesViewSimpleValueEvalMacro; - } - - let grips = [aProperty.value, aProperty.getter, aProperty.setter]; - grips.forEach(addActorForDescriptor); - - let inspectable = !VariablesView.isPrimitive({ value: aProperty.value }); - let longString = WebConsoleUtils.isActorGrip(aProperty.value) && - aProperty.value.type == "longString"; - if (inspectable) { - aProperty.onexpand = this._fetchVarProperties; - } - else if (longString) { - aProperty.onexpand = this._fetchVarLongString; - aProperty.showArrow(); - } - }; - - let client = new GripClient(this.hud.proxy.client, grip); - client.getPrototypeAndProperties((aResponse) => { - let { ownProperties, prototype, safeGetterValues } = aResponse; - let sortable = VariablesView.NON_SORTABLE_CLASSES.indexOf(grip.class) == -1; - - // Merge the safe getter values into one object such that we can use it - // in VariablesView. - for (let name of Object.keys(safeGetterValues)) { - if (name in ownProperties) { - ownProperties[name].getterValue = safeGetterValues[name].getterValue; - ownProperties[name].getterPrototypeLevel = safeGetterValues[name] - .getterPrototypeLevel; - } - else { - ownProperties[name] = safeGetterValues[name]; - } - } - - // Add all the variable properties. - if (ownProperties) { - aVar.addProperties(ownProperties, { - sorted: sortable, - callback: onNewProperty, - }); - } - - // Add the variable's __proto__. - if (prototype && prototype.type != "null") { - let proto = aVar.addProperty("__proto__", { value: prototype }); - onNewProperty(proto); - } - - aVar._retrieved = true; - view.commitHierarchy(); - this.emit("variablesview-fetched", aVar); - }); - }, - - /** - * Fetch the full string for a given variable that displays a long string. - * - * @param object aVar - * The VariablesView Variable instance where the properties get added. - */ - _fetchVarLongString: function JST__fetchVarLongString(aVar) - { - if (aVar._fetched) { - return; - } - aVar._fetched = true; - - let grip = aVar.value; - if (!grip) { - throw new Error("No long string actor grip was given for the variable."); - } - - let client = this.webConsoleClient.longString(grip); - let toIndex = Math.min(grip.length, MAX_LONG_STRING_LENGTH); - client.substring(grip.initial.length, toIndex, (aResponse) => { - if (aResponse.error) { - Cu.reportError("JST__fetchVarLongString substring failure: " + - aResponse.error + ": " + aResponse.message); - return; - } - - aVar.onexpand = null; - aVar.setGrip(grip.initial + aResponse.substring); - aVar.hideArrow(); - aVar._retrieved = true; - - if (toIndex != grip.length) { - this.hud.logWarningAboutStringTooLong(); - } - }); - }, /** * Writes a JS object to the JSTerm outputNode. @@ -4358,11 +4188,7 @@ JSTerm.prototype = { _sidebarDestroy: function JST__sidebarDestroy() { if (this._variablesView) { - let actors = this._objectActorsInVariablesViews.get(this._variablesView); - for (let actor of actors) { - this.hud._releaseObject(actor); - } - actors.clear(); + this._variablesView.controller.releaseActors(); this._variablesView = null; } From 210ecef3b89a6710266c9d5e6a22fa34ae7ea363 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Fri, 14 Jun 2013 10:46:21 -0700 Subject: [PATCH 429/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/d7f1671443c5 Author: Julien Wajsberg Desc: Merge pull request #10367 from lissyx/bug882607 Bug 882607 - Using white-space: pre-wrap for SMS and MMS r=julien ======== https://hg.mozilla.org/integration/gaia-central/rev/e0fd3dfd5c1c Author: Alexandre Lissy Desc: Bug 882607 - Using white-space: pre-wrap for SMS and MMS We also remove Utils.Message.format() which becomes useless. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index a37a35133325..d628944bc3c5 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "6cf49c161c55638f87b788756ec15192f085cd3f", + "revision": "d7f1671443c5751a3f877bd4edc3283b798d3d66", "repo_path": "/integration/gaia-central" } From a0c0f93e4ed611b4adfe16d47bbe9101af6fcb78 Mon Sep 17 00:00:00 2001 From: Steven Michaud Date: Fri, 14 Jun 2013 17:05:55 -0500 Subject: [PATCH 430/615] Bug 877500 - Add a null check so that CFRelease() doesn't crash. r=joshmoz --- .../exthandler/mac/nsOSHelperAppService.mm | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/uriloader/exthandler/mac/nsOSHelperAppService.mm b/uriloader/exthandler/mac/nsOSHelperAppService.mm index 8fc73f07f0bd..8b99923c1eac 100644 --- a/uriloader/exthandler/mac/nsOSHelperAppService.mm +++ b/uriloader/exthandler/mac/nsOSHelperAppService.mm @@ -507,21 +507,23 @@ nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, } CFStringRef cfType = ::CFStringCreateWithCString(NULL, mimeType.get(), kCFStringEncodingUTF8); - CFStringRef cfTypeDesc = NULL; - if (::LSCopyKindStringForMIMEType(cfType, &cfTypeDesc) == noErr) { - nsAutoTArray buffer; - CFIndex typeDescLength = ::CFStringGetLength(cfTypeDesc); - buffer.SetLength(typeDescLength); - ::CFStringGetCharacters(cfTypeDesc, CFRangeMake(0, typeDescLength), - buffer.Elements()); - nsAutoString typeDesc; - typeDesc.Assign(buffer.Elements(), typeDescLength); - mimeInfoMac->SetDescription(typeDesc); + if (cfType) { + CFStringRef cfTypeDesc = NULL; + if (::LSCopyKindStringForMIMEType(cfType, &cfTypeDesc) == noErr) { + nsAutoTArray buffer; + CFIndex typeDescLength = ::CFStringGetLength(cfTypeDesc); + buffer.SetLength(typeDescLength); + ::CFStringGetCharacters(cfTypeDesc, CFRangeMake(0, typeDescLength), + buffer.Elements()); + nsAutoString typeDesc; + typeDesc.Assign(buffer.Elements(), typeDescLength); + mimeInfoMac->SetDescription(typeDesc); + } + if (cfTypeDesc) { + ::CFRelease(cfTypeDesc); + } + ::CFRelease(cfType); } - if (cfTypeDesc) { - ::CFRelease(cfTypeDesc); - } - ::CFRelease(cfType); } PR_LOG(mLog, PR_LOG_DEBUG, ("OS gave us: type '%s' found '%i'\n", mimeType.get(), *aFound)); From 63eccd6385ff581757a3f43171ee4ba038118fbe Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Fri, 14 Jun 2013 15:15:58 -0700 Subject: [PATCH 431/615] Bug 883205 - Add mozsystemmonitor to mozbase; r=ahal --- testing/mozbase/Makefile.in | 1 + testing/mozbase/mozsystemmonitor/README.rst | 13 + .../mozsystemmonitor/__init__.py | 0 .../mozsystemmonitor/resourcemonitor.py | 481 ++++++++++++++++++ .../mozsystemmonitor/test/__init__.py | 0 .../test/test_resource_monitor.py | 154 ++++++ testing/mozbase/mozsystemmonitor/setup.py | 29 ++ testing/mozbase/packages.txt | 1 + 8 files changed, 679 insertions(+) create mode 100644 testing/mozbase/mozsystemmonitor/README.rst create mode 100644 testing/mozbase/mozsystemmonitor/mozsystemmonitor/__init__.py create mode 100644 testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py create mode 100644 testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/__init__.py create mode 100644 testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py create mode 100644 testing/mozbase/mozsystemmonitor/setup.py diff --git a/testing/mozbase/Makefile.in b/testing/mozbase/Makefile.in index c790348ee01d..ee6d65be6ea3 100644 --- a/testing/mozbase/Makefile.in +++ b/testing/mozbase/Makefile.in @@ -25,6 +25,7 @@ MOZBASE_PACKAGES = \ mozrunner \ mozdevice \ moznetwork \ + mozsystemmonitor \ $(NULL) MOZBASE_EXTRAS = \ diff --git a/testing/mozbase/mozsystemmonitor/README.rst b/testing/mozbase/mozsystemmonitor/README.rst new file mode 100644 index 000000000000..65756d44d35d --- /dev/null +++ b/testing/mozbase/mozsystemmonitor/README.rst @@ -0,0 +1,13 @@ +================ +mozsystemmonitor +================ + +mozsystemmonitor contains modules for monitoring a running system. + +SystemResourceMonitor +===================== + +mozsystemmonitor.resourcemonitor.SystemResourceMonitor is class used to +measure system resource usage. It is useful to get a handle on what an +overall system is doing. + diff --git a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/__init__.py b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py new file mode 100644 index 000000000000..a7013c7f329a --- /dev/null +++ b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/resourcemonitor.py @@ -0,0 +1,481 @@ +# 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/. + +import multiprocessing +import sys +import time + +try: + import psutil +except ImportError: + psutil = None + +from collections import ( + OrderedDict, + namedtuple, +) + +from contextlib import contextmanager + + +def _collect(pipe, poll_interval): + """Collects system metrics. + + This is the main function for the background process. It collects + data then forwards it on a pipe until told to stop. + """ + + data = [] + + # Establish initial values. + + # We should ideally use a monotonic clock. However, Python 2.7 doesn't + # make a monotonic clock available on all platforms. Python 3.3 does! + last_time = time.time() + io_last = psutil.disk_io_counters() + cpu_last = psutil.cpu_times(True) + swap_last = psutil.swap_memory() + psutil.cpu_percent(None, True) + + sin_index = swap_last._fields.index('sin') + sout_index = swap_last._fields.index('sout') + + sleep_interval = poll_interval + + while not pipe.poll(sleep_interval): + io = psutil.disk_io_counters() + cpu_times = psutil.cpu_times(True) + cpu_percent = psutil.cpu_percent(None, True) + virt_mem = psutil.virtual_memory() + swap_mem = psutil.swap_memory() + measured_end_time = time.time() + + # TODO Does this wrap? At 32 bits? At 64 bits? + # TODO Consider patching "delta" API to upstream. + io_diff = [v - io_last[i] for i, v in enumerate(io)] + io_last = io + + cpu_diff = [] + for core, values in enumerate(cpu_times): + cpu_diff.append([v - cpu_last[core][i] for i, v in + enumerate(values)]) + + cpu_last = cpu_times + + swap_entry = list(swap_mem) + swap_entry[sin_index] = swap_mem.sin - swap_last.sin + swap_entry[sout_index] = swap_mem.sout - swap_last.sout + swap_last = swap_mem + + data.append((last_time, measured_end_time, io_diff, cpu_diff, + cpu_percent, list(virt_mem), swap_entry)) + + collection_overhead = time.time() - last_time - poll_interval + last_time = measured_end_time + sleep_interval = max(0, poll_interval - collection_overhead) + + for entry in data: + pipe.send(entry) + + pipe.send(('done', None, None, None, None, None, None)) + pipe.close() + sys.exit(0) + + +SystemResourceUsage = namedtuple('SystemResourceUsage', + ['start', 'end', 'cpu_times', 'cpu_percent', 'io', 'virt', 'swap']) + + +class SystemResourceMonitor(object): + """Measures system resources. + + Each instance measures system resources from the time it is started + until it is finished. It does this on a separate process so it doesn't + impact execution of the main Python process. + + Each instance is a one-shot instance. It cannot be used to record multiple + durations. + + Aside from basic data gathering, the class supports basic analysis + capabilities. You can query for data between ranges. You can also tell it + when certain events occur and later grab data relevant to those events or + plot those events on a timeline. + + The resource monitor works by periodically polling the state of the + system. By default, it polls every second. This can be adjusted depending + on the required granularity of the data and considerations for probe + overhead. It tries to probe at the interval specified. However, variations + should be expected. Fast and well-behaving systems should experience + variations in the 1ms range. Larger variations may exist if the system is + under heavy load or depending on how accurate socket polling is on your + system. + + In its current implementation, data is not available until collection has + stopped. This may change in future iterations. + + Usage + ===== + + monitor = SystemResourceMonitor() + monitor.start() + + # Record that a single event in time just occurred. + foo.do_stuff() + monitor.record_event('foo_did_stuff') + + # Record that we're about to perform a possibly long-running event. + with monitor.phase('long_job'): + foo.do_long_running_job() + + # Stop recording. Currently we need to stop before data is available. + monitor.stop() + + # Obtain the raw data for the entire probed range. + print('CPU Usage:') + for core in monitor.aggregate_cpu(): + print(core) + + # We can also request data corresponding to a specific phase. + for data in monitor.phase_usage('long_job'): + print(data.cpu_percent) + """ + + # The interprocess communication is complicated enough to warrant + # explanation. To work around the Python GIL, we launch a separate + # background process whose only job is to collect metrics. If we performed + # collection in the main process, the polling interval would be + # inconsistent if a long-running function were on the stack. Since the + # child process is independent of the instantiating process, data + # collection should be evenly spaced. + # + # As the child process collects data, it buffers it locally. When + # collection stops, it flushes all that data to a pipe to be read by + # the parent process. + + def __init__(self, poll_interval=1.0): + """Instantiate a system resource monitor instance. + + The instance is configured with a poll interval. This is the interval + between samples, in float seconds. + """ + self.start_time = None + self.end_time = None + + self.events = [] + self.phases = OrderedDict() + + self._active_phases = {} + + self._running = False + self._stopped = False + + if psutil is None: + return + + cpu_percent = psutil.cpu_percent(0.0, True) + cpu_times = psutil.cpu_times(False) + io = psutil.disk_io_counters() + virt = psutil.virtual_memory() + swap = psutil.swap_memory() + + self._cpu_cores = len(cpu_percent) + self._cpu_times_type = type(cpu_times) + self._cpu_times_len = len(cpu_times) + self._io_type = type(io) + self._io_len = len(io) + self._virt_type = type(virt) + self._virt_len = len(virt) + self._swap_type = type(swap) + self._swap_len = len(swap) + + self._pipe, child_pipe = multiprocessing.Pipe(True) + + self._process = multiprocessing.Process(None, _collect, + args=(child_pipe, poll_interval)) + + def __del__(self): + if self._running: + self._pipe.send(('terminate',)) + self._process.join() + + # Methods to control monitoring. + + def start(self): + """Start measuring system-wide CPU resource utilization. + + You should only call this once per instance. + """ + if psutil is None: + return + + self._running = True + self._process.start() + + def stop(self): + """Stop measuring system-wide CPU resource utilization. + + You should call this if and only if you have called start(). You should + always pair a stop() with a start(). + + Currently, data is not available until you call stop(). + """ + if psutil is None: + self._stopped = True + return + + assert self._running + assert not self._stopped + + self._pipe.send(('terminate')) + self._running = False + self._stopped = True + + self.measurements = [] + + done = False + + while self._pipe.poll(1): + start_time, end_time, io_diff, cpu_diff, cpu_percent, virt_mem, \ + swap_mem = self._pipe.recv() + + if start_time == 'done': + done = True + continue + + io = self._io_type(*io_diff) + virt = self._virt_type(*virt_mem) + swap = self._swap_type(*swap_mem) + cpu_times = [self._cpu_times_type(*v) for v in cpu_diff] + + self.measurements.append(SystemResourceUsage(start_time, end_time, + cpu_times, cpu_percent, io, virt, swap)) + + self._process.join() + assert done + + if len(self.measurements): + self.start_time = self.measurements[0].start + self.end_time = self.measurements[-1].end + + # Methods to record events alongside the monitored data. + + def record_event(self, name): + """Record an event as occuring now. + + Events are actions that occur at a specific point in time. If you are + looking for an action that has a duration, see the phase API below. + """ + self.events.append((time.time(), name)) + + @contextmanager + def phase(self, name): + """Context manager for recording an active phase.""" + self.begin_phase(name) + yield + self.finish_phase(name) + + def begin_phase(self, name): + """Record the start of a phase. + + Phases are actions that have a duration. Multiple phases can be active + simultaneously. Phases can be closed in any order. + + Keep in mind that if phases occur in parallel, it will become difficult + to isolate resource utilization specific to individual phases. + """ + assert name not in self._active_phases + + self._active_phases[name] = time.time() + + def finish_phase(self, name): + """Record the end of a phase.""" + + assert name in self._active_phases + + phase = (self._active_phases[name], time.time()) + self.phases[name] = phase + del self._active_phases[name] + + return phase[1] - phase[0] + + # Methods to query data. + + def range_usage(self, start=None, end=None): + """Obtain the usage data falling within the given time range. + + This is a generator of SystemResourceUsage. + + If no time range bounds are given, all data is returned. + """ + if not self._stopped or self.start_time is None: + return + + if start is None: + start = self.start_time + + if end is None: + end = self.end_time + + for entry in self.measurements: + if entry.start < start: + continue + + if entry.end > end: + break + + yield entry + + def phase_usage(self, phase): + """Obtain usage data for a specific phase. + + This is a generator of SystemResourceUsage. + """ + time_start, time_end = self.phases[phase] + + return self.range_usage(time_start, time_end) + + def between_events_usage(self, start_event, end_event): + """Obtain usage data between two point events. + + This is a generator of SystemResourceUsage. + """ + start_time = None + end_time = None + + for t, name in self.events: + if name == start_event: + start_time = t + elif name == end_event: + end_time = t + + if start_time is None: + raise Exception('Could not find start event: %s' % start_event) + + if end_time is None: + raise Exception('Could not find end event: %s' % end_event) + + return self.range_usage(start_time, end_time) + + def aggregate_cpu_percent(self, start=None, end=None, phase=None, + per_cpu=True): + """Obtain the aggregate CPU percent usage for a range. + + Returns a list of floats representing average CPU usage percentage per + core if per_cpu is True (the default). If per_cpu is False, return a + single percentage value. + + By default this will return data for the entire instrumented interval. + If phase is defined, data for a named phase will be returned. If start + and end are defined, these times will be fed into range_usage(). + """ + cpu = [[] for i in range(0, self._cpu_cores)] + + if phase: + data = self.phase_usage(phase) + else: + data = self.range_usage(start, end) + + for usage in data: + for i, v in enumerate(usage.cpu_percent): + cpu[i].append(v) + + samples = len(cpu[0]) + + if not samples: + return None + + if per_cpu: + return [sum(x) / samples for x in cpu] + + cores = [sum(x) for x in cpu] + + return sum(cores) / len(cpu) / samples + + def aggregate_cpu_times(self, start=None, end=None, phase=None, + per_cpu=True): + """Obtain the aggregate CPU times for a range. + + If per_cpu is True (the default), this returns a list of named tuples. + Each tuple is as if it were returned by psutil.cpu_times(). If per_cpu + is False, this returns a single named tuple of the aforementioned type. + """ + empty = [0 for i in range(0, self._cpu_times_len)] + cpu = [list(empty) for i in range(0, self._cpu_cores)] + + if phase: + data = self.phase_usage(phase) + else: + data = self.range_usage(start, end) + + for usage in data: + for i, core_values in enumerate(usage.cpu_times): + for j, v in enumerate(core_values): + cpu[i][j] += v + + if per_cpu: + return [self._cpu_times_type(*v) for v in cpu] + + sums = list(empty) + for core in cpu: + for i, v in enumerate(core): + sums[i] += v + + return self._cpu_times_type(*sums) + + def aggregate_io(self, start=None, end=None, phase=None): + """Obtain aggregate I/O counters for a range. + + Returns an iostat named tuple from psutil. + """ + + io = [0 for i in range(self._io_len)] + + if phase: + data = self.phase_usage(phase) + else: + data = self.range_usage(start, end) + + for usage in data: + for i, v in enumerate(usage.io): + io[i] += v + + return self._io_type(*io) + + def min_memory_available(self, start=None, end=None, phase=None): + """Return the minimum observed available memory number from a range. + + Returns long bytes of memory available. + + See psutil for notes on how this is calculated. + """ + if phase: + data = self.phase_usage(phase) + else: + data = self.range_usage(start, end) + + values = [] + + for usage in data: + values.append(usage.virt.available) + + return min(values) + + def max_memory_percent(self, start=None, end=None, phase=None): + """Returns the maximum percentage of system memory used. + + Returns a float percentage. 1.00 would mean all system memory was in + use at one point. + """ + if phase: + data = self.phase_usage(phase) + else: + data = self.range_usage(start, end) + + values = [] + + for usage in data: + values.append(usage.virt.percent) + + return max(values) + diff --git a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/__init__.py b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py new file mode 100644 index 000000000000..9273d99e0af7 --- /dev/null +++ b/testing/mozbase/mozsystemmonitor/mozsystemmonitor/test/test_resource_monitor.py @@ -0,0 +1,154 @@ +# 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/. + +import multiprocessing +import tempfile +import time +import unittest + +try: + import psutil +except ImportError: + psutil = None + +from mozsystemmonitor.resourcemonitor import ( + SystemResourceMonitor, + SystemResourceUsage, +) + + +@unittest.skipIf(psutil is None, 'Resource monitor requires psutil.') +class TestResourceMonitor(unittest.TestCase): + def test_basic(self): + monitor = SystemResourceMonitor(poll_interval=0.5) + + monitor.start() + time.sleep(3) + + monitor.stop() + + data = list(monitor.range_usage()) + self.assertGreater(len(data), 3) + + self.assertIsInstance(data[0], SystemResourceUsage) + + def test_empty(self): + monitor = SystemResourceMonitor(poll_interval=2.0) + monitor.start() + monitor.stop() + + data = list(monitor.range_usage()) + self.assertEqual(len(data), 0) + + def test_phases(self): + monitor = SystemResourceMonitor(poll_interval=0.25) + + monitor.start() + time.sleep(1) + + with monitor.phase('phase1'): + time.sleep(1) + + with monitor.phase('phase2'): + time.sleep(1) + + monitor.stop() + + self.assertEqual(len(monitor.phases), 2) + self.assertEqual(['phase2', 'phase1'], monitor.phases.keys()) + + all = list(monitor.range_usage()) + data1 = list(monitor.phase_usage('phase1')) + data2 = list(monitor.phase_usage('phase2')) + + self.assertGreater(len(all), len(data1)) + self.assertGreater(len(data1), len(data2)) + + # This could fail if time.time() takes more than 0.1s. It really + # shouldn't. + self.assertAlmostEqual(data1[-1].end, data2[-1].end, delta=0.25) + + def test_no_data(self): + monitor = SystemResourceMonitor() + + data = list(monitor.range_usage()) + self.assertEqual(len(data), 0) + + def test_events(self): + monitor = SystemResourceMonitor(poll_interval=0.25) + + monitor.start() + time.sleep(0.5) + + t0 = time.time() + monitor.record_event('t0') + time.sleep(0.5) + + t1 = time.time() + monitor.record_event('t1') + time.sleep(0.5) + monitor.stop() + + events = monitor.events + self.assertEqual(len(events), 2) + + event = events[0] + + self.assertEqual(event[1], 't0') + self.assertAlmostEqual(event[0], t0, delta=0.25) + + data = list(monitor.between_events_usage('t0', 't1')) + self.assertGreater(len(data), 0) + + def test_aggregate_cpu(self): + monitor = SystemResourceMonitor(poll_interval=0.25) + + monitor.start() + time.sleep(1) + monitor.stop() + + values = monitor.aggregate_cpu_percent() + self.assertIsInstance(values, list) + self.assertEqual(len(values), multiprocessing.cpu_count()) + for v in values: + self.assertIsInstance(v, float) + + value = monitor.aggregate_cpu_percent(per_cpu=False) + self.assertIsInstance(value, float) + + values = monitor.aggregate_cpu_times() + self.assertIsInstance(values, list) + self.assertGreater(len(values), 0) + self.assertTrue(hasattr(values[0], 'user')) + + t = type(values[0]) + + value = monitor.aggregate_cpu_times(per_cpu=False) + self.assertIsInstance(value, t) + + def test_aggregate_io(self): + monitor = SystemResourceMonitor(poll_interval=0.25) + + # There's really no easy way to ensure I/O occurs. For all we know + # reads and writes will all be serviced by the page cache. + monitor.start() + time.sleep(1.0) + monitor.stop() + + values = monitor.aggregate_io() + self.assertTrue(hasattr(values, 'read_count')) + + def test_memory(self): + monitor = SystemResourceMonitor(poll_interval=0.25) + + monitor.start() + time.sleep(1.0) + monitor.stop() + + v = monitor.min_memory_available() + self.assertIsInstance(v, long) + + v = monitor.max_memory_percent() + self.assertIsInstance(v, float) + diff --git a/testing/mozbase/mozsystemmonitor/setup.py b/testing/mozbase/mozsystemmonitor/setup.py new file mode 100644 index 000000000000..c352e0ddc0a5 --- /dev/null +++ b/testing/mozbase/mozsystemmonitor/setup.py @@ -0,0 +1,29 @@ +# 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/. + +import os + +from setuptools import setup + +PACKAGE_VERSION = '0.0' + +try: + pwd = os.path.dirname(os.path.abspath(__file__)) + description = open(os.path.join(here, 'README.rst')).read() +except: + description = '' + +setup( + name='mozsystemmonitor', + description='Monitor system resource usage.', + long_description=description, + license='MPL 2.0', + keywords='mozilla', + author='Mozilla Automation and Tools Team', + author_email='tools@lists.mozilla.org', + url='https://wiki.mozilla.org/Auto-tools/Projects/Mozbase', + packages=['mozsystemmonitor'], + version=PACKAGE_VERSION, + install_requires=['psutil >= 0.7.1'], +) diff --git a/testing/mozbase/packages.txt b/testing/mozbase/packages.txt index 027d2f5b86f8..56b022d5b493 100644 --- a/testing/mozbase/packages.txt +++ b/testing/mozbase/packages.txt @@ -11,4 +11,5 @@ moznetwork.pth:testing/mozbase/moznetwork mozprocess.pth:testing/mozbase/mozprocess mozprofile.pth:testing/mozbase/mozprofile mozrunner.pth:testing/mozbase/mozrunner +mozsystemmonitor.pth:testing/mozbase/mozsystemmonitor moztest.pth:testing/mozbase/moztest From 6a87e374118b434a17e27bd5b53dd65b7ab8890a Mon Sep 17 00:00:00 2001 From: Kyle Machulis Date: Fri, 14 Jun 2013 18:29:20 -0700 Subject: [PATCH 432/615] Bug 882443: Check for connection before asserting in BluetoothA2dpManager::Disconnect; r=gyeh r=shuang --- dom/bluetooth/BluetoothA2dpManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/bluetooth/BluetoothA2dpManager.cpp b/dom/bluetooth/BluetoothA2dpManager.cpp index fdfd1ac9e410..33a7f274445f 100644 --- a/dom/bluetooth/BluetoothA2dpManager.cpp +++ b/dom/bluetooth/BluetoothA2dpManager.cpp @@ -203,13 +203,13 @@ BluetoothA2dpManager::Connect(const nsAString& aDeviceAddress) void BluetoothA2dpManager::Disconnect() { - MOZ_ASSERT(!mDeviceAddress.IsEmpty()); - if (!mConnected) { NS_WARNING("BluetoothA2dpManager has been disconnected"); return; } + MOZ_ASSERT(!mDeviceAddress.IsEmpty()); + BluetoothService* bs = BluetoothService::Get(); NS_ENSURE_TRUE_VOID(bs); bs->SendSinkMessage(mDeviceAddress, NS_LITERAL_STRING("Disconnect")); From 826c3c1dc422fde49863e318e97a5707e0b709e1 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Fri, 14 Jun 2013 22:23:21 -0400 Subject: [PATCH 433/615] Bug 809306 - Fix Win64 bustage. --- js/src/ion/x64/Assembler-x64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/ion/x64/Assembler-x64.h b/js/src/ion/x64/Assembler-x64.h index 82874703737b..935e23e7b9f5 100644 --- a/js/src/ion/x64/Assembler-x64.h +++ b/js/src/ion/x64/Assembler-x64.h @@ -87,10 +87,10 @@ static const MOZ_CONSTEXPR Register CallTempReg6 = rbp; // Different argument registers for WIN64 #if defined(_WIN64) static const MOZ_CONSTEXPR Register IntArgReg0 = rcx; -static constMOZ_CONSTEXPRconstexpr Register IntArgReg1 = rdx; +static const MOZ_CONSTEXPR Register IntArgReg1 = rdx; static const MOZ_CONSTEXPR Register IntArgReg2 = r8; static const MOZ_CONSTEXPR Register IntArgReg3 = r9; -static constMOZ_CONSTEXPRuint32_t NumIntArgRegs = 4; +static const MOZ_CONSTEXPR uint32_t NumIntArgRegs = 4; static const MOZ_CONSTEXPR Register IntArgRegs[NumIntArgRegs] = { rcx, rdx, r8, r9 }; static const MOZ_CONSTEXPR Register CallTempNonArgRegs[] = { rax, rdi, rbx, rsi }; From ee25bcfab1582c9579b445a255ed4401a718bcb5 Mon Sep 17 00:00:00 2001 From: ffxbld Date: Sat, 15 Jun 2013 03:23:04 -0700 Subject: [PATCH 434/615] No bug, Automated blocklist update from host bld-linux64-ix-004 - a=blocklist-update --- browser/app/blocklist.xml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/browser/app/blocklist.xml b/browser/app/blocklist.xml index 7384c43a0637..3f72049c380c 100644 --- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,5 +1,5 @@ - + @@ -222,6 +222,10 @@ + + + + @@ -253,6 +257,10 @@ + + + + @@ -803,7 +811,7 @@ - + @@ -930,6 +938,9 @@ + + + From 2606c1a4de82d542341eda6ba9cadbb9f5e4a78b Mon Sep 17 00:00:00 2001 From: ffxbld Date: Sat, 15 Jun 2013 03:25:15 -0700 Subject: [PATCH 435/615] No bug, Automated HSTS preload list update from host bld-linux64-ix-037 - a=hsts-update --- security/manager/boot/src/nsSTSPreloadList.errors | 3 +++ security/manager/boot/src/nsSTSPreloadList.inc | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/security/manager/boot/src/nsSTSPreloadList.errors b/security/manager/boot/src/nsSTSPreloadList.errors index 424209b39d22..0674597fdc5c 100644 --- a/security/manager/boot/src/nsSTSPreloadList.errors +++ b/security/manager/boot/src/nsSTSPreloadList.errors @@ -19,6 +19,7 @@ code.google.com: did not receive HSTS header codereview.appspot.com: did not receive HSTS header codereview.chromium.org: did not receive HSTS header crypto.is: did not receive HSTS header +csawctf.poly.edu: could not connect to host dl.google.com: did not receive HSTS header docs.google.com: did not receive HSTS header drive.google.com: did not receive HSTS header @@ -26,6 +27,7 @@ dropcam.com: did not receive HSTS header emailprivacytester.com: max-age too low: 8640000 encrypted.google.com: did not receive HSTS header epoxate.com: max-age too low: 259200 +factor.cc: could not connect to host fatzebra.com.au: did not receive HSTS header fj.simple.com: did not receive HSTS header gmail.com: did not receive HSTS header @@ -45,6 +47,7 @@ kiwiirc.com: max-age too low: 5256000 ledgerscope.net: max-age too low: 86400 linx.net: did not receive HSTS header lists.mayfirst.org: did not receive HSTS header +logentries.com: did not receive HSTS header mail.google.com: did not receive HSTS header makeyourlaws.org: could not connect to host market.android.com: did not receive HSTS header diff --git a/security/manager/boot/src/nsSTSPreloadList.inc b/security/manager/boot/src/nsSTSPreloadList.inc index 8191f56249ba..1300e28caa6a 100644 --- a/security/manager/boot/src/nsSTSPreloadList.inc +++ b/security/manager/boot/src/nsSTSPreloadList.inc @@ -8,7 +8,7 @@ /*****************************************************************************/ #include "mozilla/StandardInteger.h" -const PRTime gPreloadListExpirationTime = INT64_C(1381573044340000); +const PRTime gPreloadListExpirationTime = INT64_C(1382177697222000); class nsSTSPreload { @@ -30,11 +30,13 @@ static const nsSTSPreload kSTSPreloadList[] = { { "carezone.com", false }, { "check.torproject.org", false }, { "cloudsecurityalliance.org", true }, + { "conformal.com", true }, { "controlcenter.gigahost.dk", true }, { "crate.io", true }, { "crm.onlime.ch", false }, { "crypto.cat", false }, { "csawctf.poly.edu", true }, + { "cyphertite.com", true }, { "developer.mydigipass.com", false }, { "dist.torproject.org", false }, { "dm.lookout.com", false }, @@ -57,9 +59,9 @@ static const nsSTSPreload kSTSPreloadList[] = { { "library.linode.com", false }, { "linode.com", false }, { "lockify.com", true }, - { "logentries.com", false }, { "login.persona.org", true }, { "login.sapo.pt", true }, + { "logotype.se", true }, { "lookout.com", false }, { "luneta.nearbuysystems.com", false }, { "makeyourlaws.org", false }, From 5dcb2e673f257a0a8e0cbf71ba79544e782029d7 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Sat, 15 Jun 2013 07:40:53 -0700 Subject: [PATCH 436/615] Back out f691f7abfe33 (No bug) Automated HSTS preload list update that broke HSTS preload --- security/manager/boot/src/nsSTSPreloadList.errors | 3 --- security/manager/boot/src/nsSTSPreloadList.inc | 6 ++---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/security/manager/boot/src/nsSTSPreloadList.errors b/security/manager/boot/src/nsSTSPreloadList.errors index 0674597fdc5c..424209b39d22 100644 --- a/security/manager/boot/src/nsSTSPreloadList.errors +++ b/security/manager/boot/src/nsSTSPreloadList.errors @@ -19,7 +19,6 @@ code.google.com: did not receive HSTS header codereview.appspot.com: did not receive HSTS header codereview.chromium.org: did not receive HSTS header crypto.is: did not receive HSTS header -csawctf.poly.edu: could not connect to host dl.google.com: did not receive HSTS header docs.google.com: did not receive HSTS header drive.google.com: did not receive HSTS header @@ -27,7 +26,6 @@ dropcam.com: did not receive HSTS header emailprivacytester.com: max-age too low: 8640000 encrypted.google.com: did not receive HSTS header epoxate.com: max-age too low: 259200 -factor.cc: could not connect to host fatzebra.com.au: did not receive HSTS header fj.simple.com: did not receive HSTS header gmail.com: did not receive HSTS header @@ -47,7 +45,6 @@ kiwiirc.com: max-age too low: 5256000 ledgerscope.net: max-age too low: 86400 linx.net: did not receive HSTS header lists.mayfirst.org: did not receive HSTS header -logentries.com: did not receive HSTS header mail.google.com: did not receive HSTS header makeyourlaws.org: could not connect to host market.android.com: did not receive HSTS header diff --git a/security/manager/boot/src/nsSTSPreloadList.inc b/security/manager/boot/src/nsSTSPreloadList.inc index 1300e28caa6a..8191f56249ba 100644 --- a/security/manager/boot/src/nsSTSPreloadList.inc +++ b/security/manager/boot/src/nsSTSPreloadList.inc @@ -8,7 +8,7 @@ /*****************************************************************************/ #include "mozilla/StandardInteger.h" -const PRTime gPreloadListExpirationTime = INT64_C(1382177697222000); +const PRTime gPreloadListExpirationTime = INT64_C(1381573044340000); class nsSTSPreload { @@ -30,13 +30,11 @@ static const nsSTSPreload kSTSPreloadList[] = { { "carezone.com", false }, { "check.torproject.org", false }, { "cloudsecurityalliance.org", true }, - { "conformal.com", true }, { "controlcenter.gigahost.dk", true }, { "crate.io", true }, { "crm.onlime.ch", false }, { "crypto.cat", false }, { "csawctf.poly.edu", true }, - { "cyphertite.com", true }, { "developer.mydigipass.com", false }, { "dist.torproject.org", false }, { "dm.lookout.com", false }, @@ -59,9 +57,9 @@ static const nsSTSPreload kSTSPreloadList[] = { { "library.linode.com", false }, { "linode.com", false }, { "lockify.com", true }, + { "logentries.com", false }, { "login.persona.org", true }, { "login.sapo.pt", true }, - { "logotype.se", true }, { "lookout.com", false }, { "luneta.nearbuysystems.com", false }, { "makeyourlaws.org", false }, From f74f25a8b2dee498a0f4c13e025e11943bce1aec Mon Sep 17 00:00:00 2001 From: Dave Camp Date: Sat, 15 Jun 2013 12:10:23 -0700 Subject: [PATCH 437/615] Bug 866306 - Add a library to make devtools protocol interaction a bit easier - fix xpcshell tests, r=orange --- .../server/tests/unit/test_protocol_longstring.js | 9 ++++++--- .../devtools/server/tests/unit/test_protocol_simple.js | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/toolkit/devtools/server/tests/unit/test_protocol_longstring.js b/toolkit/devtools/server/tests/unit/test_protocol_longstring.js index 700460234c0a..e2dc16335562 100644 --- a/toolkit/devtools/server/tests/unit/test_protocol_longstring.js +++ b/toolkit/devtools/server/tests/unit/test_protocol_longstring.js @@ -87,7 +87,7 @@ function run_test() DebuggerServer.init(() => true); let trace = connectPipeTracing(); let client = new DebuggerClient(trace); - let rootClient = RootFront(client); + let rootClient; let strfront = null; @@ -96,10 +96,13 @@ function run_test() do_check_eq(rootClient.__poolMap.size, size + 1); } - // Root actor has no children yet. - expectRootChildren(0); client.connect((applicationType, traits) => { + rootClient = RootFront(client); + + // Root actor has no children yet. + expectRootChildren(0); + trace.expectReceive({"from":"","applicationType":"xpcshell-tests","traits":[]}); do_check_eq(applicationType, "xpcshell-tests"); rootClient.shortString().then(ret => { diff --git a/toolkit/devtools/server/tests/unit/test_protocol_simple.js b/toolkit/devtools/server/tests/unit/test_protocol_simple.js index 70525543717c..b1be4c78e4fd 100644 --- a/toolkit/devtools/server/tests/unit/test_protocol_simple.js +++ b/toolkit/devtools/server/tests/unit/test_protocol_simple.js @@ -169,12 +169,13 @@ function run_test() check_except(() => protocol.types.getType("unknown:number")); let trace = connectPipeTracing(); let client = new DebuggerClient(trace); - let rootClient = RootFront(client); + let rootClient; client.connect((applicationType, traits) => { trace.expectReceive({"from":"","applicationType":"xpcshell-tests","traits":[]}); do_check_eq(applicationType, "xpcshell-tests"); + rootClient = RootFront(client); rootClient.simpleReturn().then(ret => { trace.expectSend({"type":"simpleReturn","to":""}); From bd0240af828fd4d1de56c118bbe5b21e520c3875 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Sun, 16 Jun 2013 06:16:22 -0700 Subject: [PATCH 438/615] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/98f8d19dee9d Author: Arthur Chen Desc: Merge pull request #10261 from crh0716/873917 Bug 873917 - Use new request confirming message ======== https://hg.mozilla.org/integration/gaia-central/rev/14735567926c Author: crh0716 Desc: Bug 873917 - Use new request confirming message --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d628944bc3c5..d36449ff5715 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "d7f1671443c5751a3f877bd4edc3283b798d3d66", + "revision": "98f8d19dee9d4808e414f5811c0db09afe6adc4a", "repo_path": "/integration/gaia-central" } From e8555b91b51fd4fbd00f3a5c99e029b09d535ee1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 16 Jun 2013 18:12:35 -0700 Subject: [PATCH 439/615] Bug 883691 - Fix some simple clang warnings in SpiderMonkey. r=bhackett. --HG-- extra : rebase_source : 168fe0710a42ebf3f90c14ecb12de32305987586 --- js/src/frontend/Parser.cpp | 3 --- js/src/ion/Lowering.cpp | 2 +- js/src/ion/ParallelFunctions.cpp | 4 ++-- js/src/ion/shared/CodeGenerator-x86-shared.cpp | 2 +- js/src/vm/RegExpObject.cpp | 2 ++ 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index bd9a20930127..88ecb4d22433 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3505,7 +3505,6 @@ Parser::switchStatement() while ((tt = tokenStream.getToken()) != TOK_RC) { uint32_t caseBegin = tokenStream.currentToken().pos.begin; - ParseNodeKind caseKind; Node caseExpr; switch (tt) { case TOK_DEFAULT: @@ -3514,12 +3513,10 @@ Parser::switchStatement() return null(); } seenDefault = true; - caseKind = PNK_DEFAULT; caseExpr = null(); break; case TOK_CASE: - caseKind = PNK_CASE; caseExpr = expr(); if (!caseExpr) return null(); diff --git a/js/src/ion/Lowering.cpp b/js/src/ion/Lowering.cpp index d5ef296fe055..0c5797160bf3 100644 --- a/js/src/ion/Lowering.cpp +++ b/js/src/ion/Lowering.cpp @@ -1395,7 +1395,7 @@ bool LIRGenerator::visitToDouble(MToDouble *convert) { MDefinition *opd = convert->input(); - MToDouble::ConversionKind conversion = convert->conversion(); + mozilla::DebugOnly conversion = convert->conversion(); switch (opd->type()) { case MIRType_Value: diff --git a/js/src/ion/ParallelFunctions.cpp b/js/src/ion/ParallelFunctions.cpp index f05894ac1490..22f7310c3639 100644 --- a/js/src/ion/ParallelFunctions.cpp +++ b/js/src/ion/ParallelFunctions.cpp @@ -425,11 +425,11 @@ ion::PropagateParallelAbort(JSScript *outermostScript, void ion::ParCallToUncompiledScript(JSFunction *func) { - static const int max_bound_function_unrolling = 5; - JS_ASSERT(InParallelSection()); #ifdef DEBUG + static const int max_bound_function_unrolling = 5; + if (func->hasScript()) { JSScript *script = func->nonLazyScript(); Spew(SpewBailouts, "Call to uncompiled script: %p:%s:%d", diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index f75e02808f70..1c74bcaae480 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -684,7 +684,7 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI *ins) { Register lhs = ToRegister(ins->numerator()); Register lhsCopy = ToRegister(ins->numeratorCopy()); - Register output = ToRegister(ins->output()); + mozilla::DebugOnly output = ToRegister(ins->output()); int32_t shift = ins->shift(); // We use defineReuseInput so these should always be the same, which is diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index b46fb9205f82..087ec0ddaef0 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -581,7 +581,9 @@ RegExpShared::executeMatchOnly(JSContext *cx, const jschar *chars, size_t length if (!compileMatchOnlyIfNecessary(cx)) return RegExpRunStatus_Error; +#ifdef DEBUG const size_t origLength = length; +#endif size_t start = *lastIndex; size_t displacement = 0; From e3c139cd0fbf6f636588c6465d3388fc1b3b6872 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 16 Jun 2013 16:11:24 -0700 Subject: [PATCH 440/615] Bug 881579 - Use the canonical #ifndef wrapper form in SpiderMonkey headers so that GCC and clang can avoid including them more than once per compilation unit. r=benjamin. --HG-- extra : rebase_source : f9d2b33defe07837da4828a57c66fe0ea6772bae --- js/src/assembler/wtf/Assertions.h | 238 +------------------------ js/src/gc/StoreBuffer.h | 6 +- js/src/ion/AsmJS.h | 2 +- js/src/ion/AsmJSModule.h | 6 +- js/src/ion/BaselineCompiler.h | 8 +- js/src/ion/BaselineFrame-inl.h | 8 +- js/src/ion/BaselineFrame.h | 8 +- js/src/ion/BaselineFrameInfo.h | 8 +- js/src/ion/BaselineHelpers.h | 7 +- js/src/ion/BaselineIC.h | 8 +- js/src/ion/BaselineInspector.h | 8 +- js/src/ion/BaselineJIT.h | 8 +- js/src/ion/BaselineRegisters.h | 8 +- js/src/ion/CompilerRoot.h | 6 +- js/src/ion/ExecutionModeInlines.h | 10 +- js/src/ion/Ion.h | 6 +- js/src/ion/IonBuilder.h | 6 +- js/src/ion/IonCompartment.h | 6 +- js/src/ion/IonFrameIterator-inl.h | 6 +- js/src/ion/IonFrameIterator.h | 6 +- js/src/ion/IonFrames-inl.h | 6 +- js/src/ion/IonFrames.h | 6 +- js/src/ion/IonMacroAssembler.h | 6 +- js/src/ion/arm/BaselineHelpers-arm.h | 8 +- js/src/ion/arm/BaselineRegisters-arm.h | 8 +- js/src/ion/x64/BaselineHelpers-x64.h | 8 +- js/src/ion/x64/BaselineRegisters-x64.h | 8 +- js/src/ion/x86/BaselineHelpers-x86.h | 8 +- js/src/ion/x86/BaselineRegisters-x86.h | 8 +- js/src/jsoplengen.cpp | 4 + js/src/vm/ScopeObject-inl.h | 2 +- js/src/vm/Stack-inl.h | 1 + 32 files changed, 158 insertions(+), 284 deletions(-) diff --git a/js/src/assembler/wtf/Assertions.h b/js/src/assembler/wtf/Assertions.h index 29a4f10f7e59..f33619e9f5e6 100644 --- a/js/src/assembler/wtf/Assertions.h +++ b/js/src/assembler/wtf/Assertions.h @@ -46,241 +46,5 @@ #define CRASH() MOZ_CRASH() #define COMPILE_ASSERT(exp, name) MOZ_STATIC_ASSERT(exp, #name) -#endif +#endif // WTF_Assertions_h -#if 0 -/* - no namespaces because this file has to be includable from C and Objective-C - - Note, this file uses many GCC extensions, but it should be compatible with - C, Objective C, C++, and Objective C++. - - For non-debug builds, everything is disabled by default. - Defining any of the symbols explicitly prevents this from having any effect. - - MSVC7 note: variadic macro support was added in MSVC8, so for now we disable - those macros in MSVC7. For more info, see the MSDN document on variadic - macros here: - - http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx -*/ - -#include "Platform.h" - -#if WTF_COMPILER_MSVC -#include -#else -#include -#endif - -#if WTF_OS_SYMBIAN -#include -#include -#endif - -#ifdef NDEBUG -#define ASSERTIONS_DISABLED_DEFAULT 1 -#else -#define ASSERTIONS_DISABLED_DEFAULT 0 -#endif - -#ifndef ASSERT_DISABLED -#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef ASSERT_ARG_DISABLED -#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef FATAL_DISABLED -#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef ERROR_DISABLED -#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef LOG_DISABLED -#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#if WTF_COMPILER_GCC -#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#else -#define WTF_PRETTY_FUNCTION __FUNCTION__ -#endif - -/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute - emits a warning when %@ is used in the format string. Until is resolved we can't include - the attribute when being used from Objective-C code in case it decides to use %@. */ -#if WTF_COMPILER_GCC && !defined(__OBJC__) -#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments))) -#else -#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) -#endif - -/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState; - -typedef struct { - unsigned mask; - const char *defaultName; - WTFLogChannelState state; -} WTFLogChannel; - -void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); -void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); -void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion); -void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -void WTFLog(WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); -void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); - -#ifdef __cplusplus -} -#endif - -/* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */ - -#ifndef CRASH -#if WTF_OS_SYMBIAN -#define CRASH() do { \ - __DEBUGGER(); \ - User::Panic(_L("Webkit CRASH"),0); \ - } while(false) -#else -#define CRASH() do { \ - *(int *)(uintptr_t)0xbbadbeef = 0; \ - ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ -} while(false) -#endif -#endif - -/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */ - -#if WTF_PLATFORM_WIN || WTF_OS_SYMBIAN -/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */ -#undef ASSERT -#endif - -#if ASSERT_DISABLED - -#define ASSERT(assertion) ((void)0) -#if WTF_COMPILER_MSVC7 -#define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif WTF_COMPILER_WINSCW -#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) -#else -#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) -#endif /* COMPILER(MSVC7) */ -#define ASSERT_NOT_REACHED() ((void)0) -#define ASSERT_UNUSED(variable, assertion) ((void)variable) - -#else - -#define ASSERT(assertion) do \ - if (!(assertion)) { \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \ - CRASH(); \ - } \ -while (0) -#if WTF_COMPILER_MSVC7 -#define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif WTF_COMPILER_WINSCW -#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) -#else -#define ASSERT_WITH_MESSAGE(assertion, ...) do \ - if (!(assertion)) { \ - WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \ - CRASH(); \ - } \ -while (0) -#endif /* COMPILER(MSVC7) */ -#define ASSERT_NOT_REACHED() do { \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \ - CRASH(); \ -} while (0) - -#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) - -#endif - -/* ASSERT_ARG */ - -#if ASSERT_ARG_DISABLED - -#define ASSERT_ARG(argName, assertion) ((void)0) - -#else - -#define ASSERT_ARG(argName, assertion) do \ - if (!(assertion)) { \ - WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \ - CRASH(); \ - } \ -while (0) - -#endif - -/* COMPILE_ASSERT */ -#ifndef COMPILE_ASSERT -#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1] -#endif - -/* FATAL */ - -#if FATAL_DISABLED && !WTF_COMPILER_MSVC7 && !WTF_COMPILER_WINSCW -#define FATAL(...) ((void)0) -#elif WTF_COMPILER_MSVC7 -#define FATAL() ((void)0) -#else -#define FATAL(...) do { \ - WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \ - CRASH(); \ -} while (0) -#endif - -/* LOG_ERROR */ - -#if ERROR_DISABLED && !WTF_COMPILER_MSVC7 && !WTF_COMPILER_WINSCW -#define LOG_ERROR(...) ((void)0) -#elif WTF_COMPILER_MSVC7 -#define LOG_ERROR() ((void)0) -#elif WTF_COMPILER_WINSCW -#define LOG_ERROR(arg...) ((void)0) -#else -#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) -#endif - -/* LOG */ - -#if LOG_DISABLED && !WTF_COMPILER_MSVC7 && !WTF_COMPILER_WINSCW -#define LOG(channel, ...) ((void)0) -#elif WTF_COMPILER_MSVC7 -#define LOG() ((void)0) -#elif WTF_COMPILER_WINSCW -#define LOG(arg...) ((void)0) -#else -#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) -#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) -#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel -#endif - -/* LOG_VERBOSE */ - -#if LOG_DISABLED && !WTF_COMPILER_MSVC7 && !WTF_COMPILER_WINSCW -#define LOG_VERBOSE(channel, ...) ((void)0) -#elif WTF_COMPILER_MSVC7 -#define LOG_VERBOSE(channel) ((void)0) -#elif WTF_COMPILER_WINSCW -#define LOG_VERBOSE(channel, arg...) ((void)0) -#else -#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) -#endif - -#endif /* WTF_Assertions_h */ diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index 8a8cc6b60b19..128f65d068ed 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -4,10 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifdef JSGC_GENERATIONAL #ifndef jsgc_storebuffer_h___ #define jsgc_storebuffer_h___ +#ifdef JSGC_GENERATIONAL + #ifndef JSGC_USE_EXACT_ROOTING # error "Generational GC requires exact rooting." #endif @@ -509,5 +510,6 @@ class StoreBuffer } /* namespace gc */ } /* namespace js */ -#endif /* jsgc_storebuffer_h___ */ #endif /* JSGC_GENERATIONAL */ + +#endif /* jsgc_storebuffer_h___ */ diff --git a/js/src/ion/AsmJS.h b/js/src/ion/AsmJS.h index 7e7c1701ff32..eb3def26b10f 100644 --- a/js/src/ion/AsmJS.h +++ b/js/src/ion/AsmJS.h @@ -4,7 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_asmjs_h__) +#ifndef jsion_asmjs_h__ #define jsion_asmjs_h__ #ifdef XP_MACOSX diff --git a/js/src/ion/AsmJSModule.h b/js/src/ion/AsmJSModule.h index dc66a8e32461..a8cd305a4b78 100644 --- a/js/src/ion/AsmJSModule.h +++ b/js/src/ion/AsmJSModule.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_asmjsmodule_h__) && defined(JS_ION) +#ifndef jsion_asmjsmodule_h__ #define jsion_asmjsmodule_h__ +#ifdef JS_ION + #include "gc/Marking.h" #include "ion/RegisterSets.h" @@ -746,5 +748,7 @@ SetAsmJSModuleObject(JSFunction *moduleFun, JSObject *moduleObj); } // namespace js +#endif // JS_ION + #endif // jsion_asmjsmodule_h__ diff --git a/js/src/ion/BaselineCompiler.h b/js/src/ion/BaselineCompiler.h index 813974c79ac7..a19905ee9341 100644 --- a/js/src/ion/BaselineCompiler.h +++ b/js/src/ion/BaselineCompiler.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_compiler_h__) && defined(JS_ION) +#ifndef jsion_baseline_compiler_h__ #define jsion_baseline_compiler_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" #include "IonCode.h" @@ -265,5 +267,7 @@ class BaselineCompiler : public BaselineCompilerSpecific } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_compiler_h__ diff --git a/js/src/ion/BaselineFrame-inl.h b/js/src/ion/BaselineFrame-inl.h index 5bed02859c73..26f1a3b95b3d 100644 --- a/js/src/ion/BaselineFrame-inl.h +++ b/js/src/ion/BaselineFrame-inl.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_frame_inl_h__) && defined(JS_ION) +#ifndef jsion_baseline_frame_inl_h__ #define jsion_baseline_frame_inl_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" @@ -78,5 +80,7 @@ BaselineFrame::callObj() const } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_frame_inl_h__ diff --git a/js/src/ion/BaselineFrame.h b/js/src/ion/BaselineFrame.h index 3a10069331d9..dbccc6c3c130 100644 --- a/js/src/ion/BaselineFrame.h +++ b/js/src/ion/BaselineFrame.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_frame_h__) && defined(JS_ION) +#ifndef jsion_baseline_frame_h__ #define jsion_baseline_frame_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" @@ -396,5 +398,7 @@ JS_STATIC_ASSERT(((sizeof(BaselineFrame) + BaselineFrame::FramePointerOffset) % } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_frame_h__ diff --git a/js/src/ion/BaselineFrameInfo.h b/js/src/ion/BaselineFrameInfo.h index c282f8469035..742ec5cbedf9 100644 --- a/js/src/ion/BaselineFrameInfo.h +++ b/js/src/ion/BaselineFrameInfo.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_frameinfo_h__) && defined(JS_ION) +#ifndef jsion_baseline_frameinfo_h__ #define jsion_baseline_frameinfo_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" @@ -329,5 +331,7 @@ class FrameInfo } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_frameinfo_h__ diff --git a/js/src/ion/BaselineHelpers.h b/js/src/ion/BaselineHelpers.h index 795ef4b74473..beefd6d4a0c0 100644 --- a/js/src/ion/BaselineHelpers.h +++ b/js/src/ion/BaselineHelpers.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_helpers_h__) && defined(JS_ION) +#ifndef jsion_baseline_helpers_h__ #define jsion_baseline_helpers_h__ +#ifdef JS_ION + #if defined(JS_CPU_X86) # include "x86/BaselineHelpers-x86.h" #elif defined(JS_CPU_X64) @@ -23,5 +25,6 @@ namespace ion { } // namespace ion } // namespace js -#endif +#endif // JS_ION +#endif // jsion_baseline_helpers_h__ diff --git a/js/src/ion/BaselineIC.h b/js/src/ion/BaselineIC.h index 128283c48601..6afd51f216b9 100644 --- a/js/src/ion/BaselineIC.h +++ b/js/src/ion/BaselineIC.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_ic_h__) && defined(JS_ION) +#ifndef jsion_baseline_ic_h__ #define jsion_baseline_ic_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" #include "jsgc.h" @@ -5522,4 +5524,6 @@ class ICRest_Fallback : public ICFallbackStub } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_ic_h__ diff --git a/js/src/ion/BaselineInspector.h b/js/src/ion/BaselineInspector.h index 2870afa95432..2c889fcdb67e 100644 --- a/js/src/ion/BaselineInspector.h +++ b/js/src/ion/BaselineInspector.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_inspector_h__) && defined(JS_ION) +#ifndef jsion_baseline_inspector_h__ #define jsion_baseline_inspector_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" @@ -111,5 +113,7 @@ class BaselineInspector } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_inspector_h__ diff --git a/js/src/ion/BaselineJIT.h b/js/src/ion/BaselineJIT.h index b53f701f6a6a..5b3aa858b757 100644 --- a/js/src/ion/BaselineJIT.h +++ b/js/src/ion/BaselineJIT.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_jit_h__) && defined(JS_ION) +#ifndef jsion_baseline_jit_h__ #define jsion_baseline_jit_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" @@ -330,5 +332,7 @@ MarkActiveBaselineScripts(Zone *zone); } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_jit_h__ diff --git a/js/src/ion/BaselineRegisters.h b/js/src/ion/BaselineRegisters.h index 26365375481d..d74e246f0e33 100644 --- a/js/src/ion/BaselineRegisters.h +++ b/js/src/ion/BaselineRegisters.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_registers_h__) && defined(JS_ION) +#ifndef jsion_baseline_registers_h__ #define jsion_baseline_registers_h__ +#ifdef JS_ION + #if defined(JS_CPU_X86) # include "x86/BaselineRegisters-x86.h" #elif defined(JS_CPU_X64) @@ -21,5 +23,7 @@ namespace ion { } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_registers_h__ diff --git a/js/src/ion/CompilerRoot.h b/js/src/ion/CompilerRoot.h index 50c41a863d55..ef7ccc6bff7b 100644 --- a/js/src/ion/CompilerRoot.h +++ b/js/src/ion/CompilerRoot.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_ion_gc_h__) && defined(JS_ION) +#ifndef jsion_ion_gc_h__ #define jsion_ion_gc_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "js/RootingAPI.h" @@ -61,5 +63,7 @@ typedef CompilerRoot CompilerRootValue; } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_ion_gc_h__ diff --git a/js/src/ion/ExecutionModeInlines.h b/js/src/ion/ExecutionModeInlines.h index 938445719ab8..8ccca3a2b563 100644 --- a/js/src/ion/ExecutionModeInlines.h +++ b/js/src/ion/ExecutionModeInlines.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_executionmodeinlines_h__) && defined(JS_ION) +#ifndef jsion_executionmodeinlines_h__ #define jsion_executionmodeinlines_h__ +#ifdef JS_ION + namespace js { namespace ion { @@ -102,7 +104,9 @@ CompilerOutputKind(ExecutionMode cmode) return types::CompilerOutput::Ion; } -} -} +} // namespace ion +} // namespace js + +#endif // JS_ION #endif // jsion_executionmodeinlines_h__ diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index b266084ada2b..9cbadd814883 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_ion_h__) && defined(JS_ION) +#ifndef jsion_ion_h__ #define jsion_ion_h__ +#ifdef JS_ION + #include "jscntxt.h" #include "jscompartment.h" #include "IonCode.h" @@ -350,5 +352,7 @@ void TraceIonScripts(JSTracer* trc, JSScript *script); } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_ion_h__ diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h index e1a47e2c01da..8e673f412181 100644 --- a/js/src/ion/IonBuilder.h +++ b/js/src/ion/IonBuilder.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_bytecode_analyzer_h__) && defined(JS_ION) +#ifndef jsion_bytecode_analyzer_h__ #define jsion_bytecode_analyzer_h__ +#ifdef JS_ION + // This file declares the data structures for building a MIRGraph from a // JSScript. @@ -798,4 +800,6 @@ bool NeedsPostBarrier(CompileInfo &info, MDefinition *value); } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_bytecode_analyzer_h__ diff --git a/js/src/ion/IonCompartment.h b/js/src/ion/IonCompartment.h index 3ad4298f1223..024a442e2e6a 100644 --- a/js/src/ion/IonCompartment.h +++ b/js/src/ion/IonCompartment.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_ion_compartment_h__) && defined(JS_ION) +#ifndef jsion_ion_compartment_h__ #define jsion_ion_compartment_h__ +#ifdef JS_ION + #include "IonCode.h" #include "jsweakcache.h" #include "js/Value.h" @@ -316,5 +318,7 @@ void FinishInvalidation(FreeOp *fop, JSScript *script); } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_ion_compartment_h__ diff --git a/js/src/ion/IonFrameIterator-inl.h b/js/src/ion/IonFrameIterator-inl.h index 33f4c37d23cd..8a1a7b82aa88 100644 --- a/js/src/ion/IonFrameIterator-inl.h +++ b/js/src/ion/IonFrameIterator-inl.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_frame_iterator_inl_h__) && defined(JS_ION) +#ifndef jsion_frame_iterator_inl_h__ #define jsion_frame_iterator_inl_h__ +#ifdef JS_ION + #include "ion/BaselineFrame.h" #include "ion/IonFrameIterator.h" #include "ion/Bailouts.h" @@ -236,4 +238,6 @@ IonFrameIterator::baselineFrame() const } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_frame_iterator_inl_h__ diff --git a/js/src/ion/IonFrameIterator.h b/js/src/ion/IonFrameIterator.h index 9bb9bb3e0039..a4b293cc5a46 100644 --- a/js/src/ion/IonFrameIterator.h +++ b/js/src/ion/IonFrameIterator.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_frame_iterator_h__) && defined(JS_ION) +#ifndef jsion_frame_iterator_h__ #define jsion_frame_iterator_h__ +#ifdef JS_ION + #include "jstypes.h" #include "IonCode.h" #include "SnapshotReader.h" @@ -331,5 +333,7 @@ typedef InlineFrameIteratorMaybeGC InlineFrameIteratorNoGC; } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_frames_iterator_h__ diff --git a/js/src/ion/IonFrames-inl.h b/js/src/ion/IonFrames-inl.h index 34e05d5c5113..d85656edfb20 100644 --- a/js/src/ion/IonFrames-inl.h +++ b/js/src/ion/IonFrames-inl.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_frames_inl_h__) && defined(JS_ION) +#ifndef jsion_frames_inl_h__ #define jsion_frames_inl_h__ +#ifdef JS_ION + #include "ion/IonFrames.h" #include "ion/IonFrameIterator.h" #include "ion/LIR.h" @@ -147,5 +149,7 @@ GetTopBaselineFrame(JSContext *cx) } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_frames_inl_h__ diff --git a/js/src/ion/IonFrames.h b/js/src/ion/IonFrames.h index a27f4177f6d1..2ead4d4bacab 100644 --- a/js/src/ion/IonFrames.h +++ b/js/src/ion/IonFrames.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_frames_h__) && defined(JS_ION) +#ifndef jsion_frames_h__ #define jsion_frames_h__ +#ifdef JS_ION + #include "mozilla/DebugOnly.h" #include "jsfun.h" @@ -330,5 +332,7 @@ MarkCalleeToken(JSTracer *trc, CalleeToken token); } /* namespace ion */ } /* namespace js */ +#endif // JS_ION + #endif // jsion_frames_h__ diff --git a/js/src/ion/IonMacroAssembler.h b/js/src/ion/IonMacroAssembler.h index 7c48e7081f48..a5caad5b36d3 100644 --- a/js/src/ion/IonMacroAssembler.h +++ b/js/src/ion/IonMacroAssembler.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_macro_assembler_h__) && defined(JS_ION) +#ifndef jsion_macro_assembler_h__ #define jsion_macro_assembler_h__ +#ifdef JS_ION + #if defined(JS_CPU_X86) # include "ion/x86/MacroAssembler-x86.h" #elif defined(JS_CPU_X64) @@ -996,4 +998,6 @@ class ABIArgIter } // namespace ion } // namespace js +#endif // JS_ION + #endif // jsion_macro_assembler_h__ diff --git a/js/src/ion/arm/BaselineHelpers-arm.h b/js/src/ion/arm/BaselineHelpers-arm.h index 6d5611eb5437..3c99b4010644 100644 --- a/js/src/ion/arm/BaselineHelpers-arm.h +++ b/js/src/ion/arm/BaselineHelpers-arm.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_helpers_arm_h__) && defined(JS_ION) +#ifndef jsion_baseline_helpers_arm_h__ #define jsion_baseline_helpers_arm_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" #include "ion/BaselineFrame.h" #include "ion/BaselineRegisters.h" @@ -303,5 +305,7 @@ EmitStubGuardFailure(MacroAssembler &masm) } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_helpers_arm_h__ diff --git a/js/src/ion/arm/BaselineRegisters-arm.h b/js/src/ion/arm/BaselineRegisters-arm.h index 53c908850855..4a9ff3a63064 100644 --- a/js/src/ion/arm/BaselineRegisters-arm.h +++ b/js/src/ion/arm/BaselineRegisters-arm.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_registers_arm_h__) && defined(JS_ION) +#ifndef jsion_baseline_registers_arm_h__ #define jsion_baseline_registers_arm_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" namespace js { @@ -53,5 +55,7 @@ static const FloatRegister FloatReg1 = d2; } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_registers_arm_h__ diff --git a/js/src/ion/x64/BaselineHelpers-x64.h b/js/src/ion/x64/BaselineHelpers-x64.h index 832bbd36a457..8c232fd8c1f6 100644 --- a/js/src/ion/x64/BaselineHelpers-x64.h +++ b/js/src/ion/x64/BaselineHelpers-x64.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_helpers_x64_h__) && defined(JS_ION) +#ifndef jsion_baseline_helpers_x64_h__ #define jsion_baseline_helpers_x64_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" #include "ion/BaselineFrame.h" #include "ion/BaselineRegisters.h" @@ -274,5 +276,7 @@ EmitStubGuardFailure(MacroAssembler &masm) } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_helpers_x64_h__ diff --git a/js/src/ion/x64/BaselineRegisters-x64.h b/js/src/ion/x64/BaselineRegisters-x64.h index 72a64a55bb1f..11e6dee02126 100644 --- a/js/src/ion/x64/BaselineRegisters-x64.h +++ b/js/src/ion/x64/BaselineRegisters-x64.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_registers_x64_h__) && defined(JS_ION) +#ifndef jsion_baseline_registers_x64_h__ #define jsion_baseline_registers_x64_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" namespace js { @@ -34,5 +36,7 @@ static const FloatRegister FloatReg1 = xmm1; } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_registers_x64_h__ diff --git a/js/src/ion/x86/BaselineHelpers-x86.h b/js/src/ion/x86/BaselineHelpers-x86.h index 2565d4898734..e7b61d67729a 100644 --- a/js/src/ion/x86/BaselineHelpers-x86.h +++ b/js/src/ion/x86/BaselineHelpers-x86.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_helpers_x86_h__) && defined(JS_ION) +#ifndef jsion_baseline_helpers_x86_h__ #define jsion_baseline_helpers_x86_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" #include "ion/BaselineFrame.h" #include "ion/BaselineRegisters.h" @@ -280,5 +282,7 @@ EmitStubGuardFailure(MacroAssembler &masm) } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_helpers_x86_h__ diff --git a/js/src/ion/x86/BaselineRegisters-x86.h b/js/src/ion/x86/BaselineRegisters-x86.h index b28bda46ea29..6564e1ab0c26 100644 --- a/js/src/ion/x86/BaselineRegisters-x86.h +++ b/js/src/ion/x86/BaselineRegisters-x86.h @@ -4,9 +4,11 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#if !defined(jsion_baseline_registers_x86_h__) && defined(JS_ION) +#ifndef jsion_baseline_registers_x86_h__ #define jsion_baseline_registers_x86_h__ +#ifdef JS_ION + #include "ion/IonMacroAssembler.h" namespace js { @@ -35,5 +37,7 @@ static const FloatRegister FloatReg1 = xmm1; } // namespace ion } // namespace js -#endif +#endif // JS_ION + +#endif // jsion_baseline_registers_x86_h__ diff --git a/js/src/jsoplengen.cpp b/js/src/jsoplengen.cpp index bd090bd59ac0..db5249a4eb27 100644 --- a/js/src/jsoplengen.cpp +++ b/js/src/jsoplengen.cpp @@ -41,6 +41,8 @@ main(int argc, char **argv) perror("fopen"); return EXIT_FAILURE; } + fputs("#ifndef JSAUTOOPLEN_H___\n", fp); + fputs("#define JSAUTOOPLEN_H___\n", fp); fputs("/*\n" " * Automatically generated header with JS opcode length constants.\n" " *\n" @@ -78,6 +80,8 @@ main(int argc, char **argv) } } + fputs("#endif // JSAUTOOPLEN_H___\n", fp); + if (fclose(fp)) { perror("fclose"); return EXIT_FAILURE; diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 91b93a924db1..9efbae12c444 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -315,4 +315,4 @@ JSObject::asDebugScope() return *static_cast(this); } -#endif /* CallObject_inl_h___ */ +#endif /* ScopeObject_inl_h___ */ diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 1e8562961e69..9359160d5e28 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -892,4 +892,5 @@ InterpreterActivation::~InterpreterActivation() {} } /* namespace js */ + #endif /* Stack_inl_h__ */ From 84c3593dcac99d75382d041b43619d03b41704ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Sun, 16 Jun 2013 21:16:21 -0700 Subject: [PATCH 441/615] Bug 874339 - System Message API: redundant queues are created for the pending "activity" system messages r=gene --- dom/messages/SystemMessageInternal.js | 80 ++++++++++++--------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/dom/messages/SystemMessageInternal.js b/dom/messages/SystemMessageInternal.js index a30fd0832ba7..e849e615998a 100644 --- a/dom/messages/SystemMessageInternal.js +++ b/dom/messages/SystemMessageInternal.js @@ -128,6 +128,17 @@ SystemMessageInternal.prototype = { } }, + _findPage: function _findPage(aType, aPageURL, aManifestURL) { + let page = null; + this._pages.some(function(aPage) { + if (this._isPageMatched(aPage, aType, aPageURL, aManifestURL)) { + page = aPage; + } + return page !== null; + }, this); + return page; + }, + sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) { // Buffer system messages until the webapps' registration is ready, // so that we can know the correct pages registered to be sent. @@ -157,23 +168,14 @@ SystemMessageInternal.prototype = { return; } - let pagesToOpen = {}; - this._pages.forEach(function(aPage) { - if (!this._isPageMatched(aPage, aType, aPageURI.spec, aManifestURI.spec)) { - return; - } - + let page = this._findPage(aType, aPageURI.spec, aManifestURI.spec); + if (page) { // Queue this message in the corresponding pages. - this._queueMessage(aPage, aMessage, messageID); + this._queueMessage(page, aMessage, messageID); // Open app pages to handle their pending messages. - // Note that we only need to open each app page once. - let key = this._createKeyForPage(aPage); - if (!pagesToOpen.hasOwnProperty(key)) { - this._openAppPage(aPage, aMessage); - pagesToOpen[key] = true; - } - }, this); + this._openAppPage(page, aMessage); + } }, broadcastMessage: function broadcastMessage(aType, aMessage) { @@ -192,7 +194,6 @@ SystemMessageInternal.prototype = { debug("Broadcasting " + aType + " " + JSON.stringify(aMessage)); // Find pages that registered an handler for this type. - let pagesToOpen = {}; this._pages.forEach(function(aPage) { if (aPage.type == aType) { // Don't need to open the pages and queue the system message @@ -209,12 +210,7 @@ SystemMessageInternal.prototype = { this._queueMessage(aPage, aMessage, messageID); // Open app pages to handle their pending messages. - // Note that we only need to open each app page once. - let key = this._createKeyForPage(aPage); - if (!pagesToOpen.hasOwnProperty(key)) { - this._openAppPage(aPage, aMessage); - pagesToOpen[key] = true; - } + this._openAppPage(aPage, aMessage); } }, this); }, @@ -224,9 +220,20 @@ SystemMessageInternal.prototype = { throw Cr.NS_ERROR_INVALID_ARG; } + let pageURL = aPageURI.spec; + let manifestURL = aManifestURI.spec; + + // Don't register duplicates for this tuple. + let page = this._findPage(aType, pageURL, manifestURL); + if (page) { + debug("Ignoring duplicate registration of " + + [aType, pageURL, manifestURL]); + return; + } + this._pages.push({ type: aType, - uri: aPageURI.spec, - manifest: aManifestURI.spec, + uri: pageURL, + manifest: manifestURL, pendingMessages: [] }); }, @@ -361,13 +368,7 @@ SystemMessageInternal.prototype = { // This is a sync call used to return the pending messages for a page. // Find the right page to get its corresponding pending messages. - let page = null; - this._pages.some(function(aPage) { - if (this._isPageMatched(aPage, msg.type, msg.uri, msg.manifest)) { - page = aPage; - } - return page !== null; - }, this); + let page = this._findPage(msg.type, msg.uri, msg.manifest); if (!page) { return; } @@ -398,13 +399,7 @@ SystemMessageInternal.prototype = { // This is a sync call used to return if a page has pending messages. // Find the right page to get its corresponding pending messages. - let page = null; - this._pages.some(function(aPage) { - if (this._isPageMatched(aPage, msg.type, msg.uri, msg.manifest)) { - page = aPage; - } - return page !== null; - }, this); + let page = this._findPage(msg.type, msg.uri, msg.manifest); if (!page) { return false; } @@ -419,19 +414,16 @@ SystemMessageInternal.prototype = { // We need to clean up the pending message since the app has already // received it, thus avoiding the re-lanunched app handling it again. - this._pages.forEach(function(aPage) { - if (!this._isPageMatched(aPage, msg.type, msg.uri, msg.manifest)) { - return; - } - - let pendingMessages = aPage.pendingMessages; + let page = this._findPage(msg.type, msg.uri, msg.manifest); + if (page) { + let pendingMessages = page.pendingMessages; for (let i = 0; i < pendingMessages.length; i++) { if (pendingMessages[i].msgID === msg.msgID) { pendingMessages.splice(i, 1); break; } } - }, this); + } break; } case "SystemMessageManager:HandleMessagesDone": From 6af94aeebd5d64068da23cc7dc2342ecf5d97069 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Sun, 16 Jun 2013 21:31:22 -0700 Subject: [PATCH 442/615] Bumping gaia.json for 2 gaia-central revision(s) Truncated some number of revisions since the previous bump. ======== https://hg.mozilla.org/integration/gaia-central/rev/b406627a0838 Author: Alive.Kuo Desc: Merge pull request #10412 from alivedise/bugzilla/882053/content-channel-should-trigger-vibration-mode Bug 882053 - Content channel triggers silent mode incorrectly.r=timdream,a=leo+ ======== https://hg.mozilla.org/integration/gaia-central/rev/cc24e1635053 Author: Alive Kuo Desc: Bug 882053 - Content channel triggers silent mode incorrectly. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d36449ff5715..4faafa888643 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "98f8d19dee9d4808e414f5811c0db09afe6adc4a", + "revision": "b406627a0838957e791b588509925cf1e85e1b2f", "repo_path": "/integration/gaia-central" } From 5492ea1e0c4651a457057683c16dc123cc4fb640 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Sun, 16 Jun 2013 21:31:42 -0700 Subject: [PATCH 443/615] Bumping gaia.json for 4 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/3320c4f90ffb Author: Alive.Kuo Desc: Merge pull request #9905 from NeerajSeth/bug-817909 [Settings-Phone Lock] "confirm passcode" field accepts invalid entries, ...r=alive ======== https://hg.mozilla.org/integration/gaia-central/rev/34b2010670a1 Author: Neeraj Kumar Desc: [Settings-Phone Lock] "confirm passcode" field accepts invalid entries, if you previously typed correct value and then backspaced some of it ======== https://hg.mozilla.org/integration/gaia-central/rev/05d8d85f4a15 Author: Alive.Kuo Desc: Merge pull request #10386 from leob2g/Bug_834148_volume_up_key_skips_vibrate_when_moving_up_20130614 Bug 834148 - move from silent to vibrate instead of volume 1 when moving up, r=alive, a=leo+ ======== https://hg.mozilla.org/integration/gaia-central/rev/7df2ca443036 Author: hanj.kim Desc: Bug 834148 - move from silent to vibrate instead of volume 1 when power up button is pressed on silent --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 4faafa888643..e59046d4c3bb 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "b406627a0838957e791b588509925cf1e85e1b2f", + "revision": "3320c4f90ffb0c372f06f7b72d14b54ce0f7a138", "repo_path": "/integration/gaia-central" } From 6c5bb2cc06966fa16bc180c45f4f07169ccb2011 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 18 Jun 2013 19:58:43 +1200 Subject: [PATCH 444/615] Bug 873944 - Add FlushRendering API to the compositor interface. r=nrc --- gfx/layers/Layers.h | 9 +++++++++ gfx/layers/client/ClientLayerManager.cpp | 10 ++++++++++ gfx/layers/client/ClientLayerManager.h | 2 ++ gfx/layers/ipc/CompositorParent.cpp | 13 +++++++++++++ gfx/layers/ipc/CompositorParent.h | 1 + gfx/layers/ipc/PCompositor.ipdl | 4 ++++ 6 files changed, 39 insertions(+) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 29aef1df13c7..95c8bd864b13 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -466,6 +466,15 @@ public: */ virtual void SetIsFirstPaint() {} + /** + * Make sure that the previous transaction has been entirely + * completed. + * + * Note: This may sychronously wait on a remote compositor + * to complete rendering. + */ + virtual void FlushRendering() { } + // We always declare the following logging symbols, because it's // extremely tricky to conditionally declare them. However, for // ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 0ceb44f9d14c..bd041160fa44 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -260,6 +260,16 @@ ClientLayerManager::MakeSnapshotIfRequired() mShadowTarget = nullptr; } +void +ClientLayerManager::FlushRendering() +{ + if (mWidget) { + if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) { + remoteRenderer->SendFlushRendering(); + } + } +} + void ClientLayerManager::ForwardTransaction() { diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index 08c64b20d0e1..774a57c807fb 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -53,6 +53,8 @@ public: virtual already_AddRefed CreateColorLayer(); virtual already_AddRefed CreateRefLayer(); + virtual void FlushRendering() MOZ_OVERRIDE; + ShadowableLayer* Hold(Layer* aLayer); bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); } diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index d807d567bf9c..be6dbf779c33 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -249,6 +249,18 @@ CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, return true; } +bool +CompositorParent::RecvFlushRendering() +{ + // If we're waiting to do a composite, then cancel it + // and do it immediately instead. + if (mCurrentCompositeTask) { + mCurrentCompositeTask->Cancel(); + ComposeToTarget(nullptr); + } + return true; +} + void CompositorParent::ActorDestroy(ActorDestroyReason why) { @@ -743,6 +755,7 @@ public: virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, SurfaceDescriptor* aOutSnapshot) { return true; } + virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; } virtual PLayerTransactionParent* AllocPLayerTransaction(const LayersBackend& aBackendType, diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index fba4cbff667b..4f25a4201af4 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -55,6 +55,7 @@ public: virtual bool RecvResume() MOZ_OVERRIDE; virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, SurfaceDescriptor* aOutSnapshot); + virtual bool RecvFlushRendering() MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; diff --git a/gfx/layers/ipc/PCompositor.ipdl b/gfx/layers/ipc/PCompositor.ipdl index cc78eba14ccb..72e1ea00f019 100644 --- a/gfx/layers/ipc/PCompositor.ipdl +++ b/gfx/layers/ipc/PCompositor.ipdl @@ -53,6 +53,10 @@ parent: sync MakeSnapshot(SurfaceDescriptor inSnapshot) returns (SurfaceDescriptor outSnapshot); + // Make sure any pending composites are started immediately and + // block until they are completed. + sync FlushRendering(); + sync PLayerTransaction(LayersBackend layersBackendHint, uint64_t id) returns (TextureFactoryIdentifier textureFactoryIdentifier); }; From 7b0c403cca06eab5189744317d8a8ede6017fa6b Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 18 Jun 2013 19:59:00 +1200 Subject: [PATCH 445/615] Bug 873944 - Remove unecessarily callers to nsView::Invalidate. r=roc --- docshell/base/nsDocShell.cpp | 11 ---- layout/base/nsDocumentViewer.cpp | 6 -- view/public/nsViewManager.h | 4 -- view/src/nsViewManager.cpp | 100 +------------------------------ widget/cocoa/nsChildView.mm | 4 ++ 5 files changed, 5 insertions(+), 120 deletions(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 5df9a12d5620..66b021cb9398 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -7890,17 +7890,6 @@ nsDocShell::RestoreFromHistory() // Restart plugins, and paint the content. if (shell) { shell->Thaw(); - - newVM = shell->GetViewManager(); - if (newVM) { - // When we insert the root view above the resulting invalidate is - // dropped because painting is suppressed in the presshell until we - // call Thaw. So we issue the invalidate here. - newRootView = newVM->GetRootView(); - if (newRootView) { - newVM->InvalidateView(newRootView); - } - } } return privWin->FireDelayedDOMEvents(); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index e599bad969ee..066b8fbcb558 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1541,12 +1541,6 @@ nsDocumentViewer::Destroy() nsView *rootView = vm->GetRootView(); if (rootView) { - // The invalidate that removing this view causes is dropped because - // the Freeze call above sets painting to be suppressed for our - // document. So we do it ourselves and make it happen. - vm->InvalidateViewNoSuppression(rootView, - rootView->GetBounds() - rootView->GetPosition()); - nsView *rootViewParent = rootView->GetParent(); if (rootViewParent) { nsViewManager *parentVM = rootViewParent->GetViewManager(); diff --git a/view/public/nsViewManager.h b/view/public/nsViewManager.h index 3cb547956019..2ce343bc6c50 100644 --- a/view/public/nsViewManager.h +++ b/view/public/nsViewManager.h @@ -344,10 +344,6 @@ private: // aView is the view for aWidget and aRegion is relative to aWidget. void Refresh(nsView *aView, const nsIntRegion& aRegion); - void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut); - void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, - nscoord aY1, nscoord aY2, bool aInCutOut); - // Utilities bool IsViewInserted(nsView *aView); diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index de10d5c56da3..56d40f0b5880 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -384,7 +384,6 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, vm->mRootView->IsEffectivelyVisible() && mPresShell && mPresShell->IsVisible()) { vm->FlushDelayedResize(true); - vm->InvalidateView(vm->mRootView); } } @@ -842,11 +841,6 @@ nsViewManager::InsertChild(nsView *aParent, nsView *aChild, nsView *aSibling, // if the parent view is marked as "floating", make the newly added view float as well. if (aParent->GetFloating()) aChild->SetFloating(true); - - //and mark this area as dirty if the view is visible... - - if (nsViewVisibility_kHide != aChild->GetVisibility()) - aChild->GetViewManager()->InvalidateView(aChild); } } @@ -869,7 +863,6 @@ nsViewManager::RemoveChild(nsView *aChild) if (nullptr != parent) { NS_ASSERTION(aChild->GetViewManager() == this || parent->GetViewManager() == this, "wrong view manager"); - aChild->GetViewManager()->InvalidateView(aChild); parent->RemoveChild(aChild); } } @@ -878,53 +871,7 @@ void nsViewManager::MoveViewTo(nsView *aView, nscoord aX, nscoord aY) { NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); - nsPoint oldPt = aView->GetPosition(); - nsRect oldBounds = aView->GetBoundsInParentUnits(); aView->SetPosition(aX, aY); - - // only do damage control if the view is visible - - if ((aX != oldPt.x) || (aY != oldPt.y)) { - if (aView->GetVisibility() != nsViewVisibility_kHide) { - nsView* parentView = aView->GetParent(); - if (parentView) { - nsViewManager* parentVM = parentView->GetViewManager(); - parentVM->InvalidateView(parentView, oldBounds); - parentVM->InvalidateView(parentView, aView->GetBoundsInParentUnits()); - } - } - } -} - -void nsViewManager::InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, - nscoord aY1, nscoord aY2, bool aInCutOut) { - nscoord height = aY2 - aY1; - if (aRect.x < aCutOut.x) { - nsRect r(aRect.x, aY1, aCutOut.x - aRect.x, height); - InvalidateView(aView, r); - } - if (!aInCutOut && aCutOut.x < aCutOut.XMost()) { - nsRect r(aCutOut.x, aY1, aCutOut.width, height); - InvalidateView(aView, r); - } - if (aCutOut.XMost() < aRect.XMost()) { - nsRect r(aCutOut.XMost(), aY1, aRect.XMost() - aCutOut.XMost(), height); - InvalidateView(aView, r); - } -} - -void nsViewManager::InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut) { - NS_ASSERTION(aView->GetViewManager() == this, - "InvalidateRectDifference called on view we don't own"); - if (aRect.y < aCutOut.y) { - InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aRect.y, aCutOut.y, false); - } - if (aCutOut.y < aCutOut.YMost()) { - InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.y, aCutOut.YMost(), true); - } - if (aCutOut.YMost() < aRect.YMost()) { - InvalidateHorizontalBandDifference(aView, aRect, aCutOut, aCutOut.YMost(), aRect.YMost(), false); - } } void @@ -934,28 +881,7 @@ nsViewManager::ResizeView(nsView *aView, const nsRect &aRect, bool aRepaintExpos nsRect oldDimensions = aView->GetDimensions(); if (!oldDimensions.IsEqualEdges(aRect)) { - // resize the view. - // Prevent Invalidation of hidden views - if (aView->GetVisibility() == nsViewVisibility_kHide) { - aView->SetDimensions(aRect, false); - } else { - nsView* parentView = aView->GetParent(); - if (!parentView) { - parentView = aView; - } - nsRect oldBounds = aView->GetBoundsInParentUnits(); - aView->SetDimensions(aRect, true); - nsViewManager* parentVM = parentView->GetViewManager(); - if (!aRepaintExposedAreaOnly) { - // Invalidate the union of the old and new size - InvalidateView(aView, aRect); - parentVM->InvalidateView(parentView, oldBounds); - } else { - InvalidateRectDifference(aView, aRect, oldDimensions); - nsRect newBounds = aView->GetBoundsInParentUnits(); - parentVM->InvalidateRectDifference(parentView, oldBounds, newBounds); - } - } + aView->SetDimensions(aRect, true); } // Note that if layout resizes the view and the view has a custom clip @@ -980,21 +906,6 @@ nsViewManager::SetViewVisibility(nsView *aView, nsViewVisibility aVisible) if (aVisible != aView->GetVisibility()) { aView->SetVisibility(aVisible); - - if (IsViewInserted(aView)) { - if (!aView->HasWidget()) { - if (nsViewVisibility_kHide == aVisible) { - nsView* parentView = aView->GetParent(); - if (parentView) { - parentView->GetViewManager()-> - InvalidateView(parentView, aView->GetBoundsInParentUnits()); - } - } - else { - InvalidateView(aView); - } - } - } } } @@ -1027,20 +938,11 @@ nsViewManager::SetViewZIndex(nsView *aView, bool aAutoZIndex, int32_t aZIndex, b return; } - bool oldTopMost = aView->IsTopMost(); - bool oldIsAuto = aView->GetZIndexIsAuto(); - if (aAutoZIndex) { aZIndex = 0; } - int32_t oldidx = aView->GetZIndex(); aView->SetZIndex(aAutoZIndex, aZIndex, aTopMost); - - if (oldidx != aZIndex || oldTopMost != aTopMost || - oldIsAuto != aAutoZIndex) { - InvalidateView(aView); - } } nsViewManager* diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index f3763ab87807..a6e37b86b3c9 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1386,6 +1386,10 @@ NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect) if (!mView || !mVisible) return NS_OK; + NS_ASSERTION(GetLayerManager()->GetBackendType() != LAYERS_CLIENT || + Compositor::GetBackend() == LAYERS_BASIC, + "Shouldn't need to invalidate with accelerated OMTC layers!"); + if ([NSView focusView]) { // if a view is focussed (i.e. being drawn), then postpone the invalidate so that we // don't lose it. From 7b9d5b3e53279ec28777a1c468eaa36589aeb025 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 18 Jun 2013 19:59:29 +1200 Subject: [PATCH 446/615] Bug 873944 - When we have OMTC, don't invalidate and wait for the widget paint event, just call DidPaint immediately. If we do get a widget paint event (from an OS initiated resize or similar), then block until the compositor has drawn the frame. r=roc --- gfx/layers/Layers.h | 6 ++++++ gfx/layers/client/ClientLayerManager.h | 2 ++ layout/base/nsDisplayList.cpp | 7 +++++-- layout/base/nsPresShell.cpp | 18 +++++++++++------- layout/reftests/forms/input/range/reftest.list | 4 ++-- view/src/nsViewManager.cpp | 13 +++++++++++-- 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 95c8bd864b13..71d2b95bb652 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -475,6 +475,12 @@ public: */ virtual void FlushRendering() { } + /** + * Checks if we need to invalidate the OS widget to trigger + * painting when updating this layer manager. + */ + virtual bool NeedsWidgetInvalidation() { return true; } + // We always declare the following logging symbols, because it's // extremely tricky to conditionally declare them. However, for // ifndef MOZ_LAYERS_HAVE_LOG builds, they only have trivial diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index 774a57c807fb..ef630073dcea 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -55,6 +55,8 @@ public: virtual void FlushRendering() MOZ_OVERRIDE; + virtual bool NeedsWidgetInvalidation() MOZ_OVERRIDE { return Compositor::GetBackend() == LAYERS_BASIC; } + ShadowableLayer* Hold(Layer* aLayer); bool HasShadowManager() const { return ShadowLayerForwarder::HasShadowManager(); } diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 69d03c0499a8..8301b5f85a0d 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1199,6 +1199,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, LayerProperties::ClearInvalidations(root); } + bool shouldInvalidate = layerManager->NeedsWidgetInvalidation(); if (view) { if (props) { if (!invalid.IsEmpty()) { @@ -1207,10 +1208,12 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, presContext->DevPixelsToAppUnits(bounds.y), presContext->DevPixelsToAppUnits(bounds.width), presContext->DevPixelsToAppUnits(bounds.height)); - view->GetViewManager()->InvalidateViewNoSuppression(view, rect); + if (shouldInvalidate) { + view->GetViewManager()->InvalidateViewNoSuppression(view, rect); + } presContext->NotifyInvalidation(bounds, 0); } - } else { + } else if (shouldInvalidate) { view->GetViewManager()->InvalidateView(view); } } diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index aedc2b81e2d2..3314b88ef368 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5489,8 +5489,6 @@ PresShell::Paint(nsView* aViewToPaint, return; } - nsAutoNotifyDidPaint notifyDidPaint(this, aFlags); - nsPresContext* presContext = GetPresContext(); AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint); @@ -5500,6 +5498,13 @@ PresShell::Paint(nsView* aViewToPaint, LayerManager* layerManager = aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager); NS_ASSERTION(layerManager, "Must be in paint event"); + bool shouldInvalidate = layerManager->NeedsWidgetInvalidation(); + + uint32_t didPaintFlags = aFlags; + if (!shouldInvalidate) { + didPaintFlags |= PAINT_COMPOSITE; + } + nsAutoNotifyDidPaint notifyDidPaint(this, didPaintFlags); // Whether or not we should set first paint when painting is // suppressed is debatable. For now we'll do it because @@ -5519,9 +5524,6 @@ PresShell::Paint(nsView* aViewToPaint, // 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 (!(aFlags & PAINT_LAYERS)) { - if (layerManager->HasShadowManager() && Compositor::GetBackend() != LAYERS_BASIC) { - return; - } layerManager->BeginTransaction(); if (layerManager->EndEmptyTransaction()) { return; @@ -5556,10 +5558,12 @@ PresShell::Paint(nsView* aViewToPaint, presContext->DevPixelsToAppUnits(bounds.y), presContext->DevPixelsToAppUnits(bounds.width), presContext->DevPixelsToAppUnits(bounds.height)); - aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect); + if (shouldInvalidate) { + aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect); + } presContext->NotifyInvalidation(bounds, 0); } - } else { + } else if (shouldInvalidate) { aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint); } diff --git a/layout/reftests/forms/input/range/reftest.list b/layout/reftests/forms/input/range/reftest.list index 8d0074da3dc4..e82889ed8c8c 100644 --- a/layout/reftests/forms/input/range/reftest.list +++ b/layout/reftests/forms/input/range/reftest.list @@ -21,8 +21,8 @@ default-preferences pref(dom.experimental_forms_range,true) == input-valueAsNumber-prop.html input-75pct-common-ref.html fails-if(B2G) == input-stepDown-unthemed.html input-75pct-unthemed-common-ref.html fails-if(B2G) == input-stepDown.html input-75pct-common-ref.html -fails-if(B2G) == input-stepUp-unthemed.html input-75pct-unthemed-common-ref.html -fails-if(B2G) == input-stepUp.html input-75pct-common-ref.html +== input-stepUp-unthemed.html input-75pct-unthemed-common-ref.html +== input-stepUp.html input-75pct-common-ref.html # 'direction' property: == input-range-direction-unthemed-1.html input-range-direction-unthemed-1-ref.html diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 56d40f0b5880..2017a2984e68 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -25,6 +25,7 @@ #include "mozilla/Preferences.h" #include "nsContentUtils.h" #include "nsLayoutUtils.h" +#include "mozilla/layers/Compositor.h" /** XXX TODO XXX @@ -42,6 +43,8 @@ we ask for a specific z-order, we don't assume that widget z-ordering actually works. */ +using namespace mozilla::layers; + #define NSCOORD_NONE INT32_MIN #undef DEBUG_MOUSE_LOCATION @@ -330,8 +333,14 @@ void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion) printf("--COMPOSITE-- %p\n", mPresShell); } #endif - mPresShell->Paint(aView, damageRegion, - nsIPresShell::PAINT_COMPOSITE); + uint32_t paintFlags = nsIPresShell::PAINT_COMPOSITE; + LayerManager *manager = widget->GetLayerManager(); + if (!manager->NeedsWidgetInvalidation()) { + manager->FlushRendering(); + } else { + mPresShell->Paint(aView, damageRegion, + paintFlags); + } #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { printf("--ENDCOMPOSITE--\n"); From ac3c3cd4586d8c0c17aa4ba2ea3518ce15c4ae96 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Tue, 18 Jun 2013 19:59:46 +1200 Subject: [PATCH 447/615] Bug 876626 - Always redraw the entire reftest canvas for async animations tests. r=roc --- layout/reftests/bugs/598726-1.html | 4 ++-- layout/tools/reftest/reftest-content.js | 24 ++++++++++++++++++++++-- layout/tools/reftest/reftest.js | 21 +++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/layout/reftests/bugs/598726-1.html b/layout/reftests/bugs/598726-1.html index c2c22365222a..63248805da33 100644 --- a/layout/reftests/bugs/598726-1.html +++ b/layout/reftests/bugs/598726-1.html @@ -1,5 +1,5 @@ - +