From 721fe4a8ffcc4cc0b01314c9482ee9aa1cd49d6f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 09:51:49 +0100 Subject: [PATCH 001/160] Bug 1245093: Explictly refer to |class ResponseCode| in global namespace, r=dhylands |VolumeResponseCallback::ResponseCode| shadows the type |ResponseCode|. This patch changes all affected places to refer explicitly to the |ResponseCode| type in the global namespace. --- dom/system/gonk/VolumeCommand.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dom/system/gonk/VolumeCommand.h b/dom/system/gonk/VolumeCommand.h index a2e7c69b82b..022965b5e02 100644 --- a/dom/system/gonk/VolumeCommand.h +++ b/dom/system/gonk/VolumeCommand.h @@ -48,13 +48,13 @@ public: // Response codes from the 200, 400, and 500 series all indicated that // the command has completed. - return (mResponseCode >= ResponseCode::CommandOkay) - && (mResponseCode < ResponseCode::UnsolicitedInformational); + return (mResponseCode >= ::ResponseCode::CommandOkay) + && (mResponseCode < ::ResponseCode::UnsolicitedInformational); } bool WasSuccessful() const { - return mResponseCode == ResponseCode::CommandOkay; + return mResponseCode == ::ResponseCode::CommandOkay; } bool IsPending() const { return mPending; } @@ -79,7 +79,7 @@ private: #else mResponseStr = aResponseStr; #endif - if (mResponseCode >= ResponseCode::CommandOkay) { + if (mResponseCode >= ::ResponseCode::CommandOkay) { // This is a final response. mPending = false; } From e0bb65e0d9ce49116cad6a1323758db8d6809bd4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 09:52:24 +0100 Subject: [PATCH 002/160] Bug 1245100: Include missing headers in SystemProperty.cpp, r=edgar --- dom/system/gonk/SystemProperty.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dom/system/gonk/SystemProperty.cpp b/dom/system/gonk/SystemProperty.cpp index 6fd1e86666c..1f874ce908b 100644 --- a/dom/system/gonk/SystemProperty.cpp +++ b/dom/system/gonk/SystemProperty.cpp @@ -5,8 +5,11 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SystemProperty.h" -#include +#include +#include + +#include "nsDebug.h" #include "prinit.h" namespace mozilla { From 1ebb17479d539067d8bb67fcb6716d6407451ef5 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 3 Feb 2016 09:22:58 +0000 Subject: [PATCH 003/160] Bug 1244693 - On Beta/Release channels, allow OpenType Layout tables (GDEF/GPOS/GSUB) to pass through OTS unchecked, relying on harfbuzz to handle them safely. r=jdaggett --- gfx/thebes/gfxUserFontSet.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp index 302ffa8913c..a1acf253188 100644 --- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -178,8 +178,15 @@ public: : mUserFontEntry(aUserFontEntry) {} virtual ots::TableAction GetTableAction(uint32_t aTag) override { - // preserve Graphite, color glyph and SVG tables - if (aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') || + // Preserve Graphite, color glyph and SVG tables + if ( +#ifdef RELEASE_BUILD // For Beta/Release, also allow OT Layout tables through + // unchecked, and rely on harfbuzz to handle them safely. + aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') || + aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') || + aTag == TRUETYPE_TAG('G', 'S', 'U', 'B') || +#endif + aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') || aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') || aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') || aTag == TRUETYPE_TAG('G', 'l', 'a', 't') || From 1012db254c2181dba3cbe22a3cff877037e89c80 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 3 Feb 2016 09:24:24 +0000 Subject: [PATCH 004/160] Bug 1243125 - patch 0 - Relax overly-harsh writing mode assertions in nsReflowMetrics size accessors. r=dholbert --- layout/generic/nsHTMLReflowMetrics.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsHTMLReflowMetrics.h b/layout/generic/nsHTMLReflowMetrics.h index 94df2cc8fb9..a2a32f5de15 100644 --- a/layout/generic/nsHTMLReflowMetrics.h +++ b/layout/generic/nsHTMLReflowMetrics.h @@ -219,24 +219,29 @@ public: // width in horizontal writing modes, height in vertical ones), and BSize is // the size in the block-progression direction. nscoord ISize(mozilla::WritingMode aWritingMode) const { - CHECK_WRITING_MODE(aWritingMode); + NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode), + "mismatched writing mode"); return mISize; } nscoord BSize(mozilla::WritingMode aWritingMode) const { - CHECK_WRITING_MODE(aWritingMode); + NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode), + "mismatched writing mode"); return mBSize; } mozilla::LogicalSize Size(mozilla::WritingMode aWritingMode) const { - CHECK_WRITING_MODE(aWritingMode); + NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode), + "mismatched writing mode"); return mozilla::LogicalSize(aWritingMode, mISize, mBSize); } nscoord& ISize(mozilla::WritingMode aWritingMode) { - CHECK_WRITING_MODE(aWritingMode); + NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode), + "mismatched writing mode"); return mISize; } nscoord& BSize(mozilla::WritingMode aWritingMode) { - CHECK_WRITING_MODE(aWritingMode); + NS_ASSERTION(!aWritingMode.IsOrthogonalTo(mWritingMode), + "mismatched writing mode"); return mBSize; } From e128e82c8ea5763782fcce02564dfcb7b8352d54 Mon Sep 17 00:00:00 2001 From: Oriol Date: Wed, 3 Feb 2016 09:24:26 +0000 Subject: [PATCH 005/160] Bug 1243125 - patch 1 - Check block size instead of height when detecting truncated frames. r=jfkthame --- layout/generic/nsHTMLReflowState.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 801144b65d4..fd2b6888bba 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -2925,8 +2925,8 @@ void nsHTMLReflowState::SetTruncated(const nsHTMLReflowMetrics& aMetrics, nsReflowStatus* aStatus) const { - if (AvailableHeight() != NS_UNCONSTRAINEDSIZE && - AvailableHeight() < aMetrics.Height() && + if (AvailableBSize() != NS_UNCONSTRAINEDSIZE && + AvailableBSize() < aMetrics.BSize(GetWritingMode()) && !mFlags.mIsTopOfPage) { *aStatus |= NS_FRAME_TRUNCATED; } else { From e3f9bcd043f9b4b5144c7c16569355a88859270b Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 3 Feb 2016 09:24:28 +0000 Subject: [PATCH 006/160] Bug 1243125 - patch 2 - Don't ever set NS_FRAME_TRUNCATED for orthogonal flows. r=dholbert --- layout/generic/nsHTMLReflowState.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index fd2b6888bba..d2a46cdcc0c 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -2925,9 +2925,14 @@ void nsHTMLReflowState::SetTruncated(const nsHTMLReflowMetrics& aMetrics, nsReflowStatus* aStatus) const { - if (AvailableBSize() != NS_UNCONSTRAINEDSIZE && - AvailableBSize() < aMetrics.BSize(GetWritingMode()) && - !mFlags.mIsTopOfPage) { + const WritingMode containerWM = aMetrics.GetWritingMode(); + if (GetWritingMode().IsOrthogonalTo(containerWM)) { + // Orthogonal flows are always reflowed with an unconstrained dimension, + // so should never end up truncated (see nsHTMLReflowState::Init()). + *aStatus &= ~NS_FRAME_TRUNCATED; + } else if (AvailableBSize() != NS_UNCONSTRAINEDSIZE && + AvailableBSize() < aMetrics.BSize(containerWM) && + !mFlags.mIsTopOfPage) { *aStatus |= NS_FRAME_TRUNCATED; } else { *aStatus &= ~NS_FRAME_TRUNCATED; From 40e44079a4f649abb32cb206a8a10ada05d5f740 Mon Sep 17 00:00:00 2001 From: Oriol Date: Wed, 3 Feb 2016 09:24:29 +0000 Subject: [PATCH 007/160] Bug 1243125 - Reftest for floats overflowing container, with diverse writing-modes. r=jfkthame --- .../1243125-1-floats-overflowing-ref.html | 31 ++++++++++++++ .../1243125-1-floats-overflowing.html | 40 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 2 + 3 files changed, 73 insertions(+) create mode 100644 layout/reftests/writing-mode/1243125-1-floats-overflowing-ref.html create mode 100644 layout/reftests/writing-mode/1243125-1-floats-overflowing.html diff --git a/layout/reftests/writing-mode/1243125-1-floats-overflowing-ref.html b/layout/reftests/writing-mode/1243125-1-floats-overflowing-ref.html new file mode 100644 index 00000000000..35b2d8239a3 --- /dev/null +++ b/layout/reftests/writing-mode/1243125-1-floats-overflowing-ref.html @@ -0,0 +1,31 @@ + + + + Bug 1243125 testcase + + + + +

There should be 9 green bars

+ +
+
+
+ +
+
+
+ +
+
+
+ + diff --git a/layout/reftests/writing-mode/1243125-1-floats-overflowing.html b/layout/reftests/writing-mode/1243125-1-floats-overflowing.html new file mode 100644 index 00000000000..463396fbf24 --- /dev/null +++ b/layout/reftests/writing-mode/1243125-1-floats-overflowing.html @@ -0,0 +1,40 @@ + + + + Bug 1243125 testcase + + + + +

There should be 9 green bars

+ +
+
+
+ +
+
+
+ +
+
+
+ + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 05464d7ae4c..17fa6c85202 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -167,6 +167,8 @@ fuzzy-if(gtkWidget||B2G,255,6) fuzzy-if(cocoaWidget,65,69) == 1193519-sideways-l == 1216747-1.html 1216747-1-ref.html != 1216747-1.html 1216747-1-notref.html +== 1243125-1-floats-overflowing.html 1243125-1-floats-overflowing-ref.html + # Suite of tests from GĂ©rard Talbot in bug 1079151 # Frequent Windows 7 load failed: timed out waiting for test to complete (waiting for onload scripts to complete), bug 1167155 and friends skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) include abspos/reftest.list From 255899bcebd9f3b31cd2f0197bf67985c8aecd28 Mon Sep 17 00:00:00 2001 From: Edwin Flores Date: Wed, 3 Feb 2016 09:59:22 +0000 Subject: [PATCH 008/160] Bug 1227548 - Check the result of MakeCurrent in ReadBuffer and DrawBuffer destructors - r=jgilbert --- gfx/gl/GLScreenBuffer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp index f67b283365b..1739afb324b 100755 --- a/gfx/gl/GLScreenBuffer.cpp +++ b/gfx/gl/GLScreenBuffer.cpp @@ -846,7 +846,8 @@ DrawBuffer::Create(GLContext* const gl, DrawBuffer::~DrawBuffer() { - mGL->MakeCurrent(); + if (!mGL->MakeCurrent()) + return; GLuint fb = mFB; GLuint rbs[] = { @@ -923,7 +924,8 @@ ReadBuffer::Create(GLContext* gl, ReadBuffer::~ReadBuffer() { - mGL->MakeCurrent(); + if (!mGL->MakeCurrent()) + return; GLuint fb = mFB; GLuint rbs[] = { From e43291b0a7e4fa39b0efda443c07e00dffaf9012 Mon Sep 17 00:00:00 2001 From: Hector Zhao Date: Tue, 26 Jan 2016 23:10:36 +0800 Subject: [PATCH 009/160] Bug 1242973 - Make services/mobileid eslintable. r=ferjm --- services/mobileid/MobileIdentityManager.jsm | 298 +++++++++--------- .../MobileIdentitySmsVerificationFlow.jsm | 105 +++--- services/mobileid/moz.build | 7 +- 3 files changed, 210 insertions(+), 200 deletions(-) diff --git a/services/mobileid/MobileIdentityManager.jsm b/services/mobileid/MobileIdentityManager.jsm index 77d99def065..480c601fbd7 100644 --- a/services/mobileid/MobileIdentityManager.jsm +++ b/services/mobileid/MobileIdentityManager.jsm @@ -8,6 +8,7 @@ this.EXPORTED_SYMBOLS = ["MobileIdentityManager"]; const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.import("resource://gre/modules/AppConstants.jsm"); Cu.import("resource://gre/modules/MobileIdentityCommon.jsm"); Cu.import("resource://gre/modules/MobileIdentityUIGlueCommon.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); @@ -51,19 +52,19 @@ XPCOMUtils.defineLazyServiceGetter(this, "appsService", "@mozilla.org/AppsService;1", "nsIAppsService"); -#ifdef MOZ_B2G_RIL -XPCOMUtils.defineLazyServiceGetter(this, "Ril", - "@mozilla.org/ril;1", - "nsIRadioInterfaceLayer"); +if (AppConstants.MOZ_B2G_RIL) { + XPCOMUtils.defineLazyServiceGetter(this, "Ril", + "@mozilla.org/ril;1", + "nsIRadioInterfaceLayer"); -XPCOMUtils.defineLazyServiceGetter(this, "IccService", - "@mozilla.org/icc/iccservice;1", - "nsIIccService"); + XPCOMUtils.defineLazyServiceGetter(this, "IccService", + "@mozilla.org/icc/iccservice;1", + "nsIIccService"); -XPCOMUtils.defineLazyServiceGetter(this, "MobileConnectionService", - "@mozilla.org/mobileconnection/mobileconnectionservice;1", - "nsIMobileConnectionService"); -#endif + XPCOMUtils.defineLazyServiceGetter(this, "MobileConnectionService", + "@mozilla.org/mobileconnection/mobileconnectionservice;1", + "nsIMobileConnectionService"); +} this.MobileIdentityManager = { @@ -107,156 +108,132 @@ this.MobileIdentityManager = { /********************************************************* * Getters ********************************************************/ -#ifdef MOZ_B2G_RIL - // We have these getters to allow mocking RIL stuff from the tests. - get ril() { - if (this._ril) { - return this._ril; - } - return Ril; - }, - - get iccService() { - if (this._iccService) { - return this._iccService; - } - return IccService; - }, - - get mobileConnectionService() { - if (this._mobileConnectionService) { - return this._mobileConnectionService; - } - return MobileConnectionService; - }, -#endif - get iccInfo() { if (this._iccInfo) { return this._iccInfo; } -#ifdef MOZ_B2G_RIL - let self = this; - let iccListener = { - notifyStkCommand: function() {}, + if (AppConstants.MOZ_B2G_RIL) { + let self = this; + let iccListener = { + notifyStkCommand: function() {}, - notifyStkSessionEnd: function() {}, + notifyStkSessionEnd: function() {}, - notifyCardStateChanged: function() {}, + notifyCardStateChanged: function() {}, - notifyIccInfoChanged: function() { - // If we receive a notification about an ICC info change, we clear - // the ICC related caches so they can be rebuilt with the new changes. + notifyIccInfoChanged: function() { + // If we receive a notification about an ICC info change, we clear + // the ICC related caches so they can be rebuilt with the new changes. - log.debug("ICC info changed observed. Clearing caches"); + log.debug("ICC info changed observed. Clearing caches"); - // We don't need to keep listening for changes until we rebuild the - // cache again. - for (let i = 0; i < self._iccInfo.length; i++) { - let icc = self.iccService.getIccByServiceId(i); - if (icc) { - icc.unregisterListener(iccListener); + // We don't need to keep listening for changes until we rebuild the + // cache again. + for (let i = 0; i < self._iccInfo.length; i++) { + let icc = self.iccService.getIccByServiceId(i); + if (icc) { + icc.unregisterListener(iccListener); + } } + + self._iccInfo = null; + self._iccIds = null; + } + }; + + // _iccInfo is a local cache containing the information about the SIM cards + // that is interesting for the Mobile ID flow. + // The index of this array does not necesarily need to match the real + // identifier of the SIM card ("clientId" or "serviceId" in RIL language). + this._iccInfo = []; + + for (let i = 0; i < this.ril.numRadioInterfaces; i++) { + let icc = this.iccService.getIccByServiceId(i); + if (!icc) { + log.warn("Tried to get the Icc instance for an invalid service ID " + i); + continue; } - self._iccInfo = null; - self._iccIds = null; - } - }; - - // _iccInfo is a local cache containing the information about the SIM cards - // that is interesting for the Mobile ID flow. - // The index of this array does not necesarily need to match the real - // identifier of the SIM card ("clientId" or "serviceId" in RIL language). - this._iccInfo = []; - - for (let i = 0; i < this.ril.numRadioInterfaces; i++) { - let icc = this.iccService.getIccByServiceId(i); - if (!icc) { - log.warn("Tried to get the Icc instance for an invalid service ID " + i); - continue; - } - - let info = icc.iccInfo; - if (!info || !info.iccid || - !info.mcc || !info.mcc.length || - !info.mnc || !info.mnc.length) { - log.warn("Absent or invalid ICC info"); - continue; - } - - // GSM SIMs may have MSISDN while CDMA SIMs may have MDN - let phoneNumber = null; - try { - if (info.iccType === "sim" || info.iccType === "usim") { - let gsmInfo = info.QueryInterface(Ci.nsIGsmIccInfo); - phoneNumber = gsmInfo.msisdn; - } else if (info.iccType === "ruim" || info.iccType === "csim") { - let cdmaInfo = info.QueryInterface(Ci.nsICdmaIccInfo); - phoneNumber = cdmaInfo.mdn; + let info = icc.iccInfo; + if (!info || !info.iccid || + !info.mcc || !info.mcc.length || + !info.mnc || !info.mnc.length) { + log.warn("Absent or invalid ICC info"); + continue; } - } catch (e) { - log.error("Failed to retrieve phoneNumber: " + e); + + // GSM SIMs may have MSISDN while CDMA SIMs may have MDN + let phoneNumber = null; + try { + if (info.iccType === "sim" || info.iccType === "usim") { + let gsmInfo = info.QueryInterface(Ci.nsIGsmIccInfo); + phoneNumber = gsmInfo.msisdn; + } else if (info.iccType === "ruim" || info.iccType === "csim") { + let cdmaInfo = info.QueryInterface(Ci.nsICdmaIccInfo); + phoneNumber = cdmaInfo.mdn; + } + } catch (e) { + log.error("Failed to retrieve phoneNumber: " + e); + } + + let connection = this.mobileConnectionService.getItemByServiceId(i); + let voice = connection && connection.voice; + let data = connection && connection.data; + let operator = null; + if (voice && + voice.network && + voice.network.shortName && + voice.network.shortName.length) { + operator = voice.network.shortName; + } else if (data && + data.network && + data.network.shortName && + data.network.shortName.length) { + operator = data.network.shortName; + } + + this._iccInfo.push({ + // Because it is possible that the _iccInfo array index doesn't match + // the real client ID, we need to store this value for later usage. + clientId: i, + iccId: info.iccid, + mcc: info.mcc, + mnc: info.mnc, + msisdn: phoneNumber, + operator: operator, + roaming: voice && voice.roaming + }); + + // We need to subscribe to ICC change notifications so we can refresh + // the cache if any change is observed. + icc.registerListener(iccListener); } - let connection = this.mobileConnectionService.getItemByServiceId(i); - let voice = connection && connection.voice; - let data = connection && connection.data; - let operator = null; - if (voice && - voice.network && - voice.network.shortName && - voice.network.shortName.length) { - operator = voice.network.shortName; - } else if (data && - data.network && - data.network.shortName && - data.network.shortName.length) { - operator = data.network.shortName; - } - - this._iccInfo.push({ - // Because it is possible that the _iccInfo array index doesn't match - // the real client ID, we need to store this value for later usage. - clientId: i, - iccId: info.iccid, - mcc: info.mcc, - mnc: info.mnc, - msisdn: phoneNumber, - operator: operator, - roaming: voice && voice.roaming - }); - - // We need to subscribe to ICC change notifications so we can refresh - // the cache if any change is observed. - icc.registerListener(iccListener); + return this._iccInfo; + } else { + return null; } - - return this._iccInfo; -#else - return null; -#endif }, get iccIds() { -#ifdef MOZ_B2G_RIL - if (this._iccIds) { + if (AppConstants.MOZ_B2G_RIL) { + if (this._iccIds) { + return this._iccIds; + } + + this._iccIds = []; + if (!this.iccInfo) { + return this._iccIds; + } + + for (let i = 0; i < this.iccInfo.length; i++) { + this._iccIds.push(this.iccInfo[i].iccId); + } + return this._iccIds; + } else { + return null; } - - this._iccIds = []; - if (!this.iccInfo) { - return this._iccIds; - } - - for (let i = 0; i < this.iccInfo.length; i++) { - this._iccIds.push(this.iccInfo[i].iccId); - } - - return this._iccIds; -#else - return null; -#endif }, get credStore() { @@ -551,8 +528,8 @@ this.MobileIdentityManager = { this.ui, this.client ); -#ifdef MOZ_B2G_RIL - } else if (aToVerify.verificationMethod.indexOf(SMS_MO_MT) != -1 && + } else if (AppConstants.MOZ_B2G_RIL && + aToVerify.verificationMethod.indexOf(SMS_MO_MT) != -1 && aToVerify.serviceId && aToVerify.verificationDetails && aToVerify.verificationDetails.moVerifier && @@ -567,7 +544,6 @@ this.MobileIdentityManager = { this.ui, this.client ); -#endif } else { return Promise.reject(ERROR_INTERNAL_CANNOT_VERIFY_SELECTION); } @@ -1068,4 +1044,40 @@ this.MobileIdentityManager = { }; +if (AppConstants.MOZ_B2G_RIL) { + // We have these getters to allow mocking RIL stuff from the tests. + Object.defineProperties(MobileIdentityManager, { + "ril": { + configurable: true, + enumerable: true, + get() { + if (this._ril) { + return this._ril; + } + return Ril; + } + }, + "iccService": { + configurable: true, + enumerable: true, + get() { + if (this._iccService) { + return this._iccService; + } + return IccService; + } + }, + "mobileConnectionService": { + configurable: true, + enumerable: true, + get() { + if (this._mobileConnectionService) { + return this._mobileConnectionService; + } + return MobileConnectionService; + } + } + }); +} + MobileIdentityManager.init(); diff --git a/services/mobileid/MobileIdentitySmsVerificationFlow.jsm b/services/mobileid/MobileIdentitySmsVerificationFlow.jsm index 2e1826a56d9..99f90706562 100644 --- a/services/mobileid/MobileIdentitySmsVerificationFlow.jsm +++ b/services/mobileid/MobileIdentitySmsVerificationFlow.jsm @@ -8,16 +8,17 @@ this.EXPORTED_SYMBOLS = ["MobileIdentitySmsVerificationFlow"]; const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +Cu.import("resource://gre/modules/AppConstants.jsm"); Cu.import("resource://gre/modules/MobileIdentityCommon.jsm"); Cu.import("resource://gre/modules/MobileIdentityVerificationFlow.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -#ifdef MOZ_B2G_RIL -XPCOMUtils.defineLazyServiceGetter(this, "smsService", - "@mozilla.org/sms/smsservice;1", - "nsISmsService"); -#endif +if (AppConstants.MOZ_B2G_RIL) { + XPCOMUtils.defineLazyServiceGetter(this, "smsService", + "@mozilla.org/sms/smsservice;1", + "nsISmsService"); +} this.MobileIdentitySmsVerificationFlow = function(aVerificationOptions, aUI, @@ -51,58 +52,58 @@ this.MobileIdentitySmsVerificationFlow.prototype = { // is unknown for us, so we always observe for incoming messages coming // from the given mtSender. -#ifdef MOZ_B2G_RIL - this.observedSilentNumber = this.verificationOptions.mtSender; - try { - smsService.addSilentNumber(this.observedSilentNumber); - } catch (e) { - log.warn("We are already listening for that number"); + if (AppConstants.MOZ_B2G_RIL) { + this.observedSilentNumber = this.verificationOptions.mtSender; + try { + smsService.addSilentNumber(this.observedSilentNumber); + } catch (e) { + log.warn("We are already listening for that number"); + } + + this.onSilentSms = (function(aSubject, aTopic, aData) { + log.debug("Got silent message " + aSubject.sender + " - " + aSubject.body); + // We might have observed a notification of an incoming silent message + // for other number. In that case, we just bail out. + if (aSubject.sender != this.observedSilentNumber) { + return; + } + + // We got the SMS containing the verification code. + + // If the phone number we are trying to verify is or can be an external + // phone number (meaning that it doesn't belong to any of the inserted + // SIMs) we will be receiving an human readable SMS containing a short + // verification code. In this case we need to parse the SMS body to + // extract the verification code. + // Otherwise, we just use the whole SMS body as it should contain a long + // verification code. + let verificationCode = aSubject.body; + if (this.verificationOptions.external) { + // We just take the numerical characters from the body. + verificationCode = aSubject.body.replace(/[^0-9]/g,''); + } + + log.debug("Verification code: " + verificationCode); + + this.verificationCodeDeferred.resolve(verificationCode); + }).bind(this); + + Services.obs.addObserver(this.onSilentSms, + SILENT_SMS_RECEIVED_TOPIC, + false); + log.debug("Observing messages from " + this.observedSilentNumber); } - this.onSilentSms = (function(aSubject, aTopic, aData) { - log.debug("Got silent message " + aSubject.sender + " - " + aSubject.body); - // We might have observed a notification of an incoming silent message - // for other number. In that case, we just bail out. - if (aSubject.sender != this.observedSilentNumber) { - return; - } - - // We got the SMS containing the verification code. - - // If the phone number we are trying to verify is or can be an external - // phone number (meaning that it doesn't belong to any of the inserted - // SIMs) we will be receiving an human readable SMS containing a short - // verification code. In this case we need to parse the SMS body to - // extract the verification code. - // Otherwise, we just use the whole SMS body as it should contain a long - // verification code. - let verificationCode = aSubject.body; - if (this.verificationOptions.external) { - // We just take the numerical characters from the body. - verificationCode = aSubject.body.replace(/[^0-9]/g,''); - } - - log.debug("Verification code: " + verificationCode); - - this.verificationCodeDeferred.resolve(verificationCode); - }).bind(this); - - Services.obs.addObserver(this.onSilentSms, - SILENT_SMS_RECEIVED_TOPIC, - false); - log.debug("Observing messages from " + this.observedSilentNumber); -#endif - return this.smsVerifyStrategy(); }, _cleanupStrategy: function() { -#ifdef MOZ_B2G_RIL - smsService.removeSilentNumber(this.observedSilentNumber); - Services.obs.removeObserver(this.onSilentSms, - SILENT_SMS_RECEIVED_TOPIC); - this.observedSilentNumber = null; - this.onSilentSms = null; -#endif + if (AppConstants.MOZ_B2G_RIL) { + smsService.removeSilentNumber(this.observedSilentNumber); + Services.obs.removeObserver(this.onSilentSms, + SILENT_SMS_RECEIVED_TOPIC); + this.observedSilentNumber = null; + this.onSilentSms = null; + } } }; diff --git a/services/mobileid/moz.build b/services/mobileid/moz.build index e18d282b11b..908e3f852e0 100644 --- a/services/mobileid/moz.build +++ b/services/mobileid/moz.build @@ -12,13 +12,10 @@ EXTRA_JS_MODULES += [ 'MobileIdentityClient.jsm', 'MobileIdentityCommon.jsm', 'MobileIdentityCredentialsStore.jsm', + 'MobileIdentityManager.jsm', 'MobileIdentitySmsMoMtVerificationFlow.jsm', 'MobileIdentitySmsMtVerificationFlow.jsm', + 'MobileIdentitySmsVerificationFlow.jsm', 'MobileIdentityUIGlueCommon.jsm', 'MobileIdentityVerificationFlow.jsm' ] - -EXTRA_PP_JS_MODULES += [ - 'MobileIdentityManager.jsm', - 'MobileIdentitySmsVerificationFlow.jsm' -] From 969da3f3c87d099754f5066a2e580531e5d8f9a8 Mon Sep 17 00:00:00 2001 From: Hector Zhao Date: Tue, 2 Feb 2016 10:37:50 +0800 Subject: [PATCH 010/160] Bug 1242977 - Make services eslintable. r=markh --- .eslintignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.eslintignore b/.eslintignore index 86e31991e58..545843dd9ae 100644 --- a/.eslintignore +++ b/.eslintignore @@ -39,7 +39,6 @@ parser/** probes/** python/** rdf/** -services/** startupcache/** testing/** tools/** @@ -170,6 +169,11 @@ mobile/android/components/Snippets.js # Bug 1178739: Ignore this file as a quick fix for "Illegal yield expression" mobile/android/modules/HomeProvider.jsm +# services/ exclusions + +# Uses `#filter substitution` +services/sync/modules/constants.js + # toolkit/ exclusions # Not part of the default build From 47ff04b9c58e13ae92b7263cf7037725a4c32757 Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 2 Feb 2016 07:21:00 +0100 Subject: [PATCH 011/160] Bug 885952 - Add thread name to MozLogging, r=froydnj --- xpcom/base/Logging.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/xpcom/base/Logging.cpp b/xpcom/base/Logging.cpp index 2679b9378a0..2223f1b4bfb 100644 --- a/xpcom/base/Logging.cpp +++ b/xpcom/base/Logging.cpp @@ -86,6 +86,7 @@ public: : mModulesLock("logmodules") , mModules(kInitialModuleCount) , mOutFile(nullptr) + , mMainThread(PR_GetCurrentThread()) , mAddTimestamp(false) , mIsSync(false) { @@ -176,20 +177,31 @@ public: // // Additionally we prefix the output with the abbreviated log level // and the module name. + PRThread *currentThread = PR_GetCurrentThread(); + const char *currentThreadName = (mMainThread == currentThread) + ? "Main Thread" + : PR_GetThreadName(currentThread); + + char noNameThread[40]; + if (!currentThreadName) { + snprintf_literal(noNameThread, "Unnamed thread %p", currentThread); + currentThreadName = noNameThread; + } + if (!mAddTimestamp) { fprintf_stderr(out, - "[%p]: %s/%s %s%s", - PR_GetCurrentThread(), ToLogStr(aLevel), + "[%s]: %s/%s %s%s", + currentThreadName, ToLogStr(aLevel), aName, buffToWrite, newline); } else { PRExplodedTime now; PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); fprintf_stderr( out, - "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%p]: %s/%s %s%s", + "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%s]: %s/%s %s%s", now.tm_year, now.tm_month + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec, - PR_GetCurrentThread(), ToLogStr(aLevel), + currentThreadName, ToLogStr(aLevel), aName, buffToWrite, newline); } @@ -206,6 +218,7 @@ private: OffTheBooksMutex mModulesLock; nsClassHashtable mModules; ScopedCloseFile mOutFile; + PRThread *mMainThread; bool mAddTimestamp; bool mIsSync; }; From 119e5681dbf43ef2f2ce511030f1900d73d0ac9c Mon Sep 17 00:00:00 2001 From: Honza Bambas Date: Tue, 2 Feb 2016 06:43:00 +0100 Subject: [PATCH 012/160] Bug 1136857 - Make DOMStorageCache::mLoaded flag atomic to prevent potential races, r=nfroyd --- dom/storage/DOMStorageCache.cpp | 11 +++++++++-- dom/storage/DOMStorageCache.h | 6 ++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/dom/storage/DOMStorageCache.cpp b/dom/storage/DOMStorageCache.cpp index c2f049569b2..4c84ac0dcbb 100644 --- a/dom/storage/DOMStorageCache.cpp +++ b/dom/storage/DOMStorageCache.cpp @@ -564,9 +564,16 @@ DOMStorageCache::Clear(const DOMStorage* aStorage) void DOMStorageCache::CloneFrom(const DOMStorageCache* aThat) { - mLoaded = aThat->mLoaded; + // This will never be called on anything else than SessionStorage. + // This means mData will never be touched on any other thread than + // the main thread and it never went through the loading process. + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mPersistent); + MOZ_ASSERT(!(bool)aThat->mLoaded); + + mLoaded = false; mInitialized = aThat->mInitialized; - mPersistent = aThat->mPersistent; + mPersistent = false; mSessionOnlyDataSetActive = aThat->mSessionOnlyDataSetActive; for (uint32_t i = 0; i < kDataSetCount; ++i) { diff --git a/dom/storage/DOMStorageCache.h b/dom/storage/DOMStorageCache.h index 3ee3ce1e5c7..2bd4737f45b 100644 --- a/dom/storage/DOMStorageCache.h +++ b/dom/storage/DOMStorageCache.h @@ -15,6 +15,7 @@ #include "nsHashKeys.h" #include "mozilla/Monitor.h" #include "mozilla/Telemetry.h" +#include "mozilla/Atomics.h" #include "nsAutoPtr.h" namespace mozilla { @@ -220,8 +221,9 @@ private: // Flag that is initially false. When the cache is about to work with // the database (i.e. it is persistent) this flags is set to true after // all keys and coresponding values are loaded from the database. - // This flag never goes from true back to false. - bool mLoaded; + // This flag never goes from true back to false. Since this flag is + // critical for mData hashtable synchronization, it's made atomic. + Atomic mLoaded; // Result of load from the database. Valid after mLoaded flag has been set. nsresult mLoadResult; From 2413ec54fb62ccdefac8c1449b9a9b7efcd60621 Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Tue, 2 Feb 2016 11:05:00 +0100 Subject: [PATCH 013/160] Bug 1187464 - Part 1. We can get the wrong texture source type, so deal with it. r=mstange --- gfx/2d/Logging.h | 1 + gfx/layers/basic/BasicCompositor.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gfx/2d/Logging.h b/gfx/2d/Logging.h index 11c3390f46e..ad5c3c6892a 100644 --- a/gfx/2d/Logging.h +++ b/gfx/2d/Logging.h @@ -131,6 +131,7 @@ enum class LogReason : int { GlyphAllocFailedCG, InvalidRect, CannotDraw3D, // 20 + IncompatibleBasicTexturedEffect, // End MustBeLessThanThis = 101, }; diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 8191d7190d4..05b92a614ea 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -430,14 +430,14 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, static_cast(aEffectChain.mPrimaryEffect.get()); TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic(); - if (texturedEffect->mPremultiplied) { + if (source && texturedEffect->mPremultiplied) { DrawSurfaceWithTextureCoords(dest, aRect, source->GetSurface(dest), texturedEffect->mTextureCoords, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); - } else { + } else if (source) { RefPtr srcData = source->GetSurface(dest)->GetDataSurface(); // Yes, we re-create the premultiplied data every time. @@ -450,7 +450,10 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); + } else { + gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic"; } + break; } case EffectTypes::YCBCR: { From e324817371fc74578bece9369a38a5f8c06102f4 Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Tue, 2 Feb 2016 11:06:00 +0100 Subject: [PATCH 014/160] Bug 1187464 - Part 2. RTTI for TextureSource debug purposes. r=botond --- gfx/layers/basic/BasicCompositor.cpp | 3 ++- gfx/layers/basic/BasicCompositor.h | 2 ++ gfx/layers/basic/MacIOSurfaceTextureHostBasic.h | 2 ++ gfx/layers/basic/X11BasicCompositor.h | 2 ++ gfx/layers/basic/X11TextureSourceBasic.h | 2 ++ gfx/layers/composite/TextureHost.cpp | 7 +++++++ gfx/layers/composite/TextureHost.h | 6 ++++++ gfx/layers/composite/X11TextureHost.h | 2 ++ gfx/layers/d3d11/TextureD3D11.h | 3 +++ gfx/layers/d3d9/TextureD3D9.h | 4 ++++ gfx/layers/opengl/CompositingRenderTargetOGL.h | 2 ++ gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h | 2 ++ gfx/layers/opengl/TextureHostOGL.h | 7 +++++++ 13 files changed, 43 insertions(+), 1 deletion(-) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 05b92a614ea..7c3a992a356 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -34,6 +34,7 @@ class DataTextureSourceBasic : public DataTextureSource , public TextureSourceBasic { public: + virtual const char* Name() const override { return "DataTextureSourceBasic"; } virtual TextureSourceBasic* AsSourceBasic() override { return this; } @@ -451,7 +452,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); } else { - gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic"; + gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name(); } break; diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index 05e64e2fcb1..dfc7d8491fc 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -23,6 +23,8 @@ public: , mSize(aRect.Size()) { } + virtual const char* Name() const override { return "BasicCompositingRenderTarget"; } + virtual gfx::IntSize GetSize() const override { return mSize; } void BindRenderTarget(); diff --git a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h index 19a8a707805..3dd6afb468f 100644 --- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h +++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h @@ -31,6 +31,8 @@ public: MacIOSurface* aSurface); virtual ~MacIOSurfaceTextureSourceBasic(); + virtual const char* Name() const override { return "MacIOSurfaceTextureSourceBasic"; } + virtual TextureSourceBasic* AsSourceBasic() override { return this; } virtual gfx::IntSize GetSize() const override; diff --git a/gfx/layers/basic/X11BasicCompositor.h b/gfx/layers/basic/X11BasicCompositor.h index 4e3cf037d8f..48d2f8e81cb 100644 --- a/gfx/layers/basic/X11BasicCompositor.h +++ b/gfx/layers/basic/X11BasicCompositor.h @@ -22,6 +22,8 @@ class X11DataTextureSourceBasic : public DataTextureSource public: X11DataTextureSourceBasic() {}; + virtual const char* Name() const override { return "X11DataTextureSourceBasic"; } + virtual bool Update(gfx::DataSourceSurface* aSurface, nsIntRegion* aDestRegion = nullptr, gfx::IntPoint* aSrcOffset = nullptr) override; diff --git a/gfx/layers/basic/X11TextureSourceBasic.h b/gfx/layers/basic/X11TextureSourceBasic.h index 92c9f6c63d0..f813560e04e 100644 --- a/gfx/layers/basic/X11TextureSourceBasic.h +++ b/gfx/layers/basic/X11TextureSourceBasic.h @@ -24,6 +24,8 @@ class X11TextureSourceBasic public: X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXlibSurface* aSurface); + virtual const char* Name() const override { return "X11TextureSourceBasic"; } + virtual X11TextureSourceBasic* AsSourceBasic() override { return this; } virtual gfx::IntSize GetSize() const override; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index dcf9278717c..75aa85b30fa 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -374,6 +374,13 @@ TextureSource::~TextureSource() MOZ_COUNT_DTOR(TextureSource); } +const char* +TextureSource::Name() const +{ + MOZ_CRASH("TextureSource without class name"); + return "TextureSource"; +} + BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc, TextureFlags aFlags) : TextureHost(aFlags) diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 4de69a787ab..4c4a882246a 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -88,6 +88,8 @@ public: virtual ~TextureSource(); + virtual const char* Name() const = 0; + /** * Should be overridden in order to deallocate the data that is associated * with the rendering backend, such as GL textures. @@ -233,6 +235,8 @@ public: : mUpdateSerial(0) {} + virtual const char* Name() const override { return "DataTextureSource"; } + virtual DataTextureSource* AsDataTextureSource() override { return this; } /** @@ -724,6 +728,8 @@ public: {} virtual ~CompositingRenderTarget() {} + virtual const char* Name() const override { return "CompositingRenderTarget"; } + #ifdef MOZ_DUMP_PAINTING virtual already_AddRefed Dump(Compositor* aCompositor) { return nullptr; } #endif diff --git a/gfx/layers/composite/X11TextureHost.h b/gfx/layers/composite/X11TextureHost.h index 4ac586f01b1..7c6cc7d72bb 100644 --- a/gfx/layers/composite/X11TextureHost.h +++ b/gfx/layers/composite/X11TextureHost.h @@ -21,6 +21,8 @@ public: // Called when the underlying X surface has been changed. // Useful for determining whether to rebind a GLXPixmap to a texture. virtual void Updated() = 0; + + virtual const char* Name() const override { return "X11TextureSource"; } }; // TextureHost for Xlib-backed TextureSources. diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index f4bc9f69582..1c91a3c06e4 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -253,6 +253,7 @@ public: virtual ~DataTextureSourceD3D11(); + virtual const char* Name() const override { return "DataTextureSourceD3D11"; } // DataTextureSource @@ -408,6 +409,8 @@ public: const gfx::IntPoint& aOrigin, DXGI_FORMAT aFormatOverride = DXGI_FORMAT_UNKNOWN); + virtual const char* Name() const override { return "CompositingRenderTargetD3D11"; } + virtual TextureSourceD3D11* AsSourceD3D11() override { return this; } void BindRenderTarget(ID3D11DeviceContext* aContext); diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index 83a1b0b0a45..4e341463a1f 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -112,6 +112,8 @@ public: virtual ~DataTextureSourceD3D9(); + virtual const char* Name() const override { return "DataTextureSourceD3D9"; } + // DataTextureSource virtual bool Update(gfx::DataSourceSurface* aSurface, @@ -398,6 +400,8 @@ public: const gfx::IntRect& aRect); virtual ~CompositingRenderTargetD3D9(); + virtual const char* Name() const override { return "CompositingRenderTargetD3D9"; } + virtual TextureSourceD3D9* AsSourceD3D9() override { MOZ_ASSERT(mTexture, diff --git a/gfx/layers/opengl/CompositingRenderTargetOGL.h b/gfx/layers/opengl/CompositingRenderTargetOGL.h index 3b6b055c522..cca94410a06 100644 --- a/gfx/layers/opengl/CompositingRenderTargetOGL.h +++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h @@ -77,6 +77,8 @@ public: ~CompositingRenderTargetOGL(); + virtual const char* Name() const override { return "CompositingRenderTargetOGL"; } + /** * Create a render target around the default FBO, for rendering straight to * the window. diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index f408244acc4..48250e1a9df 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -28,6 +28,8 @@ public: MacIOSurface* aSurface); virtual ~MacIOSurfaceTextureSourceOGL(); + virtual const char* Name() const override { return "MacIOSurfaceTextureSourceOGL"; } + virtual TextureSourceOGL* AsSourceOGL() override { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index efdc19a7ce3..5d6334a1fbe 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -142,6 +142,7 @@ public: , mIterating(false) {} + virtual const char* Name() const override { return "TextureImageTextureSourceOGL"; } // DataTextureSource virtual bool Update(gfx::DataSourceSurface* aSurface, @@ -237,6 +238,8 @@ public: ~GLTextureSource(); + virtual const char* Name() const override { return "GLTextureSource"; } + virtual GLTextureSource* AsGLTextureSource() override { return this; } virtual TextureSourceOGL* AsSourceOGL() override { return this; } @@ -344,6 +347,8 @@ public: GLenum aWrapMode, gfx::IntSize aSize); + virtual const char* Name() const override { return "SurfaceTextureSource"; } + virtual TextureSourceOGL* AsSourceOGL() { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; @@ -436,6 +441,8 @@ public: GLenum aWrapMode, gfx::IntSize aSize); + virtual const char* Name() const override { return "EGLImageTextureSource"; } + virtual TextureSourceOGL* AsSourceOGL() override { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; From 920f065175ee8a16bec1ab8a8bc899d2dcc2a9a0 Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Tue, 2 Feb 2016 11:07:00 +0100 Subject: [PATCH 015/160] Bug 1187464 - Part 3. Check if GetSurface returned null. r=mstange --- gfx/layers/basic/BasicCompositor.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 7c3a992a356..8febcc215ad 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -176,6 +176,11 @@ DrawSurfaceWithTextureCoords(DrawTarget *aDest, SourceSurface *aMask, const Matrix* aMaskTransform) { + if (!aSource || !aMask) { + gfxWarning() << "DrawSurfaceWithTextureCoords problem " << gfx::hexa(aSource) << " and " << gfx::hexa(aMask); + return; + } + // Convert aTextureCoords into aSource's coordinate space gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width, aTextureCoords.y * aSource->GetSize().height, @@ -397,6 +402,9 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { EffectMask *effectMask = static_cast(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest); + if (!sourceMask) { + gfxWarning() << "Invalid sourceMask effect"; + } MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!"); MOZ_ASSERT(!effectMask->mIs3D); maskTransform = effectMask->mMaskTransform.As2D(); @@ -439,7 +447,9 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); } else if (source) { - RefPtr srcData = source->GetSurface(dest)->GetDataSurface(); + SourceSurface* srcSurf = source->GetSurface(dest); + if (srcSurf) { + RefPtr srcData = srcSurf->GetDataSurface(); // Yes, we re-create the premultiplied data every time. // This might be better with a cache, eventually. @@ -451,8 +461,9 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); + } } else { - gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name(); + gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name() << " and " << gfx::hexa(sourceMask); } break; From a57552183104b6fc81336aae8e6345c2884809d5 Mon Sep 17 00:00:00 2001 From: James Graham Date: Tue, 2 Feb 2016 22:04:13 +0000 Subject: [PATCH 016/160] Bug 1245460 - Update web-platform-tests to revision af65262f5f3400024279c526117489f1f11d3233, a=testonly --- testing/web-platform/meta/MANIFEST.json | 66 +++- testing/web-platform/meta/mozilla-sync | 2 +- testing/web-platform/tests/DOMEvents/OWNERS | 3 + testing/web-platform/tests/FileAPI/OWNERS | 6 + testing/web-platform/tests/IndexedDB/OWNERS | 8 + .../web-platform/tests/WebCryptoAPI/OWNERS | 2 + .../web-platform/tests/XMLHttpRequest/OWNERS | 13 + .../responsexml-document-properties.htm | 2 +- .../web-platform/tests/ambient-light/OWNERS | 3 + testing/web-platform/tests/app-uri/OWNERS | 1 + testing/web-platform/tests/common/OWNERS | 4 + .../tests/conformance-checkers/OWNERS | 1 + .../tests/content-security-policy/OWNERS | 2 + testing/web-platform/tests/cors/OWNERS | 5 + testing/web-platform/tests/cssom-view/OWNERS | 1 + .../web-platform/tests/custom-elements/OWNERS | 3 + testing/web-platform/tests/docs/OWNERS | 4 + testing/web-platform/tests/dom/OWNERS | 6 + testing/web-platform/tests/domparsing/OWNERS | 5 + testing/web-platform/tests/domxpath/OWNERS | 3 + testing/web-platform/tests/editing/OWNERS | 1 + testing/web-platform/tests/encoding/OWNERS | 2 + testing/web-platform/tests/eventsource/OWNERS | 5 + testing/web-platform/tests/fetch/OWNERS | 2 + testing/web-platform/tests/gamepad/OWNERS | 1 + .../web-platform/tests/geolocation-API/OWNERS | 2 + testing/web-platform/tests/hr-time/OWNERS | 2 + .../web-platform/tests/html-imports/OWNERS | 1 + .../web-platform/tests/html-longdesc/OWNERS | 2 + .../tests/html-media-capture/OWNERS | 2 + testing/web-platform/tests/html/OWNERS | 1 + .../resources/blank1.html | 8 + .../resources/blank2.html | 8 + .../resources/page-with-fragment.html | 20 ++ .../scroll-restoration-basic.html | 34 +++ ...ation-fragment-scrolling-cross-origin.html | 67 ++++ ...estoration-fragment-scrolling-samedoc.html | 54 ++++ ...l-restoration-navigation-cross-origin.html | 71 +++++ ...scroll-restoration-navigation-samedoc.html | 81 +++++ .../tests/html/dom/interfaces.html | 3 + .../lists/li-type-supported-ref.html | 6 +- .../lists/li-type-supported.html | 6 +- .../lists/li-type-supported.xhtml | 6 +- .../the-embed-element/embed-document.html | 10 +- .../the-button-element/button-events.html | 16 +- .../forms/the-input-element/checkbox.html | 60 +++- .../forms/the-input-element/file-manual.html | 4 +- .../forms/the-input-element/radio.html | 58 ++-- .../events/event-handler-onresize.html | 38 +++ testing/web-platform/tests/images/OWNERS | 2 + .../web-platform/tests/media-source/OWNERS | 4 + testing/web-platform/tests/media/OWNERS | 2 + .../tests/mediacapture-streams/OWNERS | 3 + .../web-platform/tests/mixed-content/OWNERS | 1 + .../tests/navigation-timing/OWNERS | 2 + .../web-platform/tests/notifications/OWNERS | 4 + .../web-platform/tests/page-visibility/OWNERS | 2 + .../tests/performance-timeline/OWNERS | 1 + .../web-platform/tests/pointerevents/OWNERS | 7 + testing/web-platform/tests/pointerlock/OWNERS | 1 + testing/web-platform/tests/proximity/OWNERS | 2 + testing/web-platform/tests/quirks-mode/OWNERS | 1 + .../web-platform/tests/referrer-policy/OWNERS | 1 + .../web-platform/tests/resource-timing/OWNERS | 3 + .../tests/screen-orientation/OWNERS | 1 + testing/web-platform/tests/selection/OWNERS | 1 + .../web-platform/tests/service-workers/OWNERS | 1 + .../service-workers/cache-storage/OWNERS | 2 + .../cache-storage/resources/test-helpers.js | 200 ++++++++++++ .../resources/testharness-helpers.js | 67 ---- .../cache-storage/script-tests/cache-add.js | 138 ++++++++- .../cache-storage/script-tests/cache-match.js | 289 ++---------------- .../script-tests/cache-matchAll.js | 154 ++++++++++ .../cache-storage/script-tests/cache-put.js | 22 +- .../script-tests/cache-storage.js | 3 +- .../serviceworker/cache-match.https.html | 2 +- .../serviceworker/cache-matchAll.https.html | 10 + .../window/cache-match.https.html | 2 +- .../window/cache-matchAll.https.html | 9 + .../worker/cache-match.https.html | 2 +- .../worker/cache-matchAll.https.html | 9 + testing/web-platform/tests/shadow-dom/OWNERS | 5 + .../tests/subresource-integrity/OWNERS | 6 + testing/web-platform/tests/svg/OWNERS | 2 + .../web-platform/tests/touch-events/OWNERS | 3 + testing/web-platform/tests/typedarrays/OWNERS | 4 + testing/web-platform/tests/url/OWNERS | 8 + testing/web-platform/tests/user-timing/OWNERS | 1 + testing/web-platform/tests/vibration/OWNERS | 3 + .../web-platform/tests/web-animations/OWNERS | 1 + testing/web-platform/tests/webaudio/OWNERS | 1 + testing/web-platform/tests/webdriver/OWNERS | 4 + .../conformance/programs/program-test.html | 6 +- .../web-platform/tests/webmessaging/OWNERS | 6 + testing/web-platform/tests/webrtc/OWNERS | 4 + ...Secure-valid-url-protocol-setCorrectly.htm | 2 +- testing/web-platform/tests/websockets/OWNERS | 9 + .../tests/websockets/websocket.js | 72 ++--- testing/web-platform/tests/webstorage/OWNERS | 9 + testing/web-platform/tests/workers/OWNERS | 6 + .../WorkerUtils/importScripts/001.html | 26 -- .../WorkerUtils/importScripts/001.worker.js | 7 + .../WorkerUtils/importScripts/002.html | 32 -- .../WorkerUtils/importScripts/002.worker.js | 11 + 104 files changed, 1348 insertions(+), 539 deletions(-) create mode 100644 testing/web-platform/tests/DOMEvents/OWNERS create mode 100644 testing/web-platform/tests/FileAPI/OWNERS create mode 100644 testing/web-platform/tests/IndexedDB/OWNERS create mode 100644 testing/web-platform/tests/WebCryptoAPI/OWNERS create mode 100644 testing/web-platform/tests/XMLHttpRequest/OWNERS create mode 100644 testing/web-platform/tests/ambient-light/OWNERS create mode 100644 testing/web-platform/tests/app-uri/OWNERS create mode 100644 testing/web-platform/tests/common/OWNERS create mode 100644 testing/web-platform/tests/conformance-checkers/OWNERS create mode 100644 testing/web-platform/tests/content-security-policy/OWNERS create mode 100644 testing/web-platform/tests/cors/OWNERS create mode 100644 testing/web-platform/tests/cssom-view/OWNERS create mode 100644 testing/web-platform/tests/custom-elements/OWNERS create mode 100644 testing/web-platform/tests/docs/OWNERS create mode 100644 testing/web-platform/tests/dom/OWNERS create mode 100644 testing/web-platform/tests/domparsing/OWNERS create mode 100644 testing/web-platform/tests/domxpath/OWNERS create mode 100644 testing/web-platform/tests/editing/OWNERS create mode 100644 testing/web-platform/tests/encoding/OWNERS create mode 100644 testing/web-platform/tests/eventsource/OWNERS create mode 100644 testing/web-platform/tests/fetch/OWNERS create mode 100644 testing/web-platform/tests/gamepad/OWNERS create mode 100644 testing/web-platform/tests/geolocation-API/OWNERS create mode 100644 testing/web-platform/tests/hr-time/OWNERS create mode 100644 testing/web-platform/tests/html-imports/OWNERS create mode 100644 testing/web-platform/tests/html-longdesc/OWNERS create mode 100644 testing/web-platform/tests/html-media-capture/OWNERS create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html create mode 100644 testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html create mode 100644 testing/web-platform/tests/html/webappapis/scripting/events/event-handler-onresize.html create mode 100644 testing/web-platform/tests/images/OWNERS create mode 100644 testing/web-platform/tests/media-source/OWNERS create mode 100644 testing/web-platform/tests/media/OWNERS create mode 100644 testing/web-platform/tests/mediacapture-streams/OWNERS create mode 100644 testing/web-platform/tests/mixed-content/OWNERS create mode 100644 testing/web-platform/tests/navigation-timing/OWNERS create mode 100644 testing/web-platform/tests/notifications/OWNERS create mode 100644 testing/web-platform/tests/page-visibility/OWNERS create mode 100644 testing/web-platform/tests/performance-timeline/OWNERS create mode 100644 testing/web-platform/tests/pointerevents/OWNERS create mode 100644 testing/web-platform/tests/pointerlock/OWNERS create mode 100644 testing/web-platform/tests/proximity/OWNERS create mode 100644 testing/web-platform/tests/quirks-mode/OWNERS create mode 100644 testing/web-platform/tests/referrer-policy/OWNERS create mode 100644 testing/web-platform/tests/resource-timing/OWNERS create mode 100644 testing/web-platform/tests/screen-orientation/OWNERS create mode 100644 testing/web-platform/tests/selection/OWNERS create mode 100644 testing/web-platform/tests/service-workers/OWNERS create mode 100644 testing/web-platform/tests/service-workers/cache-storage/OWNERS create mode 100644 testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js create mode 100644 testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-matchAll.https.html create mode 100644 testing/web-platform/tests/service-workers/cache-storage/window/cache-matchAll.https.html create mode 100644 testing/web-platform/tests/service-workers/cache-storage/worker/cache-matchAll.https.html create mode 100644 testing/web-platform/tests/shadow-dom/OWNERS create mode 100644 testing/web-platform/tests/subresource-integrity/OWNERS create mode 100644 testing/web-platform/tests/svg/OWNERS create mode 100644 testing/web-platform/tests/touch-events/OWNERS create mode 100644 testing/web-platform/tests/typedarrays/OWNERS create mode 100644 testing/web-platform/tests/url/OWNERS create mode 100644 testing/web-platform/tests/user-timing/OWNERS create mode 100644 testing/web-platform/tests/vibration/OWNERS create mode 100644 testing/web-platform/tests/web-animations/OWNERS create mode 100644 testing/web-platform/tests/webaudio/OWNERS create mode 100644 testing/web-platform/tests/webdriver/OWNERS create mode 100644 testing/web-platform/tests/webmessaging/OWNERS create mode 100644 testing/web-platform/tests/webrtc/OWNERS create mode 100644 testing/web-platform/tests/websockets/OWNERS create mode 100644 testing/web-platform/tests/webstorage/OWNERS create mode 100644 testing/web-platform/tests/workers/OWNERS delete mode 100644 testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.html create mode 100644 testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.worker.js delete mode 100644 testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.html create mode 100644 testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.worker.js diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index c7c06998045..427edc6a089 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -13583,6 +13583,10 @@ "path": "cssom-view/elementsFromPoint.html", "url": "/cssom-view/elementsFromPoint.html" }, + { + "path": "cssom-view/negativeMargins.html", + "url": "/cssom-view/negativeMargins.html" + }, { "path": "cssom-view/scrollingElement.html", "url": "/cssom-view/scrollingElement.html" @@ -15627,6 +15631,18 @@ "path": "html/browsers/browsing-the-web/history-traversal/hashchange_event.html", "url": "/html/browsers/browsing-the-web/history-traversal/hashchange_event.html" }, + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html" + }, + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html" + }, + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html" + }, { "path": "html/browsers/browsing-the-web/history-traversal/popstate_event.html", "url": "/html/browsers/browsing-the-web/history-traversal/popstate_event.html" @@ -19515,6 +19531,10 @@ "path": "html/webappapis/scripting/events/event-handler-javascript.html", "url": "/html/webappapis/scripting/events/event-handler-javascript.html" }, + { + "path": "html/webappapis/scripting/events/event-handler-onresize.html", + "url": "/html/webappapis/scripting/events/event-handler-onresize.html" + }, { "path": "html/webappapis/scripting/events/event-handler-spec-example.html", "url": "/html/webappapis/scripting/events/event-handler-spec-example.html" @@ -31964,12 +31984,12 @@ "url": "/workers/interfaces/WorkerUtils/WindowTimers/004.html" }, { - "path": "workers/interfaces/WorkerUtils/importScripts/001.html", - "url": "/workers/interfaces/WorkerUtils/importScripts/001.html" + "path": "workers/interfaces/WorkerUtils/importScripts/001.worker.js", + "url": "/workers/interfaces/WorkerUtils/importScripts/001.worker" }, { - "path": "workers/interfaces/WorkerUtils/importScripts/002.html", - "url": "/workers/interfaces/WorkerUtils/importScripts/002.html" + "path": "workers/interfaces/WorkerUtils/importScripts/002.worker.js", + "url": "/workers/interfaces/WorkerUtils/importScripts/002.worker" }, { "path": "workers/interfaces/WorkerUtils/importScripts/003.html", @@ -32498,6 +32518,16 @@ "timeout": "long", "url": "/eventsource/shared-worker/eventsource-constructor-non-same-origin.htm" }, + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html", + "timeout": "long", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html" + }, + { + "path": "html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html", + "timeout": "long", + "url": "/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html" + }, { "path": "html/browsers/browsing-the-web/scroll-to-fragid/007.html", "timeout": "long", @@ -33428,6 +33458,11 @@ "timeout": "long", "url": "/service-workers/cache-storage/serviceworker/cache-match.https.html" }, + { + "path": "service-workers/cache-storage/serviceworker/cache-matchAll.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/serviceworker/cache-matchAll.https.html" + }, { "path": "service-workers/cache-storage/serviceworker/cache-put.https.html", "timeout": "long", @@ -33463,6 +33498,11 @@ "timeout": "long", "url": "/service-workers/cache-storage/window/cache-match.https.html" }, + { + "path": "service-workers/cache-storage/window/cache-matchAll.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/window/cache-matchAll.https.html" + }, { "path": "service-workers/cache-storage/window/cache-put.https.html", "timeout": "long", @@ -33503,6 +33543,11 @@ "timeout": "long", "url": "/service-workers/cache-storage/worker/cache-match.https.html" }, + { + "path": "service-workers/cache-storage/worker/cache-matchAll.https.html", + "timeout": "long", + "url": "/service-workers/cache-storage/worker/cache-matchAll.https.html" + }, { "path": "service-workers/cache-storage/worker/cache-put.https.html", "timeout": "long", @@ -33713,16 +33758,7 @@ }, "local_changes": { "deleted": [], - "items": { - "testharness": { - "cssom-view/negativeMargins.html": [ - { - "path": "cssom-view/negativeMargins.html", - "url": "/cssom-view/negativeMargins.html" - } - ] - } - }, + "items": {}, "reftest_nodes": {} }, "reftest_nodes": { @@ -39835,7 +39871,7 @@ } ] }, - "rev": "f3f87e1a2cc3845819038a8a6fe435bb6092e213", + "rev": "af65262f5f3400024279c526117489f1f11d3233", "url_base": "/", "version": 2 } diff --git a/testing/web-platform/meta/mozilla-sync b/testing/web-platform/meta/mozilla-sync index 269ca479cd1..5f5462944ea 100644 --- a/testing/web-platform/meta/mozilla-sync +++ b/testing/web-platform/meta/mozilla-sync @@ -1 +1 @@ -a035c3724da7e8235c26a3b6ea567365efda3b15 \ No newline at end of file +fa876a5774a3178efb42d6ebd8c8df045e03a80b \ No newline at end of file diff --git a/testing/web-platform/tests/DOMEvents/OWNERS b/testing/web-platform/tests/DOMEvents/OWNERS new file mode 100644 index 00000000000..50802902fb8 --- /dev/null +++ b/testing/web-platform/tests/DOMEvents/OWNERS @@ -0,0 +1,3 @@ +@jdm +@zqzhang +@Ms2ger diff --git a/testing/web-platform/tests/FileAPI/OWNERS b/testing/web-platform/tests/FileAPI/OWNERS new file mode 100644 index 00000000000..03bb9336574 --- /dev/null +++ b/testing/web-platform/tests/FileAPI/OWNERS @@ -0,0 +1,6 @@ +@inexorabletash +@plehegar +@zqzhang +@zcorpan +@jdm +@Ms2ger diff --git a/testing/web-platform/tests/IndexedDB/OWNERS b/testing/web-platform/tests/IndexedDB/OWNERS new file mode 100644 index 00000000000..711894a54b3 --- /dev/null +++ b/testing/web-platform/tests/IndexedDB/OWNERS @@ -0,0 +1,8 @@ +@Velmont +@inexorabletash +@chunywang +@dumbmatter +@zqzhang +@yunxiaoxie +@zhaozihao +@foolip diff --git a/testing/web-platform/tests/WebCryptoAPI/OWNERS b/testing/web-platform/tests/WebCryptoAPI/OWNERS new file mode 100644 index 00000000000..70190999b7c --- /dev/null +++ b/testing/web-platform/tests/WebCryptoAPI/OWNERS @@ -0,0 +1,2 @@ +@Wafflespeanut +@Ms2ger diff --git a/testing/web-platform/tests/XMLHttpRequest/OWNERS b/testing/web-platform/tests/XMLHttpRequest/OWNERS new file mode 100644 index 00000000000..7a809e70f6c --- /dev/null +++ b/testing/web-platform/tests/XMLHttpRequest/OWNERS @@ -0,0 +1,13 @@ +@ecoal95 +@hallvors +@kangxu +@caitp +@Manishearth +@plehegar +@foolip +@jungkees +@ibelem +@mathiasbynens +@ronkorving +@jdm +@Ms2ger diff --git a/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm b/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm index ed53996dcec..a1bdc8e97db 100644 --- a/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm +++ b/testing/web-platform/tests/XMLHttpRequest/responsexml-document-properties.htm @@ -43,7 +43,7 @@ } test(function() { - assert_true((new Date(client.getResponseHeader('Last-Modified'))).getTime() == (new Date(client.responseXML.lastModified)).getTime(), 'responseXML.lastModified time shoud be equal to time in response Last-Modified header') + assert_true((new Date(client.getResponseHeader('Last-Modified'))).getTime() == (new Date(client.responseXML.lastModified)).getTime(), 'responseXML.lastModified time should be equal to time in response Last-Modified header') }, 'lastModified set according to HTTP header') test(function() { diff --git a/testing/web-platform/tests/ambient-light/OWNERS b/testing/web-platform/tests/ambient-light/OWNERS new file mode 100644 index 00000000000..548c25a14da --- /dev/null +++ b/testing/web-platform/tests/ambient-light/OWNERS @@ -0,0 +1,3 @@ +@zqzhang +@Volker-E +@dontcallmedom diff --git a/testing/web-platform/tests/app-uri/OWNERS b/testing/web-platform/tests/app-uri/OWNERS new file mode 100644 index 00000000000..261dea7df72 --- /dev/null +++ b/testing/web-platform/tests/app-uri/OWNERS @@ -0,0 +1 @@ +@happyoungj diff --git a/testing/web-platform/tests/common/OWNERS b/testing/web-platform/tests/common/OWNERS new file mode 100644 index 00000000000..1da08cf4983 --- /dev/null +++ b/testing/web-platform/tests/common/OWNERS @@ -0,0 +1,4 @@ +@zqzhang +@foolip +@dontcallmedom +@deniak diff --git a/testing/web-platform/tests/conformance-checkers/OWNERS b/testing/web-platform/tests/conformance-checkers/OWNERS new file mode 100644 index 00000000000..2ac6145caa8 --- /dev/null +++ b/testing/web-platform/tests/conformance-checkers/OWNERS @@ -0,0 +1 @@ +@sideshowbarker diff --git a/testing/web-platform/tests/content-security-policy/OWNERS b/testing/web-platform/tests/content-security-policy/OWNERS new file mode 100644 index 00000000000..27348607493 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/OWNERS @@ -0,0 +1,2 @@ +@sideshowbarker +@hillbrad diff --git a/testing/web-platform/tests/cors/OWNERS b/testing/web-platform/tests/cors/OWNERS new file mode 100644 index 00000000000..c8979792445 --- /dev/null +++ b/testing/web-platform/tests/cors/OWNERS @@ -0,0 +1,5 @@ +@sideshowbarker +@zqzhang +@Velmont +@hillbrad +@jdm diff --git a/testing/web-platform/tests/cssom-view/OWNERS b/testing/web-platform/tests/cssom-view/OWNERS new file mode 100644 index 00000000000..cd9ff2eee4b --- /dev/null +++ b/testing/web-platform/tests/cssom-view/OWNERS @@ -0,0 +1 @@ +@AutomatedTester diff --git a/testing/web-platform/tests/custom-elements/OWNERS b/testing/web-platform/tests/custom-elements/OWNERS new file mode 100644 index 00000000000..4671167903f --- /dev/null +++ b/testing/web-platform/tests/custom-elements/OWNERS @@ -0,0 +1,3 @@ +@deepak-sa +@sgrekhov +@alsemenov diff --git a/testing/web-platform/tests/docs/OWNERS b/testing/web-platform/tests/docs/OWNERS new file mode 100644 index 00000000000..af3e0845c35 --- /dev/null +++ b/testing/web-platform/tests/docs/OWNERS @@ -0,0 +1,4 @@ +@sideshowbarker +@dontcallmedom +@zcorpan +@Ms2ger diff --git a/testing/web-platform/tests/dom/OWNERS b/testing/web-platform/tests/dom/OWNERS new file mode 100644 index 00000000000..fad498154e4 --- /dev/null +++ b/testing/web-platform/tests/dom/OWNERS @@ -0,0 +1,6 @@ +@ayg +@jdm +@Ms2ger +@plehegar +@zcorpan +@zqzhang diff --git a/testing/web-platform/tests/domparsing/OWNERS b/testing/web-platform/tests/domparsing/OWNERS new file mode 100644 index 00000000000..113c79d205d --- /dev/null +++ b/testing/web-platform/tests/domparsing/OWNERS @@ -0,0 +1,5 @@ +@sideshowbarker +@ChrisParis +@deniak +@jdm +@Ms2ger diff --git a/testing/web-platform/tests/domxpath/OWNERS b/testing/web-platform/tests/domxpath/OWNERS new file mode 100644 index 00000000000..7c764a42450 --- /dev/null +++ b/testing/web-platform/tests/domxpath/OWNERS @@ -0,0 +1,3 @@ +@gsnedders +@zqzhang +@deniak diff --git a/testing/web-platform/tests/editing/OWNERS b/testing/web-platform/tests/editing/OWNERS new file mode 100644 index 00000000000..ce908c45b4a --- /dev/null +++ b/testing/web-platform/tests/editing/OWNERS @@ -0,0 +1 @@ +@ayg diff --git a/testing/web-platform/tests/encoding/OWNERS b/testing/web-platform/tests/encoding/OWNERS new file mode 100644 index 00000000000..4917e26650a --- /dev/null +++ b/testing/web-platform/tests/encoding/OWNERS @@ -0,0 +1,2 @@ +@inexorabletash +@sideshowbarker diff --git a/testing/web-platform/tests/eventsource/OWNERS b/testing/web-platform/tests/eventsource/OWNERS new file mode 100644 index 00000000000..4f8d605d71c --- /dev/null +++ b/testing/web-platform/tests/eventsource/OWNERS @@ -0,0 +1,5 @@ +@zqzhang +@sideshowbarker +@deniak +@Velmont +@Yaffle diff --git a/testing/web-platform/tests/fetch/OWNERS b/testing/web-platform/tests/fetch/OWNERS new file mode 100644 index 00000000000..fbeac366e3c --- /dev/null +++ b/testing/web-platform/tests/fetch/OWNERS @@ -0,0 +1,2 @@ +@jdm +@youennf diff --git a/testing/web-platform/tests/gamepad/OWNERS b/testing/web-platform/tests/gamepad/OWNERS new file mode 100644 index 00000000000..d7fbc2625bd --- /dev/null +++ b/testing/web-platform/tests/gamepad/OWNERS @@ -0,0 +1 @@ +@luser diff --git a/testing/web-platform/tests/geolocation-API/OWNERS b/testing/web-platform/tests/geolocation-API/OWNERS new file mode 100644 index 00000000000..64e2488b4ba --- /dev/null +++ b/testing/web-platform/tests/geolocation-API/OWNERS @@ -0,0 +1,2 @@ +@zqzhang +@jdm diff --git a/testing/web-platform/tests/hr-time/OWNERS b/testing/web-platform/tests/hr-time/OWNERS new file mode 100644 index 00000000000..ffa09d9ade9 --- /dev/null +++ b/testing/web-platform/tests/hr-time/OWNERS @@ -0,0 +1,2 @@ +@plehegar +@foolip diff --git a/testing/web-platform/tests/html-imports/OWNERS b/testing/web-platform/tests/html-imports/OWNERS new file mode 100644 index 00000000000..edda46755d6 --- /dev/null +++ b/testing/web-platform/tests/html-imports/OWNERS @@ -0,0 +1 @@ +@omo diff --git a/testing/web-platform/tests/html-longdesc/OWNERS b/testing/web-platform/tests/html-longdesc/OWNERS new file mode 100644 index 00000000000..91527fa2ac9 --- /dev/null +++ b/testing/web-platform/tests/html-longdesc/OWNERS @@ -0,0 +1,2 @@ +@chaals +@cptvitamin diff --git a/testing/web-platform/tests/html-media-capture/OWNERS b/testing/web-platform/tests/html-media-capture/OWNERS new file mode 100644 index 00000000000..b45f53558b6 --- /dev/null +++ b/testing/web-platform/tests/html-media-capture/OWNERS @@ -0,0 +1,2 @@ +@haoxli +@zqzhang diff --git a/testing/web-platform/tests/html/OWNERS b/testing/web-platform/tests/html/OWNERS index 210a621c919..ef22027135b 100644 --- a/testing/web-platform/tests/html/OWNERS +++ b/testing/web-platform/tests/html/OWNERS @@ -1,5 +1,6 @@ @Ms2ger @gsnedders +@jdm @jgraham @plehegar @sideshowbarker diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html new file mode 100644 index 00000000000..6b4df1ef2fc --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html @@ -0,0 +1,8 @@ + + + Blank 1 \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html new file mode 100644 index 00000000000..def21396675 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank2.html @@ -0,0 +1,8 @@ + + + Blank 2 diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html new file mode 100644 index 00000000000..11737661d0f --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/page-with-fragment.html @@ -0,0 +1,20 @@ + + + +Page with fragment + + \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html new file mode 100644 index 00000000000..e47cd9c3833 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-basic.html @@ -0,0 +1,34 @@ + +Verify existence and basic read/write function of history.scrollRestoration + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html new file mode 100644 index 00000000000..e3da59e3900 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html @@ -0,0 +1,67 @@ + + +Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html new file mode 100644 index 00000000000..d837b8f63f0 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html @@ -0,0 +1,54 @@ + + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html new file mode 100644 index 00000000000..87a337b2da3 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-cross-origin.html @@ -0,0 +1,71 @@ + + +Correct behaviour of scroll restoration mode is cross origin history traversal + + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html new file mode 100644 index 00000000000..46d40eedc62 --- /dev/null +++ b/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-navigation-samedoc.html @@ -0,0 +1,81 @@ + +Correct behaviour of scroll restoration mode in same document history traversals + + + + + + + diff --git a/testing/web-platform/tests/html/dom/interfaces.html b/testing/web-platform/tests/html/dom/interfaces.html index 8eb7df805fb..d55aca60516 100644 --- a/testing/web-platform/tests/html/dom/interfaces.html +++ b/testing/web-platform/tests/html/dom/interfaces.html @@ -2309,8 +2309,11 @@ interface BarProp { attribute boolean visible; }; +enum ScrollRestoration { "auto", "manual" }; interface History { + readonly attribute long length; + attribute ScrollRestoration scrollRestoration; readonly attribute any state; void go(optional long delta); void back(); diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html index 3e76576f76c..0de7ff329c2 100644 --- a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported-ref.html @@ -19,7 +19,7 @@
  • fifth item
  • sixth item
  • seventh item
  • -
  • eigth item
  • +
  • eighth item
  • ninth item
    1. first ordered item
    2. @@ -29,7 +29,7 @@
    3. fifth ordered item
    4. sixth ordered item
    5. seventh ordered item
    6. -
    7. eigth ordered item
    8. +
    9. eighth ordered item
    10. ninth ordered item
      @@ -40,6 +40,6 @@
    • fifth unordered item
    • sixth unordered item
    • seventh unordered item
    • -
    • eigth unordered item
    • +
    • eighth unordered item
    • ninth unordered item
    diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.html b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.html index 0fe85bd0492..ddd9024c117 100644 --- a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.html +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.html @@ -9,7 +9,7 @@
  • fifth item
  • sixth item
  • seventh item
  • -
  • eigth item
  • +
  • eighth item
  • ninth item
    1. first ordered item
    2. @@ -19,7 +19,7 @@
    3. fifth ordered item
    4. sixth ordered item
    5. seventh ordered item
    6. -
    7. eigth ordered item
    8. +
    9. eighth ordered item
    10. ninth ordered item
      @@ -30,6 +30,6 @@
    • fifth unordered item
    • sixth unordered item
    • seventh unordered item
    • -
    • eigth unordered item
    • +
    • eighth unordered item
    • ninth unordered item
    diff --git a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.xhtml b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.xhtml index 69f96e894bf..7a7640e03f0 100644 --- a/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.xhtml +++ b/testing/web-platform/tests/html/rendering/non-replaced-elements/lists/li-type-supported.xhtml @@ -12,7 +12,7 @@
  • fifth item
  • sixth item
  • seventh item
  • -
  • eigth item
  • +
  • eighth item
  • ninth item
    1. first ordered item
    2. @@ -22,7 +22,7 @@
    3. fifth ordered item
    4. sixth ordered item
    5. seventh ordered item
    6. -
    7. eigth ordered item
    8. +
    9. eighth ordered item
    10. ninth ordered item
      @@ -33,7 +33,7 @@
    • fifth unordered item
    • sixth unordered item
    • seventh unordered item
    • -
    • eigth unordered item
    • +
    • eighth unordered item
    • ninth unordered item
    diff --git a/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-document.html b/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-document.html index 3dba394baa5..3d44678cf16 100644 --- a/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-document.html +++ b/testing/web-platform/tests/html/semantics/embedded-content/the-embed-element/embed-document.html @@ -3,13 +3,15 @@ HTML Test: The embed element represents a document - diff --git a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html index 74b48e92100..9d308bbed3c 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html +++ b/testing/web-platform/tests/html/semantics/forms/the-button-element/button-events.html @@ -23,25 +23,25 @@ var btn = document.getElementById("btn"), document.forms.fm1.onsubmit = t1.step_func(function (evt) { evt.preventDefault(); - assert_true(evt.isTrusted, "The isTrusted attribute of the submit event shoud be true."); - assert_true(evt.bubbles, "The bubbles attribute of the submit event shoud be true."); - assert_true(evt.cancelable, "The cancelable attribute of the submit event shoud be true."); + assert_true(evt.isTrusted, "The isTrusted attribute of the submit event should be true."); + assert_true(evt.bubbles, "The bubbles attribute of the submit event should be true."); + assert_true(evt.cancelable, "The cancelable attribute of the submit event should be true."); assert_true(evt instanceof Event, "The submit event is an instance of Event interface."); t1.done(); }); document.forms.fm1.onreset = t2.step_func(function (evt) { - assert_true(evt.isTrusted, "The isTrusted attribute of the reset event shoud be true."); - assert_true(evt.bubbles, "The bubbles attribute of the reset event shoud be true."); - assert_true(evt.cancelable, "The cancelable attribute of the reset event shoud be true."); + assert_true(evt.isTrusted, "The isTrusted attribute of the reset event should be true."); + assert_true(evt.bubbles, "The bubbles attribute of the reset event should be true."); + assert_true(evt.cancelable, "The cancelable attribute of the reset event should be true."); assert_true(evt instanceof Event, "The reset event is an instance of Event interface."); t2.done(); }); document.getElementById("menu").onshow = t3.step_func(function (evt) { - assert_true(evt.isTrusted, "The isTrusted attribute of the show event shoud be true."); + assert_true(evt.isTrusted, "The isTrusted attribute of the show event should be true."); assert_equals(evt.relatedTarget, menu_btn, "The relatedTarget attribute should be initialized to the related button element."); - assert_true(evt.cancelable, "The cancelable attribute of the show event shoud be true."); + assert_true(evt.cancelable, "The cancelable attribute of the show event should be true."); assert_true(evt instanceof RelatedEvent, "The show event is an instance of RelatedEvent interface."); t3.done(); }); diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html index 1b75d74300a..054d3444449 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html +++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/checkbox.html @@ -2,7 +2,8 @@ input type checkbox - + +
    @@ -19,28 +20,39 @@ checkbox4 = document.getElementById('checkbox4'), checkbox5 = document.getElementById('checkbox5'), checkbox6 = document.getElementById('checkbox6'), - c1_input_fired = false, c1_change_fired = false, - t1 = async_test("click on mutable checkbox fires the input and change events"), + c1_click_fired = false, + c1_input_fired = false, + c1_change_fired = false, + t1 = async_test("click on mutable checkbox fires a click event, then an input event, then a change event"), t2 = async_test("click on non-mutable checkbox doesn't fire the input or change event"), t3 = async_test("pre-activation steps on unchecked checkbox"), t4 = async_test("pre-activation steps on checked checkbox"), t5 = async_test("canceled activation steps on unchecked checkbox"), t6 = async_test("canceled activation steps on unchecked checkbox (indeterminate=true in onclick)"); - checkbox1.oninput= t1.step_func(function(e) { + checkbox1.onclick = t1.step_func(function () { + c1_click_fired = true; + assert_false(c1_input_fired, "click event should fire before input event"); + assert_false(c1_change_fired, "click event should fire before change event"); + }); + checkbox1.oninput = t1.step_func(function(e) { c1_input_fired = true; + assert_true(c1_click_fired, "input event should fire after click event"); + assert_false(c1_change_fired, "input event should fire before change event"); assert_true(e.bubbles, "event should bubble"); assert_true(e.isTrusted, "event should be trusted"); - assert_false(e.cancelable, "event shoud not be cancelable"); + assert_false(e.cancelable, "event should not be cancelable"); assert_true(checkbox1.checked, "checkbox is checked"); assert_false(checkbox1.indeterminate, "checkbox is not indeterminate"); }); checkbox1.onchange = t1.step_func(function(e) { c1_change_fired = true; + assert_true(c1_click_fired, "change event should fire after click event"); + assert_true(c1_input_fired, "change event should fire after input event"); assert_true(e.bubbles, "event should bubble") assert_true(e.isTrusted, "event should be trusted"); - assert_false(e.cancelable, "event shoud not be cancelable"); + assert_false(e.cancelable, "event should not be cancelable"); assert_true(checkbox1.checked, "checkbox is checked"); assert_false(checkbox1.indeterminate, "checkbox is not indeterminate"); }); @@ -83,9 +95,22 @@ checkbox5.onclick = t5.step_func(function(e) { e.preventDefault(); - assert_false(checkbox5.checked); + /* + The prevention of the click doesn't have an effect until after all the + click event handlers have been run. + */ + assert_true(checkbox5.checked); assert_false(checkbox5.indeterminate); - t5.done(); + window.setTimeout(t5.step_func(function(e) { + /* + The click event has finished being dispatched, so the checkedness and + determinateness have been toggled back by now because the event + was preventDefault-ed. + */ + assert_false(checkbox5.checked); + assert_false(checkbox5.indeterminate); + t5.done(); + }), 0); }); t5.step(function(){ @@ -97,9 +122,22 @@ checkbox6.onclick = t6.step_func(function(e) { checkbox6.indeterminate = true; e.preventDefault(); - assert_false(checkbox6.checked); - assert_false(checkbox6.indeterminate); - t6.done(); + /* + The prevention of the click doesn't have an effect until after all the + click event handlers have been run. + */ + assert_true(checkbox6.checked); + assert_true(checkbox6.indeterminate); + window.setTimeout(t6.step_func(function(e) { + /* + The click event has finished being dispatched, so the checkedness and + determinateness have been toggled back by now because the event + was preventDefault-ed. + */ + assert_false(checkbox6.checked); + assert_false(checkbox6.indeterminate); + t6.done(); + }), 0); }); t6.step(function(){ diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html index 3340239881b..9e2d47c423d 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html +++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/file-manual.html @@ -18,12 +18,12 @@ document.getElementById('file').oninput = t1.step_func_done(function(e) { assert_true(e.bubbles, "input event bubbles"); assert_true(e.isTrusted, "input event should be trusted"); - assert_false(e.cancelable, "input event shoud not be cancelable"); + assert_false(e.cancelable, "input event should not be cancelable"); }) document.getElementById('file').onchange = t2.step_func_done(function(e) { assert_true(e.bubbles, "change event bubbles"); assert_true(e.isTrusted, "change event should be trusted"); - assert_false(e.cancelable, "change event shoud not be cancelable"); + assert_false(e.cancelable, "change event should not be cancelable"); assert_true(input.files instanceof FileList); assert_equals(input.value, "C:\\fakepath\\" + input.files[0].name); }) diff --git a/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html index 3c4fea2a617..9f8fe096d52 100644 --- a/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html +++ b/testing/web-platform/tests/html/semantics/forms/the-input-element/radio.html @@ -15,8 +15,8 @@ - - + + @@ -37,8 +37,7 @@ radio9 = document.getElementById('radio9'), radio10 = document.getElementById('radio10'), radio11 = document.getElementById('radio11'), - t1 = async_test("click on mutable radio fires the input event"), - t2 = async_test("click on mutable radio fires the change event"), + t1 = async_test("click on mutable radio fires click event, then input event, then change event"), t3 = async_test("click on non-mutable radio doesn't fire the input event"), t4 = async_test("click on non-mutable radio doesn't fire the change event"), t5 = async_test("canceled activation steps on unchecked radio"), @@ -80,18 +79,28 @@ assert_false(radio11.checked); }, "changing the name of a radio input element and setting its checkedness to true makes all the other elements' checkedness in the same radio button group be set to false"); - radio5.oninput= t1.step_func(function(e) { - input_fired = true; - assert_true(e.bubbles, "event should bubble") - assert_true(e.isTrusted, "event should be trusted"); - assert_false(e.cancelable, "event shoud not be cancelable"); + radio5.onclick = t1.step_func(function(e) { + click_fired = true; + assert_false(input_fired, "click event should fire before input event"); + assert_false(change_fired, "click event should fire before change event"); }); - radio5.onchange = t2.step_func(function(e) { + radio5.oninput = t1.step_func(function(e) { + input_fired = true; + assert_true(click_fired, "input event should fire after click event"); + assert_false(change_fired, "input event should fire before change event"); + assert_true(e.bubbles, "input event should bubble") + assert_true(e.isTrusted, "input event should be trusted"); + assert_false(e.cancelable, "input event should not be cancelable"); + }); + + radio5.onchange = t1.step_func(function(e) { change_fired = true; - assert_true(e.bubbles, "event should bubble") - assert_true(e.isTrusted, "event should be trusted"); - assert_false(e.cancelable, "event shoud not be cancelable"); + assert_true(click_fired, "change event should fire after click event"); + assert_true(input_fired, "change event should fire after input event"); + assert_true(e.bubbles, "change event should bubble") + assert_true(e.isTrusted, "change event should be trusted"); + assert_false(e.cancelable, "change event should not be cancelable"); }); radio6.oninput= t3.step_func_done(function(e) { @@ -108,11 +117,6 @@ t1.done(); }); - t2.step(function() { - assert_true(change_fired); - t2.done(); - }) - t3.step(function(){ radio6.click(); t3.done(); @@ -120,18 +124,20 @@ }); radio72.onclick = t5.step_func_done(function(e){ - assert_false(radio71.checked); - assert_true(radio72.checked); + assert_false(radio71.checked, "click on radio should uncheck other radio in same group"); + assert_true(radio72.checked, "click on radio should check that radio"); e.preventDefault(); - assert_false(radio71.checked); - assert_true(radio72.checked); + // The cancelation of the click doesn't have an effect until after all the click event handlers have been run. + assert_false(radio71.checked, "radio remains unchecked immediately after click event on other radio in same group is canceled"); + assert_true(radio72.checked, "clicked radio remains checked immediately after click event is canceled"); }); t5.step(function(){ - assert_true(radio71.checked); - assert_false(radio72.checked); + assert_true(radio71.checked, "initially checked radio should be checked"); + assert_false(radio72.checked, "other radios in same group as initially-checked radio should be unchecked"); radio72.click(); - assert_true(radio71.checked); - assert_false(radio72.checked); + // Now that the click event has been fully dispatched, its cancelation has taken effect. + assert_true(radio71.checked, "canceled click event on radio should leave the previously-checked radio checked"); + assert_false(radio72.checked, "canceled click event on previously-unchecked radio should leave that radio unchecked"); }); diff --git a/testing/web-platform/tests/html/webappapis/scripting/events/event-handler-onresize.html b/testing/web-platform/tests/html/webappapis/scripting/events/event-handler-onresize.html new file mode 100644 index 00000000000..8686716e19a --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/scripting/events/event-handler-onresize.html @@ -0,0 +1,38 @@ + +HTMLBodyElement.onresize + + + + +
    + diff --git a/testing/web-platform/tests/images/OWNERS b/testing/web-platform/tests/images/OWNERS new file mode 100644 index 00000000000..8ab38aed331 --- /dev/null +++ b/testing/web-platform/tests/images/OWNERS @@ -0,0 +1,2 @@ +@zqzhang +@tagawa diff --git a/testing/web-platform/tests/media-source/OWNERS b/testing/web-platform/tests/media-source/OWNERS new file mode 100644 index 00000000000..3b36dfa39a2 --- /dev/null +++ b/testing/web-platform/tests/media-source/OWNERS @@ -0,0 +1,4 @@ +@bit +@acolwell +@shishimaru +@sideshowbarker diff --git a/testing/web-platform/tests/media/OWNERS b/testing/web-platform/tests/media/OWNERS new file mode 100644 index 00000000000..96fa9523d7b --- /dev/null +++ b/testing/web-platform/tests/media/OWNERS @@ -0,0 +1,2 @@ +@hillbrad +@foolip diff --git a/testing/web-platform/tests/mediacapture-streams/OWNERS b/testing/web-platform/tests/mediacapture-streams/OWNERS new file mode 100644 index 00000000000..03ff57c28fd --- /dev/null +++ b/testing/web-platform/tests/mediacapture-streams/OWNERS @@ -0,0 +1,3 @@ +@dontcallmedom +@alvestrand + diff --git a/testing/web-platform/tests/mixed-content/OWNERS b/testing/web-platform/tests/mixed-content/OWNERS new file mode 100644 index 00000000000..db2d613c226 --- /dev/null +++ b/testing/web-platform/tests/mixed-content/OWNERS @@ -0,0 +1 @@ +@kristijanburnik diff --git a/testing/web-platform/tests/navigation-timing/OWNERS b/testing/web-platform/tests/navigation-timing/OWNERS new file mode 100644 index 00000000000..ffa09d9ade9 --- /dev/null +++ b/testing/web-platform/tests/navigation-timing/OWNERS @@ -0,0 +1,2 @@ +@plehegar +@foolip diff --git a/testing/web-platform/tests/notifications/OWNERS b/testing/web-platform/tests/notifications/OWNERS new file mode 100644 index 00000000000..992402311a2 --- /dev/null +++ b/testing/web-platform/tests/notifications/OWNERS @@ -0,0 +1,4 @@ +@chunywang +@sideshowbarker +@xinliux +@ibelem diff --git a/testing/web-platform/tests/page-visibility/OWNERS b/testing/web-platform/tests/page-visibility/OWNERS new file mode 100644 index 00000000000..ffa09d9ade9 --- /dev/null +++ b/testing/web-platform/tests/page-visibility/OWNERS @@ -0,0 +1,2 @@ +@plehegar +@foolip diff --git a/testing/web-platform/tests/performance-timeline/OWNERS b/testing/web-platform/tests/performance-timeline/OWNERS new file mode 100644 index 00000000000..5a05f35799c --- /dev/null +++ b/testing/web-platform/tests/performance-timeline/OWNERS @@ -0,0 +1 @@ +@plehegar diff --git a/testing/web-platform/tests/pointerevents/OWNERS b/testing/web-platform/tests/pointerevents/OWNERS new file mode 100644 index 00000000000..af346a9323f --- /dev/null +++ b/testing/web-platform/tests/pointerevents/OWNERS @@ -0,0 +1,7 @@ +@bethge +@Steditor +@EvgenyAgafonchikov +@jacobrossi +@plehegar +@scottgonzalez +@staktrace diff --git a/testing/web-platform/tests/pointerlock/OWNERS b/testing/web-platform/tests/pointerlock/OWNERS new file mode 100644 index 00000000000..5a05f35799c --- /dev/null +++ b/testing/web-platform/tests/pointerlock/OWNERS @@ -0,0 +1 @@ +@plehegar diff --git a/testing/web-platform/tests/proximity/OWNERS b/testing/web-platform/tests/proximity/OWNERS new file mode 100644 index 00000000000..7fab6d626aa --- /dev/null +++ b/testing/web-platform/tests/proximity/OWNERS @@ -0,0 +1,2 @@ +@zqzhang +@dontcallmedom diff --git a/testing/web-platform/tests/quirks-mode/OWNERS b/testing/web-platform/tests/quirks-mode/OWNERS new file mode 100644 index 00000000000..63851614695 --- /dev/null +++ b/testing/web-platform/tests/quirks-mode/OWNERS @@ -0,0 +1 @@ +@zcorpan diff --git a/testing/web-platform/tests/referrer-policy/OWNERS b/testing/web-platform/tests/referrer-policy/OWNERS new file mode 100644 index 00000000000..db2d613c226 --- /dev/null +++ b/testing/web-platform/tests/referrer-policy/OWNERS @@ -0,0 +1 @@ +@kristijanburnik diff --git a/testing/web-platform/tests/resource-timing/OWNERS b/testing/web-platform/tests/resource-timing/OWNERS new file mode 100644 index 00000000000..29f407cf1e0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/OWNERS @@ -0,0 +1,3 @@ +@haoxli +@plehegar +@zqzhang diff --git a/testing/web-platform/tests/screen-orientation/OWNERS b/testing/web-platform/tests/screen-orientation/OWNERS new file mode 100644 index 00000000000..bbdded8fff9 --- /dev/null +++ b/testing/web-platform/tests/screen-orientation/OWNERS @@ -0,0 +1 @@ +@haoxli diff --git a/testing/web-platform/tests/selection/OWNERS b/testing/web-platform/tests/selection/OWNERS new file mode 100644 index 00000000000..ce908c45b4a --- /dev/null +++ b/testing/web-platform/tests/selection/OWNERS @@ -0,0 +1 @@ +@ayg diff --git a/testing/web-platform/tests/service-workers/OWNERS b/testing/web-platform/tests/service-workers/OWNERS new file mode 100644 index 00000000000..e210b8f2d4c --- /dev/null +++ b/testing/web-platform/tests/service-workers/OWNERS @@ -0,0 +1 @@ +@ehsan diff --git a/testing/web-platform/tests/service-workers/cache-storage/OWNERS b/testing/web-platform/tests/service-workers/cache-storage/OWNERS new file mode 100644 index 00000000000..2e63dd2203e --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/OWNERS @@ -0,0 +1,2 @@ +@inexorabletash +@wanderview diff --git a/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js b/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js index 91110950d56..f4145e6217f 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js +++ b/testing/web-platform/tests/service-workers/cache-storage/resources/test-helpers.js @@ -35,3 +35,203 @@ function cache_test(test_function, description) { .then(test_function); }, description); } + +// A set of Request/Response pairs to be used with prepopulated_cache_test(). +var simple_entries = [ + { + name: 'a', + request: new Request('http://example.com/a'), + response: new Response('') + }, + + { + name: 'b', + request: new Request('http://example.com/b'), + response: new Response('') + }, + + { + name: 'a_with_query', + request: new Request('http://example.com/a?q=r'), + response: new Response('') + }, + + { + name: 'A', + request: new Request('http://example.com/A'), + response: new Response('') + }, + + { + name: 'a_https', + request: new Request('https://example.com/a'), + response: new Response('') + }, + + { + name: 'a_org', + request: new Request('http://example.org/a'), + response: new Response('') + }, + + { + name: 'cat', + request: new Request('http://example.com/cat'), + response: new Response('') + }, + + { + name: 'catmandu', + request: new Request('http://example.com/catmandu'), + response: new Response('') + }, + + { + name: 'cat_num_lives', + request: new Request('http://example.com/cat?lives=9'), + response: new Response('') + }, + + { + name: 'cat_in_the_hat', + request: new Request('http://example.com/cat/in/the/hat'), + response: new Response('') + }, + + { + name: 'non_2xx_response', + request: new Request('http://example.com/non2xx'), + response: new Response('', {status: 404, statusText: 'nope'}) + }, + + { + name: 'error_response', + request: new Request('http://example.com/error'), + response: Response.error() + }, +]; + +// A set of Request/Response pairs to be used with prepopulated_cache_test(). +// These contain a mix of test cases that use Vary headers. +var vary_entries = [ + { + name: 'vary_cookie_is_cookie', + request: new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}}), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + }, + + { + name: 'vary_cookie_is_good', + request: new Request('http://example.com/c', + {headers: {'Cookies': 'is-good-enough-for-me'}}), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + }, + + { + name: 'vary_cookie_absent', + request: new Request('http://example.com/c'), + response: new Response('', + {headers: {'Vary': 'Cookies'}}) + } +]; + +// Run |test_function| with a Cache object and a map of entries. Prior to the +// call, the Cache is populated by cache entries from |entries|. The latter is +// expected to be an Object mapping arbitrary keys to objects of the form +// {request: , response: }. There's no +// guarantee on the order in which entries will be added to the cache. +// +// |test_function| should return a Promise that can be used with promise_test. +function prepopulated_cache_test(entries, test_function, description) { + cache_test(function(cache) { + var p = Promise.resolve(); + var hash = {}; + return Promise.all(entries.map(function(entry) { + hash[entry.name] = entry; + return cache.put(entry.request.clone(), + entry.response.clone()) + .catch(function(e) { + assert_unreached( + 'Test setup failed for entry ' + entry.name + ': ' + e); + }); + })) + .then(function() { + assert_equals(Object.keys(hash).length, entries.length); + }) + .then(function() { + return test_function(cache, hash); + }); + }, description); +} + +// Helper for testing with Headers objects. Compares Headers instances +// by serializing |expected| and |actual| to arrays and comparing. +function assert_header_equals(actual, expected, description) { + assert_class_string(actual, "Headers", description); + var header; + var actual_headers = []; + var expected_headers = []; + for (header of actual) + actual_headers.push(header[0] + ": " + header[1]); + for (header of expected) + expected_headers.push(header[0] + ": " + header[1]); + assert_array_equals(actual_headers, expected_headers, + description + " Headers differ."); +} + +// Helper for testing with Response objects. Compares simple +// attributes defined on the interfaces, as well as the headers. It +// does not compare the response bodies. +function assert_response_equals(actual, expected, description) { + assert_class_string(actual, "Response", description); + ["type", "url", "status", "ok", "statusText"].forEach(function(attribute) { + assert_equals(actual[attribute], expected[attribute], + description + " Attributes differ: " + attribute + "."); + }); + assert_header_equals(actual.headers, expected.headers, description); +} + +// Assert that the two arrays |actual| and |expected| contain the same +// set of Responses as determined by assert_response_equals. The order +// is not significant. +// +// |expected| is assumed to not contain any duplicates. +function assert_response_array_equivalent(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + expected.forEach(function(expected_element) { + // assert_response_in_array treats the first argument as being + // 'actual', and the second as being 'expected array'. We are + // switching them around because we want to be resilient + // against the |actual| array containing duplicates. + assert_response_in_array(expected_element, actual, description); + }); +} + +// Asserts that two arrays |actual| and |expected| contain the same +// set of Responses as determined by assert_response_equals(). The +// corresponding elements must occupy corresponding indices in their +// respective arrays. +function assert_response_array_equals(actual, expected, description) { + assert_true(Array.isArray(actual), description); + assert_equals(actual.length, expected.length, description); + actual.forEach(function(value, index) { + assert_response_equals(value, expected[index], + description + " : object[" + index + "]"); + }); +} + +// Equivalent to assert_in_array, but uses assert_response_equals. +function assert_response_in_array(actual, expected_array, description) { + assert_true(expected_array.some(function(element) { + try { + assert_response_equals(actual, element); + return true; + } catch (e) { + return false; + } + }), description); +} diff --git a/testing/web-platform/tests/service-workers/cache-storage/resources/testharness-helpers.js b/testing/web-platform/tests/service-workers/cache-storage/resources/testharness-helpers.js index 45667056fda..e4885727b32 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/resources/testharness-helpers.js +++ b/testing/web-platform/tests/service-workers/cache-storage/resources/testharness-helpers.js @@ -31,70 +31,3 @@ function assert_promise_rejects(promise, code, description) { } }); } - -// Helper for testing with Headers objects. Compares Headers instances -// by serializing |expected| and |actual| to arrays and comparing. -function assert_header_equals(actual, expected, description) { - assert_class_string(actual, "Headers", description); - var header, actual_headers = [], expected_headers = []; - for (header of actual) - actual_headers.push(header[0] + ": " + header[1]); - for (header of expected) - expected_headers.push(header[0] + ": " + header[1]); - assert_array_equals(actual_headers, expected_headers, - description + " Headers differ."); -} - -// Helper for testing with Response objects. Compares simple -// attributes defined on the interfaces, as well as the headers. It -// does not compare the response bodies. -function assert_response_equals(actual, expected, description) { - assert_class_string(actual, "Response", description); - ["type", "url", "status", "ok", "statusText"].forEach(function(attribute) { - assert_equals(actual[attribute], expected[attribute], - description + " Attributes differ: " + attribute + "."); - }); - assert_header_equals(actual.headers, expected.headers, description); -} - -// Assert that the two arrays |actual| and |expected| contain the same -// set of Responses as determined by assert_response_equals. The order -// is not significant. -// -// |expected| is assumed to not contain any duplicates. -function assert_response_array_equivalent(actual, expected, description) { - assert_true(Array.isArray(actual), description); - assert_equals(actual.length, expected.length, description); - expected.forEach(function(expected_element) { - // assert_response_in_array treats the first argument as being - // 'actual', and the second as being 'expected array'. We are - // switching them around because we want to be resilient - // against the |actual| array containing duplicates. - assert_response_in_array(expected_element, actual, description); - }); -} - -// Asserts that two arrays |actual| and |expected| contain the same -// set of Responses as determined by assert_response_equals(). The -// corresponding elements must occupy corresponding indices in their -// respective arrays. -function assert_response_array_equals(actual, expected, description) { - assert_true(Array.isArray(actual), description); - assert_equals(actual.length, expected.length, description); - actual.forEach(function(value, index) { - assert_response_equals(value, expected[index], - description + " : object[" + index + "]"); - }); -} - -// Equivalent to assert_in_array, but uses assert_response_equals. -function assert_response_in_array(actual, expected_array, description) { - assert_true(expected_array.some(function(element) { - try { - assert_response_equals(actual, element); - return true; - } catch (e) { - return false; - } - }), description); -} diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js index 49b8db4cd71..9fc597a4b4f 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-add.js @@ -16,6 +16,16 @@ cache_test(function(cache) { .then(function(result) { assert_equals(result, undefined, 'Cache.add should resolve with undefined on success.'); + return cache.match('../resources/simple.txt'); + }) + .then(function(response) { + assert_class_string(response, 'Response', + 'Cache.add should put a resource in the cache.'); + return response.text(); + }) + .then(function(body) { + assert_equals(body, 'a simple text file\n', + 'Cache.add should retrieve the correct body.'); }); }, 'Cache.add called with relative URL specified as a string'); @@ -35,6 +45,15 @@ cache_test(function(cache) { }); }, 'Cache.add called with Request object'); +cache_test(function(cache) { + var request = new Request('../resources/simple.txt', + {method: 'POST', body: 'This is a body.'}); + return assert_promise_rejects( + cache.add(request), + new TypeError(), + 'Cache.add should throw a TypeError for non-GET requests.'); + }, 'Cache.add called with POST request'); + cache_test(function(cache) { var request = new Request('../resources/simple.txt'); return cache.add(request) @@ -51,6 +70,17 @@ cache_test(function(cache) { }); }, 'Cache.add called twice with the same Request object'); +cache_test(function(cache) { + var request = new Request('../resources/simple.txt'); + return request.text() + .then(function() { + assert_false(request.bodyUsed); + }) + .then(function() { + return cache.add(request); + }); + }, 'Cache.add with request with null body (not consumed)'); + cache_test(function(cache) { return cache.add('this-does-not-exist-please-dont-create-it') .then(function(result) { @@ -84,19 +114,62 @@ cache_test(function(cache) { }, 'Cache.addAll with a mix of valid and undefined arguments'); cache_test(function(cache) { - // Assumes the existence of ../resources/simple.txt and ../resources/blank.html - var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html']; + return cache.addAll([]) + .then(function(result) { + assert_equals(result, undefined, + 'Cache.addAll should resolve with undefined on ' + + 'success.'); + return cache.keys(); + }) + .then(function(result) { + assert_equals(result.length, 0, + 'There should be no entry in the cache.'); + }); + }, 'Cache.addAll with an empty array'); + +cache_test(function(cache) { + // Assumes the existence of ../resources/simple.txt and + // ../resources/blank.html + var urls = ['../resources/simple.txt', + self.location.href, + '../resources/blank.html']; return cache.addAll(urls) .then(function(result) { assert_equals(result, undefined, 'Cache.addAll should resolve with undefined on ' + 'success.'); + return Promise.all( + urls.map(function(url) { return cache.match(url); })); + }) + .then(function(responses) { + assert_class_string( + responses[0], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_class_string( + responses[1], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_class_string( + responses[2], 'Response', + 'Cache.addAll should put a resource in the cache.'); + return Promise.all( + responses.map(function(response) { return response.text(); })); + }) + .then(function(bodies) { + assert_equals( + bodies[0], 'a simple text file\n', + 'Cache.add should retrieve the correct body.'); + assert_equals( + bodies[2], '\nEmpty doc\n', + 'Cache.add should retrieve the correct body.'); }); }, 'Cache.addAll with string URL arguments'); cache_test(function(cache) { - // Assumes the existence of ../resources/simple.txt and ../resources/blank.html - var urls = ['../resources/simple.txt', self.location.href, '../resources/blank.html']; + // Assumes the existence of ../resources/simple.txt and + // ../resources/blank.html + var urls = ['../resources/simple.txt', + self.location.href, + '../resources/blank.html']; var requests = urls.map(function(url) { return new Request(url); }); @@ -105,13 +178,38 @@ cache_test(function(cache) { assert_equals(result, undefined, 'Cache.addAll should resolve with undefined on ' + 'success.'); + return Promise.all( + urls.map(function(url) { return cache.match(url); })); + }) + .then(function(responses) { + assert_class_string( + responses[0], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_class_string( + responses[1], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_class_string( + responses[2], 'Response', + 'Cache.addAll should put a resource in the cache.'); + return Promise.all( + responses.map(function(response) { return response.text(); })); + }) + .then(function(bodies) { + assert_equals( + bodies[0], 'a simple text file\n', + 'Cache.add should retrieve the correct body.'); + assert_equals( + bodies[2], '\nEmpty doc\n', + 'Cache.add should retrieve the correct body.'); }); }, 'Cache.addAll with Request arguments'); cache_test(function(cache) { - // Assumes that ../resources/simple.txt and ../resources/blank.html exist. The second - // resource does not. - var urls = ['../resources/simple.txt', 'this-resource-should-not-exist', '../resources/blank.html']; + // Assumes that ../resources/simple.txt and ../resources/blank.html exist. + // The second resource does not. + var urls = ['../resources/simple.txt', + 'this-resource-should-not-exist', + '../resources/blank.html']; var requests = urls.map(function(url) { return new Request(url); }); @@ -120,6 +218,32 @@ cache_test(function(cache) { assert_equals(result, undefined, 'Cache.addAll should resolve with undefined on ' + 'success.'); + return Promise.all( + urls.map(function(url) { return cache.match(url); })); + }) + .then(function(responses) { + assert_class_string( + responses[0], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_class_string( + responses[1], 'Response', + 'Cache.addAll should put a resource in the cache.'); + assert_equals( + responses[1].status, 404, + 'Cache.addAll should put a 404 resource in the cache.'); + assert_class_string( + responses[2], 'Response', + 'Cache.addAll should put a resource in the cache.'); + return Promise.all( + responses.map(function(response) { return response.text(); })); + }) + .then(function(bodies) { + assert_equals( + bodies[0], 'a simple text file\n', + 'Cache.add should retrieve the correct body.'); + assert_equals( + bodies[2], '\nEmpty doc\n', + 'Cache.add should retrieve the correct body.'); }); }, 'Cache.addAll with a mix of succeeding and failing requests'); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js index 02cf6cf5fb6..716bfe5a698 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-match.js @@ -4,105 +4,6 @@ if (self.importScripts) { importScripts('../resources/test-helpers.js'); } -// A set of Request/Response pairs to be used with prepopulated_cache_test(). -var simple_entries = [ - { - name: 'a', - request: new Request('http://example.com/a'), - response: new Response('') - }, - - { - name: 'b', - request: new Request('http://example.com/b'), - response: new Response('') - }, - - { - name: 'a_with_query', - request: new Request('http://example.com/a?q=r'), - response: new Response('') - }, - - { - name: 'A', - request: new Request('http://example.com/A'), - response: new Response('') - }, - - { - name: 'a_https', - request: new Request('https://example.com/a'), - response: new Response('') - }, - - { - name: 'a_org', - request: new Request('http://example.org/a'), - response: new Response('') - }, - - { - name: 'cat', - request: new Request('http://example.com/cat'), - response: new Response('') - }, - - { - name: 'catmandu', - request: new Request('http://example.com/catmandu'), - response: new Response('') - }, - - { - name: 'cat_num_lives', - request: new Request('http://example.com/cat?lives=9'), - response: new Response('') - }, - - { - name: 'cat_in_the_hat', - request: new Request('http://example.com/cat/in/the/hat'), - response: new Response('') - } -]; - -// A set of Request/Response pairs to be used with prepopulated_cache_test(). -// These contain a mix of test cases that use Vary headers. -var vary_entries = [ - { - name: 'vary_cookie_is_cookie', - request: new Request('http://example.com/c', - {headers: {'Cookies': 'is-for-cookie'}}), - response: new Response('', - {headers: {'Vary': 'Cookies'}}) - }, - - { - name: 'vary_cookie_is_good', - request: new Request('http://example.com/c', - {headers: {'Cookies': 'is-good-enough-for-me'}}), - response: new Response('', - {headers: {'Vary': 'Cookies'}}) - }, - - { - name: 'vary_cookie_absent', - request: new Request('http://example.com/c'), - response: new Response('', - {headers: {'Vary': 'Cookies'}}) - } -]; - -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll('not-present-in-the-cache') - .then(function(result) { - assert_response_array_equivalent( - result, [], - 'Cache.matchAll should resolve with an empty array on failure.'); - }); - }, 'Cache.matchAll with no matching entries'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match('not-present-in-the-cache') .then(function(result) { @@ -111,14 +12,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with no matching entries'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(entries.a.request.url) - .then(function(result) { - assert_response_array_equals(result, [entries.a.response], - 'Cache.matchAll should match by URL.'); - }); - }, 'Cache.matchAll with URL'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.a.request.url) .then(function(result) { @@ -127,15 +20,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with URL'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(entries.a.request) - .then(function(result) { - assert_response_array_equals( - result, [entries.a.response], - 'Cache.matchAll should match by Request.'); - }); - }, 'Cache.matchAll with Request'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.a.request) .then(function(result) { @@ -144,15 +28,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with Request'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(new Request(entries.a.request.url)) - .then(function(result) { - assert_response_array_equals( - result, [entries.a.response], - 'Cache.matchAll should match by Request.'); - }); - }, 'Cache.matchAll with new Request'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(new Request(entries.a.request.url)) .then(function(result) { @@ -161,23 +36,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with new Request'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(entries.a.request, - {ignoreSearch: true}) - .then(function(result) { - assert_response_array_equivalent( - result, - [ - entries.a.response, - entries.a_with_query.response - ], - 'Cache.matchAll with ignoreSearch should ignore the ' + - 'search parameters of cached request.'); - }); - }, - 'Cache.matchAll with ignoreSearch option (request with no search ' + - 'parameters)'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.a.request, {ignoreSearch: true}) @@ -195,22 +53,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { 'Cache.match with ignoreSearch option (request with no search ' + 'parameters)'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(entries.a_with_query.request, - {ignoreSearch: true}) - .then(function(result) { - assert_response_array_equivalent( - result, - [ - entries.a.response, - entries.a_with_query.response - ], - 'Cache.matchAll with ignoreSearch should ignore the ' + - 'search parameters of request.'); - }); - }, - 'Cache.matchAll with ignoreSearch option (request with search parameter)'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.a_with_query.request, {ignoreSearch: true}) @@ -227,18 +69,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }, 'Cache.match with ignoreSearch option (request with search parameter)'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll(entries.cat.request.url + '#mouse') - .then(function(result) { - assert_response_array_equivalent( - result, - [ - entries.cat.response, - ], - 'Cache.matchAll should ignore URL fragment.'); - }); - }, 'Cache.matchAll with URL containing fragment'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match(entries.cat.request.url + '#mouse') .then(function(result) { @@ -247,16 +77,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with URL containing fragment'); -prepopulated_cache_test(simple_entries, function(cache, entries) { - return cache.matchAll('http') - .then(function(result) { - assert_response_array_equivalent( - result, [], - 'Cache.matchAll should treat query as a URL and not ' + - 'just a string fragment.'); - }); - }, 'Cache.matchAll with string fragment "http" as query'); - prepopulated_cache_test(simple_entries, function(cache, entries) { return cache.match('http') .then(function(result) { @@ -267,48 +87,6 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with string fragment "http" as query'); -prepopulated_cache_test(vary_entries, function(cache, entries) { - return cache.matchAll('http://example.com/c') - .then(function(result) { - assert_response_array_equivalent( - result, - [ - entries.vary_cookie_absent.response - ], - 'Cache.matchAll should exclude matches if a vary header is ' + - 'missing in the query request, but is present in the cached ' + - 'request.'); - }) - - .then(function() { - return cache.matchAll( - new Request('http://example.com/c', - {headers: {'Cookies': 'none-of-the-above'}})); - }) - .then(function(result) { - assert_response_array_equivalent( - result, - [ - ], - 'Cache.matchAll should exclude matches if a vary header is ' + - 'missing in the cached request, but is present in the query ' + - 'request.'); - }) - - .then(function() { - return cache.matchAll( - new Request('http://example.com/c', - {headers: {'Cookies': 'is-for-cookie'}})); - }) - .then(function(result) { - assert_response_array_equivalent( - result, - [entries.vary_cookie_is_cookie.response], - 'Cache.matchAll should match the entire header if a vary header ' + - 'is present in both the query and cached requests.'); - }); - }, 'Cache.matchAll with responses containing "Vary" header'); - prepopulated_cache_test(vary_entries, function(cache, entries) { return cache.match('http://example.com/c') .then(function(result) { @@ -321,21 +99,6 @@ prepopulated_cache_test(vary_entries, function(cache, entries) { }); }, 'Cache.match with responses containing "Vary" header'); -prepopulated_cache_test(vary_entries, function(cache, entries) { - return cache.matchAll('http://example.com/c', - {ignoreVary: true}) - .then(function(result) { - assert_response_array_equivalent( - result, - [ - entries.vary_cookie_is_cookie.response, - entries.vary_cookie_is_good.response, - entries.vary_cookie_absent.response, - ], - 'Cache.matchAll should honor "ignoreVary" parameter.'); - }); - }, 'Cache.matchAll with "ignoreVary" parameter'); - cache_test(function(cache) { var request = new Request('http://example.com'); var response; @@ -397,7 +160,7 @@ cache_test(function(cache) { }, 'Cache.match invoked multiple times for the same Request/Response'); prepopulated_cache_test(simple_entries, function(cache, entries) { - var request = new Request(entries.a.request, { method: 'POST' }); + var request = new Request(entries.a.request.clone(), {method: 'POST'}); return cache.match(request) .then(function(result) { assert_equals(result, undefined, @@ -405,38 +168,26 @@ prepopulated_cache_test(simple_entries, function(cache, entries) { }); }, 'Cache.match with POST Request'); -// Helpers --- +prepopulated_cache_test(simple_entries, function(cache, entries) { + var response = entries.non_2xx_response.response; + return cache.match(entries.non_2xx_response.request.url) + .then(function(result) { + assert_response_equals( + result, entries.non_2xx_response.response, + 'Cache.match should return a Response object that has the ' + + 'same properties as a stored non-2xx response.'); + }); + }, 'Cache.match with a non-2xx Response'); -// Run |test_function| with a Cache object as its only parameter. Prior to the -// call, the Cache is populated by cache entries from |entries|. The latter is -// expected to be an Object mapping arbitrary keys to objects of the form -// {request: , response: }. There's no -// guarantee on the order in which entries will be added to the cache. -// -// |test_function| should return a Promise that can be used with promise_test. -function prepopulated_cache_test(entries, test_function, description) { - cache_test(function(cache) { - var p = Promise.resolve(); - var hash = {}; - entries.forEach(function(entry) { - p = p.then(function() { - return cache.put(entry.request.clone(), - entry.response.clone()) - .catch(function(e) { - assert_unreached('Test setup failed for entry ' + - entry.name + ': ' + e); - }); - }); - hash[entry.name] = entry; +prepopulated_cache_test(simple_entries, function(cache, entries) { + var response = entries.error_response.response; + return cache.match(entries.error_response.request.url) + .then(function(result) { + assert_response_equals( + result, entries.error_response.response, + 'Cache.match should return a Response object that has the ' + + 'same properties as a stored network error response.'); }); - p = p.then(function() { - assert_equals(Object.keys(hash).length, entries.length); - }); - - return p.then(function() { - return test_function(cache, hash); - }); - }, description); -} + }, 'Cache.match with a network error Response'); done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js new file mode 100644 index 00000000000..2bc661a5c90 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-matchAll.js @@ -0,0 +1,154 @@ +if (self.importScripts) { + importScripts('/resources/testharness.js'); + importScripts('../resources/testharness-helpers.js'); + importScripts('../resources/test-helpers.js'); +} + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll('not-present-in-the-cache') + .then(function(result) { + assert_response_array_equivalent( + result, [], + 'Cache.matchAll should resolve with an empty array on failure.'); + }); + }, 'Cache.matchAll with no matching entries'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request.url) + .then(function(result) { + assert_response_array_equals(result, [entries.a.response], + 'Cache.matchAll should match by URL.'); + }); + }, 'Cache.matchAll with URL'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request) + .then(function(result) { + assert_response_array_equals( + result, [entries.a.response], + 'Cache.matchAll should match by Request.'); + }); + }, 'Cache.matchAll with Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(new Request(entries.a.request.url)) + .then(function(result) { + assert_response_array_equals( + result, [entries.a.response], + 'Cache.matchAll should match by Request.'); + }); + }, 'Cache.matchAll with new Request'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a.request, + {ignoreSearch: true}) + .then(function(result) { + assert_response_array_equivalent( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.matchAll with ignoreSearch should ignore the ' + + 'search parameters of cached request.'); + }); + }, + 'Cache.matchAll with ignoreSearch option (request with no search ' + + 'parameters)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.a_with_query.request, + {ignoreSearch: true}) + .then(function(result) { + assert_response_array_equivalent( + result, + [ + entries.a.response, + entries.a_with_query.response + ], + 'Cache.matchAll with ignoreSearch should ignore the ' + + 'search parameters of request.'); + }); + }, + 'Cache.matchAll with ignoreSearch option (request with search parameter)'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll(entries.cat.request.url + '#mouse') + .then(function(result) { + assert_response_array_equivalent( + result, + [ + entries.cat.response, + ], + 'Cache.matchAll should ignore URL fragment.'); + }); + }, 'Cache.matchAll with URL containing fragment'); + +prepopulated_cache_test(simple_entries, function(cache, entries) { + return cache.matchAll('http') + .then(function(result) { + assert_response_array_equivalent( + result, [], + 'Cache.matchAll should treat query as a URL and not ' + + 'just a string fragment.'); + }); + }, 'Cache.matchAll with string fragment "http" as query'); + +prepopulated_cache_test(vary_entries, function(cache, entries) { + return cache.matchAll('http://example.com/c') + .then(function(result) { + assert_response_array_equivalent( + result, + [ + entries.vary_cookie_absent.response + ], + 'Cache.matchAll should exclude matches if a vary header is ' + + 'missing in the query request, but is present in the cached ' + + 'request.'); + }) + + .then(function() { + return cache.matchAll( + new Request('http://example.com/c', + {headers: {'Cookies': 'none-of-the-above'}})); + }) + .then(function(result) { + assert_response_array_equivalent( + result, + [ + ], + 'Cache.matchAll should exclude matches if a vary header is ' + + 'missing in the cached request, but is present in the query ' + + 'request.'); + }) + + .then(function() { + return cache.matchAll( + new Request('http://example.com/c', + {headers: {'Cookies': 'is-for-cookie'}})); + }) + .then(function(result) { + assert_response_array_equivalent( + result, + [entries.vary_cookie_is_cookie.response], + 'Cache.matchAll should match the entire header if a vary header ' + + 'is present in both the query and cached requests.'); + }); + }, 'Cache.matchAll with responses containing "Vary" header'); + +prepopulated_cache_test(vary_entries, function(cache, entries) { + return cache.matchAll('http://example.com/c', + {ignoreVary: true}) + .then(function(result) { + assert_response_array_equivalent( + result, + [ + entries.vary_cookie_is_cookie.response, + entries.vary_cookie_is_good.response, + entries.vary_cookie_absent.response + ], + 'Cache.matchAll should honor "ignoreVary" parameter.'); + }); + }, 'Cache.matchAll with "ignoreVary" parameter'); + +done(); diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js index 1d0a5b9fa14..8dbaf9789d5 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-put.js @@ -250,16 +250,22 @@ cache_test(function(cache) { assert_true( response.bodyUsed, '[https://fetch.spec.whatwg.org/#concept-body-consume-body] ' + - 'The text() method should set "body used" flag.'); - return assert_promise_rejects( - cache.put(new Request(test_url), response), - new TypeError, - '[https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-put] ' + - 'Cache put should reject with TypeError when Response ' + - 'body is already used.'); - }); + 'The text() method should make the body disturbed.'); + var request = new Request(test_url); + return cache.put(request, response).then(() => { + assert_unreached('cache.put should be rejected'); + }, () => {}); + }); }, 'Cache.put with a used response body'); +cache_test(function(cache) { + var response = new Response(test_body); + return cache.put(new Request(test_url), response) + .then(function() { + assert_throws(new TypeError(), () => response.body.getReader()); + }); + }, 'getReader() after Cache.put'); + cache_test(function(cache) { return assert_promise_rejects( cache.put(new Request(test_url), diff --git a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js index a8d4e7e61de..594b01b5810 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js +++ b/testing/web-platform/tests/service-workers/cache-storage/script-tests/cache-storage.js @@ -106,7 +106,6 @@ promise_test(function(t) { promise_test(function(t) { var cache_name = 'cache-storage/open'; - var url = '../resources/simple.txt'; var cache; return self.caches.delete(cache_name) .then(function() { @@ -135,7 +134,7 @@ promise_test(function(t) { assert_array_equals(actual_urls, expected_urls, 'CacheStorage.open should return a new Cache ' + 'object for the same backing store.'); - }) + }); }, 'CacheStorage.open with existing cache'); promise_test(function(t) { diff --git a/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-match.https.html b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-match.https.html index 859b1cd0554..6126568fb46 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-match.https.html +++ b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-match.https.html @@ -1,5 +1,5 @@ -Cache.match and Cache.matchAll +Cache.match diff --git a/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-matchAll.https.html b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-matchAll.https.html new file mode 100644 index 00000000000..878fe1209f3 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/serviceworker/cache-matchAll.https.html @@ -0,0 +1,10 @@ + +Cache.matchAll + + + + + + diff --git a/testing/web-platform/tests/service-workers/cache-storage/window/cache-match.https.html b/testing/web-platform/tests/service-workers/cache-storage/window/cache-match.https.html index 093df8db4a8..a99d700accd 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/window/cache-match.https.html +++ b/testing/web-platform/tests/service-workers/cache-storage/window/cache-match.https.html @@ -1,5 +1,5 @@ -Cache Storage: Cache.match and Cache.matchAll +Cache Storage: Cache.match diff --git a/testing/web-platform/tests/service-workers/cache-storage/window/cache-matchAll.https.html b/testing/web-platform/tests/service-workers/cache-storage/window/cache-matchAll.https.html new file mode 100644 index 00000000000..3bd92887a49 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/window/cache-matchAll.https.html @@ -0,0 +1,9 @@ + +Cache.matchAll + + + + + + + diff --git a/testing/web-platform/tests/service-workers/cache-storage/worker/cache-match.https.html b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-match.https.html index b0926fce360..5304529b775 100644 --- a/testing/web-platform/tests/service-workers/cache-storage/worker/cache-match.https.html +++ b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-match.https.html @@ -1,5 +1,5 @@ -Cache.match and Cache.matchAll +Cache.match diff --git a/testing/web-platform/tests/service-workers/cache-storage/worker/cache-matchAll.https.html b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-matchAll.https.html new file mode 100644 index 00000000000..242ccb68799 --- /dev/null +++ b/testing/web-platform/tests/service-workers/cache-storage/worker/cache-matchAll.https.html @@ -0,0 +1,9 @@ + +Cache.matchAll + + + + + diff --git a/testing/web-platform/tests/shadow-dom/OWNERS b/testing/web-platform/tests/shadow-dom/OWNERS new file mode 100644 index 00000000000..fd2132cf82d --- /dev/null +++ b/testing/web-platform/tests/shadow-dom/OWNERS @@ -0,0 +1,5 @@ +@kojiishi +@rniwa +@sideshowbarker +@sizuhiko +@yutak diff --git a/testing/web-platform/tests/subresource-integrity/OWNERS b/testing/web-platform/tests/subresource-integrity/OWNERS new file mode 100644 index 00000000000..8f7edaa358b --- /dev/null +++ b/testing/web-platform/tests/subresource-integrity/OWNERS @@ -0,0 +1,6 @@ +@metromoxie +@fmarier +@jonathanKingston +@mikewest +@hillbrad +@mastahyeti diff --git a/testing/web-platform/tests/svg/OWNERS b/testing/web-platform/tests/svg/OWNERS new file mode 100644 index 00000000000..aeee0aac345 --- /dev/null +++ b/testing/web-platform/tests/svg/OWNERS @@ -0,0 +1,2 @@ +@heycam +@Ms2ger diff --git a/testing/web-platform/tests/touch-events/OWNERS b/testing/web-platform/tests/touch-events/OWNERS new file mode 100644 index 00000000000..ef580b2ebe7 --- /dev/null +++ b/testing/web-platform/tests/touch-events/OWNERS @@ -0,0 +1,3 @@ +@jtangelder +@zqzhang +@cynthia diff --git a/testing/web-platform/tests/typedarrays/OWNERS b/testing/web-platform/tests/typedarrays/OWNERS new file mode 100644 index 00000000000..f02987223e3 --- /dev/null +++ b/testing/web-platform/tests/typedarrays/OWNERS @@ -0,0 +1,4 @@ +@koustuvsinha +@zqzhang +@haoxli +@Ms2ger diff --git a/testing/web-platform/tests/url/OWNERS b/testing/web-platform/tests/url/OWNERS new file mode 100644 index 00000000000..b91af6024f0 --- /dev/null +++ b/testing/web-platform/tests/url/OWNERS @@ -0,0 +1,8 @@ +@mikewest +@frewsxcv +@tomalec +@rubys +@sideshowbarker +@zcorpan +@xiaojunwu +@smola diff --git a/testing/web-platform/tests/user-timing/OWNERS b/testing/web-platform/tests/user-timing/OWNERS new file mode 100644 index 00000000000..5a05f35799c --- /dev/null +++ b/testing/web-platform/tests/user-timing/OWNERS @@ -0,0 +1 @@ +@plehegar diff --git a/testing/web-platform/tests/vibration/OWNERS b/testing/web-platform/tests/vibration/OWNERS new file mode 100644 index 00000000000..4020ed82efc --- /dev/null +++ b/testing/web-platform/tests/vibration/OWNERS @@ -0,0 +1,3 @@ +@dontcallmedom +@zqzhang +@xinliux diff --git a/testing/web-platform/tests/web-animations/OWNERS b/testing/web-platform/tests/web-animations/OWNERS new file mode 100644 index 00000000000..fd38f5e5b9b --- /dev/null +++ b/testing/web-platform/tests/web-animations/OWNERS @@ -0,0 +1 @@ +@birtles diff --git a/testing/web-platform/tests/webaudio/OWNERS b/testing/web-platform/tests/webaudio/OWNERS new file mode 100644 index 00000000000..d4865fcd085 --- /dev/null +++ b/testing/web-platform/tests/webaudio/OWNERS @@ -0,0 +1 @@ +@chrislo diff --git a/testing/web-platform/tests/webdriver/OWNERS b/testing/web-platform/tests/webdriver/OWNERS new file mode 100644 index 00000000000..45cf0102cd8 --- /dev/null +++ b/testing/web-platform/tests/webdriver/OWNERS @@ -0,0 +1,4 @@ +@andreastt +@lukeis +@AutomatedTester +@shs96c diff --git a/testing/web-platform/tests/webgl/conformance-1.0.3/conformance/programs/program-test.html b/testing/web-platform/tests/webgl/conformance-1.0.3/conformance/programs/program-test.html index 53e1e61e3e3..18759f64af3 100644 --- a/testing/web-platform/tests/webgl/conformance-1.0.3/conformance/programs/program-test.html +++ b/testing/web-platform/tests/webgl/conformance-1.0.3/conformance/programs/program-test.html @@ -228,11 +228,11 @@ function go() { checkGetAttachedShaders([fs], [], [fs], "attaching a single shader should give the expected list"); checkGetAttachedShaders([fs, vs], [], [fs, vs], "attaching some shaders should give the expected list"); - checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it shoud leave an empty list"); + checkGetAttachedShaders([fs], [fs], [], "attaching a shader and detaching it should leave an empty list"); checkGetAttachedShaders([fs, vs], [fs, vs], [], - "attaching some shaders and detaching them in same order shoud leave an empty list"); + "attaching some shaders and detaching them in same order should leave an empty list"); checkGetAttachedShaders([fs, vs], [vs, fs], [], - "attaching some shaders and detaching them in random order shoud leave an empty list"); + "attaching some shaders and detaching them in random order should leave an empty list"); checkGetAttachedShaders([fs, vs], [vs], [fs], "attaching and detaching some shaders should leave the difference list"); checkGetAttachedShaders([fs, vs], [fs], [vs], diff --git a/testing/web-platform/tests/webmessaging/OWNERS b/testing/web-platform/tests/webmessaging/OWNERS new file mode 100644 index 00000000000..bff9fad87de --- /dev/null +++ b/testing/web-platform/tests/webmessaging/OWNERS @@ -0,0 +1,6 @@ +@zqzhang +@sideshowbarker +@plehegar +@aogilvie +@Ms2ger +@jdm diff --git a/testing/web-platform/tests/webrtc/OWNERS b/testing/web-platform/tests/webrtc/OWNERS new file mode 100644 index 00000000000..1deb98d49c9 --- /dev/null +++ b/testing/web-platform/tests/webrtc/OWNERS @@ -0,0 +1,4 @@ +@dontcallmedom +@tidoust +@alvestrand +@phoglund diff --git a/testing/web-platform/tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm b/testing/web-platform/tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm index a6b429397b3..56330805f83 100644 --- a/testing/web-platform/tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm +++ b/testing/web-platform/tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm @@ -17,7 +17,7 @@ var isOpenCalled = false; wsocket.addEventListener('open', testOpen.step_func(function (evt) { - assert_equals(wsocket.protocol, __PROTOCOL, "protocol should be set to echo"); + assert_equals(wsocket.protocol, "echo", "protocol should be set to echo"); wsocket.close(); isOpenCalled = true; testOpen.done(); diff --git a/testing/web-platform/tests/websockets/OWNERS b/testing/web-platform/tests/websockets/OWNERS new file mode 100644 index 00000000000..a34c94d717f --- /dev/null +++ b/testing/web-platform/tests/websockets/OWNERS @@ -0,0 +1,9 @@ +@kristijanburnik +@zcorpan +@plehegar +@zqzhang +@sideshowbarker +@foolip +@Jxck +@jdm +@Ms2ger diff --git a/testing/web-platform/tests/websockets/websocket.js b/testing/web-platform/tests/websockets/websocket.js index 79b7bd59c58..1563dc2175c 100644 --- a/testing/web-platform/tests/websockets/websocket.js +++ b/testing/web-platform/tests/websockets/websocket.js @@ -4,26 +4,9 @@ var __SECURE__PORT = {{ports[wss][0]}}; var __NEW__PORT = __PORT; //All ports are non-default for now var __NEW__SECURE__PORT = __SECURE__PORT; //All ports are non-default for now var __PATH = "echo"; -var __CONTROLPATH = "control"; -var __PROTOCOL = "echo"; -var __PROTOCOLS = ["echo", "chat"]; -var __REPEATED__PROTOCOLS = ["echo", "echo"]; -var __REPEATED__PROTOCOLS_CASE_INSENSITIVE = ["echo", "eCho"]; -var __URL; -var __IS__WEBSOCKET; -var __PASS = "Pass"; -var __FAIL = "Fail"; var wsocket; -var csocket; var data; -// variables for testing Close Browser/Navigate Away scenarios -var isAssociated = false; -var guid; -var dataReceived; -var closeCode; -var urlToOpen; - function IsWebSocket() { if (!window.WebSocket) { assert_true(false, "Browser does not support WebSocket"); @@ -32,92 +15,93 @@ function IsWebSocket() { function CreateWebSocketNonAbsolute() { IsWebSocket(); - __URL = __SERVER__NAME; - wsocket = new WebSocket(__URL); + var url = __SERVER__NAME; + wsocket = new WebSocket(url); } function CreateWebSocketNonWsScheme() { IsWebSocket(); - __URL = "http://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL); + var url = "http://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url); } function CreateWebSocketNonAsciiProtocol(nonAsciiProtocol) { IsWebSocket(); - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL, nonAsciiProtocol); + var url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url, nonAsciiProtocol); } function CreateWebSocketWithAsciiSep(asciiWithSep) { IsWebSocket(); - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL, asciiWithSep); + var url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url, asciiWithSep); } function CreateWebSocketWithBlockedPort(blockedPort) { IsWebSocket(); - __URL = "wss://" + __SERVER__NAME + ":" + blockedPort + "/" + __PATH; - wsocket = new WebSocket(__URL); + var url = "wss://" + __SERVER__NAME + ":" + blockedPort + "/" + __PATH; + wsocket = new WebSocket(url); } function CreateWebSocketWithSpaceInUrl(urlWithSpace) { IsWebSocket(); - __URL = "ws://" + urlWithSpace + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL); + var url = "ws://" + urlWithSpace + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url); } function CreateWebSocketWithSpaceInProtocol(protocolWithSpace) { IsWebSocket(); - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL, protocolWithSpace); + var url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url, protocolWithSpace); } function CreateWebSocketWithRepeatedProtocols() { IsWebSocket(); - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL, __REPEATED__PROTOCOLS); + var url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url, ["echo", "echo"]); } function CreateWebSocketWithRepeatedProtocolsCaseInsensitive() { IsWebSocket(); - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; - wsocket = new WebSocket(__URL, __REPEATED__PROTOCOLS_CASE_INSENSITIVE); + var url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + wsocket = new WebSocket(url, ["echo", "eCho"]); } function CreateWebSocket(isSecure, isProtocol, isProtocols) { IsWebSocket(); + var url; if (isSecure) { if (__SECURE__PORT === null) { throw new Error("wss not yet supported"); } - __URL = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/" + __PATH; + url = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/" + __PATH; } else { - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; + url = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH; } if (isProtocol) { - wsocket = new WebSocket(__URL, __PROTOCOL); + wsocket = new WebSocket(url, "echo"); } else if (isProtocols) { - wsocket = new WebSocket(__URL, __PROTOCOLS); + wsocket = new WebSocket(url, ["echo", "chat"]); } else { - wsocket = new WebSocket(__URL); + wsocket = new WebSocket(url); } return wsocket; } function CreateControlWebSocket(isSecure) { IsWebSocket(); + var url; if (isSecure) { - __URL = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/" + __CONTROLPATH; + url = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/control"; } else { - __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __CONTROLPATH; + url = "ws://" + __SERVER__NAME + ":" + __PORT + "/control"; } - csocket = new WebSocket(__URL); - return csocket; + return new WebSocket(url); } diff --git a/testing/web-platform/tests/webstorage/OWNERS b/testing/web-platform/tests/webstorage/OWNERS new file mode 100644 index 00000000000..3b7fb5d888f --- /dev/null +++ b/testing/web-platform/tests/webstorage/OWNERS @@ -0,0 +1,9 @@ +@siusin +@inexorabletash +@zqzhang +@chunywang +@kangxu +@plehegar +@ibelem +@jdm +@Ms2ger diff --git a/testing/web-platform/tests/workers/OWNERS b/testing/web-platform/tests/workers/OWNERS new file mode 100644 index 00000000000..d211ea968e2 --- /dev/null +++ b/testing/web-platform/tests/workers/OWNERS @@ -0,0 +1,6 @@ +@zqzhang +@chunywang +@zcorpan +@caitp +@Ms2ger +@jdm diff --git a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.html b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.html deleted file mode 100644 index 00398c78077..00000000000 --- a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.html +++ /dev/null @@ -1,26 +0,0 @@ - - -importScripts no arguments - - -
    - - diff --git a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.worker.js b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.worker.js new file mode 100644 index 00000000000..aa86c8ef177 --- /dev/null +++ b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/001.worker.js @@ -0,0 +1,7 @@ +importScripts("/resources/testharness.js"); + +test(function() { + importScripts(); +}); + +done(); diff --git a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.html b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.html deleted file mode 100644 index e7d52e9797d..00000000000 --- a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.html +++ /dev/null @@ -1,32 +0,0 @@ - - -importScripts resolving urls - - -
    - - diff --git a/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.worker.js b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.worker.js new file mode 100644 index 00000000000..2cecbcb5352 --- /dev/null +++ b/testing/web-platform/tests/workers/interfaces/WorkerUtils/importScripts/002.worker.js @@ -0,0 +1,11 @@ +importScripts("/resources/testharness.js"); + +test(function() { + var ran = false; + assert_throws("SyntaxError", function() { + importScripts('data:text/javascript,ran=true','http://foo bar'); + }); + assert_false(ran, 'first argument to importScripts ran'); +}); + +done(); From d9ca2f5496a91ab229ee781dc06c7b1d936c9de2 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 3 Feb 2016 07:53:49 +0000 Subject: [PATCH 017/160] Bug 1245460 - Update web-platform-tests expected data to revision af65262f5f3400024279c526117489f1f11d3233, a=testonly --- ...oll-restoration-fragment-scrolling-cross-origin.html.ini | 6 ++++++ .../semantics/forms/the-input-element/checkbox.html.ini | 5 +---- .../html/semantics/forms/the-input-element/radio.html.ini | 2 +- .../cache-storage/serviceworker/cache-add.https.html.ini | 5 +++++ .../cache-storage/window/cache-add.https.html.ini | 5 +++++ .../cache-storage/worker/cache-add.https.html.ini | 5 +++++ 6 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini create mode 100644 testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini create mode 100644 testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini create mode 100644 testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini diff --git a/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini b/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini new file mode 100644 index 00000000000..ae72b8550f3 --- /dev/null +++ b/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html.ini @@ -0,0 +1,6 @@ +[scroll-restoration-fragment-scrolling-cross-origin.html] + type: testharness + expected: ERROR + [Manual scroll restoration should take precedent over scrolling to fragment in cross origin navigation] + expected: TIMEOUT + diff --git a/testing/web-platform/meta/html/semantics/forms/the-input-element/checkbox.html.ini b/testing/web-platform/meta/html/semantics/forms/the-input-element/checkbox.html.ini index e1846d40560..5f97421f2bf 100644 --- a/testing/web-platform/meta/html/semantics/forms/the-input-element/checkbox.html.ini +++ b/testing/web-platform/meta/html/semantics/forms/the-input-element/checkbox.html.ini @@ -3,9 +3,6 @@ [click on mutable checkbox fires the input and change events] expected: FAIL - [canceled activation steps on unchecked checkbox] - expected: FAIL - - [canceled activation steps on unchecked checkbox (indeterminate=true in onclick)] + [click on mutable checkbox fires a click event, then an input event, then a change event] expected: FAIL diff --git a/testing/web-platform/meta/html/semantics/forms/the-input-element/radio.html.ini b/testing/web-platform/meta/html/semantics/forms/the-input-element/radio.html.ini index b73b3614c96..0f6a91b11c5 100644 --- a/testing/web-platform/meta/html/semantics/forms/the-input-element/radio.html.ini +++ b/testing/web-platform/meta/html/semantics/forms/the-input-element/radio.html.ini @@ -3,6 +3,6 @@ [click on mutable radio fires the input event] expected: FAIL - [canceled activation steps on unchecked radio] + [click on mutable radio fires click event, then input event, then change event] expected: FAIL diff --git a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini new file mode 100644 index 00000000000..b67f2f79fd2 --- /dev/null +++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini @@ -0,0 +1,5 @@ +[cache-add.https.html] + type: testharness + [Cache.add with request with null body (not consumed)] + expected: FAIL + diff --git a/testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini new file mode 100644 index 00000000000..b67f2f79fd2 --- /dev/null +++ b/testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini @@ -0,0 +1,5 @@ +[cache-add.https.html] + type: testharness + [Cache.add with request with null body (not consumed)] + expected: FAIL + diff --git a/testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini b/testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini new file mode 100644 index 00000000000..b67f2f79fd2 --- /dev/null +++ b/testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini @@ -0,0 +1,5 @@ +[cache-add.https.html] + type: testharness + [Cache.add with request with null body (not consumed)] + expected: FAIL + From b75a2b1b129a461e6e9350e9278651b83f4fd1a3 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 3 Feb 2016 09:56:21 +0100 Subject: [PATCH 018/160] Bug 1245421: Remove dead function CoercesToDouble; r=h4writer --- js/src/jit/TypePolicy.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/js/src/jit/TypePolicy.h b/js/src/jit/TypePolicy.h index ff31b547674..9d671bb20f4 100644 --- a/js/src/jit/TypePolicy.h +++ b/js/src/jit/TypePolicy.h @@ -525,14 +525,6 @@ class FilterTypeSetPolicy final : public TypePolicy virtual bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override; }; -static inline bool -CoercesToDouble(MIRType type) -{ - if (type == MIRType_Undefined || IsFloatingPointType(type)) - return true; - return false; -} - #undef SPECIALIZATION_DATA_ #undef INHERIT_DATA_ #undef EMPTY_DATA_ From 5d01e450c8107de80fe1ee8a032d56e2c6a9aa2a Mon Sep 17 00:00:00 2001 From: Jonathan Howard Date: Thu, 21 Jan 2016 07:12:00 +0100 Subject: [PATCH 019/160] Bug 1204809 - Notify (don't hang) third party windows when adding shortcut icon. r=jmathies --- widget/windows/WinUtils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 79fb2e74711..9ee8226ee34 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -1379,9 +1379,8 @@ NS_IMETHODIMP AsyncEncodeAndWriteIcon::Run() fclose(file); NS_ENSURE_SUCCESS(rv, rv); - // Cleanup if (mURLShortcut) { - SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0); + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0); } return rv; } From 9d815381cf778d6baee28c07ce9e2e7a01cf6fb8 Mon Sep 17 00:00:00 2001 From: "Nils Ohlmeier [:drno]" Date: Tue, 3 Nov 2015 17:21:35 -0800 Subject: [PATCH 020/160] Bug 1214269 - read multiple DTLS packets from NSS if present. r=mt r=jesup --- media/mtransport/test/transport_unittests.cpp | 75 ++++++++++++++++--- .../third_party/nICEr/src/ice/ice_socket.c | 2 +- media/mtransport/transportlayerdtls.cpp | 39 +++++----- media/mtransport/transportlayerloopback.cpp | 16 +++- media/mtransport/transportlayerloopback.h | 16 +++- 5 files changed, 114 insertions(+), 34 deletions(-) diff --git a/media/mtransport/test/transport_unittests.cpp b/media/mtransport/test/transport_unittests.cpp index 70271de769d..2c2d0f8251c 100644 --- a/media/mtransport/test/transport_unittests.cpp +++ b/media/mtransport/test/transport_unittests.cpp @@ -91,8 +91,6 @@ class TransportLayerDummy : public TransportLayer { bool *destroyed_; }; -class TransportLayerLossy; - class Inspector { public: virtual ~Inspector() {} @@ -440,7 +438,7 @@ class TransportTestPeer : public sigslot::has_slots<> { public: TransportTestPeer(nsCOMPtr target, std::string name) : name_(name), target_(target), - received_(0), flow_(new TransportFlow(name)), + received_packets_(0),received_bytes_(0),flow_(new TransportFlow(name)), loopback_(new TransportLayerLoopback()), logging_(new TransportLayerLogging()), lossy_(new TransportLayerLossy()), @@ -724,13 +722,18 @@ class TransportTestPeer : public sigslot::has_slots<> { void PacketReceived(TransportFlow * flow, const unsigned char* data, size_t len) { std::cerr << "Received " << len << " bytes" << std::endl; - ++received_; + ++received_packets_; + received_bytes_ += len; } void SetLoss(uint32_t loss) { lossy_->SetLoss(loss); } + void SetCombinePackets(bool combine) { + loopback_->CombinePackets(combine); + } + void SetInspector(UniquePtr inspector) { lossy_->SetInspector(Move(inspector)); } @@ -768,7 +771,9 @@ class TransportTestPeer : public sigslot::has_slots<> { return state() == TransportLayer::TS_ERROR; } - size_t received() { return received_; } + size_t receivedPackets() { return received_packets_; } + + size_t receivedBytes() { return received_bytes_; } uint16_t cipherSuite() const { nsresult rv; @@ -798,7 +803,8 @@ class TransportTestPeer : public sigslot::has_slots<> { private: std::string name_; nsCOMPtr target_; - size_t received_; + size_t received_packets_; + size_t received_bytes_; RefPtr flow_; TransportLayerLoopback *loopback_; TransportLayerLogging *logging_; @@ -919,8 +925,8 @@ class TransportTest : public ::testing::Test { ASSERT_TRUE_WAIT(p2_->connected(), 10000); } - void TransferTest(size_t count) { - unsigned char buf[1000]; + void TransferTest(size_t count, size_t bytes = 1024) { + unsigned char buf[bytes]; for (size_t i= 0; i 0); } - std::cerr << "Received == " << p2_->received() << std::endl; - ASSERT_TRUE_WAIT(count == p2_->received(), 10000); + std::cerr << "Received == " << p2_->receivedPackets() << " packets" << std::endl; + ASSERT_TRUE_WAIT(count == p2_->receivedPackets(), 10000); + ASSERT_TRUE((count * sizeof(buf)) == p2_->receivedBytes()); } protected: @@ -1143,6 +1150,28 @@ TEST_F(TransportTest, TestTransfer) { TransferTest(1); } +TEST_F(TransportTest, TestTransferMaxSize) { + SetDtlsPeer(); + ConnectSocket(); + /* transportlayerdtls uses a 9216 bytes buffer - as this test uses the + * loopback implementation it does not have to take into account the extra + * bytes added by the DTLS layer below. */ + TransferTest(1, 9216); +} + +TEST_F(TransportTest, TestTransferMultiple) { + SetDtlsPeer(); + ConnectSocket(); + TransferTest(3); +} + +TEST_F(TransportTest, TestTransferCombinedPackets) { + SetDtlsPeer(); + ConnectSocket(); + p2_->SetCombinePackets(true); + TransferTest(3); +} + TEST_F(TransportTest, TestConnectLoseFirst) { SetDtlsPeer(); p1_->SetLoss(0); @@ -1155,10 +1184,32 @@ TEST_F(TransportTest, TestConnectIce) { ConnectIce(); } -TEST_F(TransportTest, TestTransferIce) { +TEST_F(TransportTest, TestTransferIceMaxSize) { SetDtlsPeer(); ConnectIce(); - TransferTest(1); + /* nICEr and transportlayerdtls both use 9216 bytes buffers. But the DTLS + * layer add extra bytes to the packet, which size depends on chosen cipher + * etc. Sending more then 9216 bytes works, but on the receiving side the call + * to PR_recvfrom() will truncate any packet bigger then nICEr's buffer size + * of 9216 bytes, which then results in the DTLS layer discarding the packet. + * Therefore we leave some headroom (according to + * https://bugzilla.mozilla.org/show_bug.cgi?id=1214269#c29 256 bytes should + * be save choice) here for the DTLS bytes to make it safely into the + * receiving buffer in nICEr. */ + TransferTest(1, 8960); +} + +TEST_F(TransportTest, TestTransferIceMultiple) { + SetDtlsPeer(); + ConnectIce(); + TransferTest(3); +} + +TEST_F(TransportTest, TestTransferIceCombinedPackets) { + SetDtlsPeer(); + ConnectIce(); + p2_->SetCombinePackets(true); + TransferTest(3); } // test the default configuration against a peer that supports only diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c index e19ae5a4ae9..3f205be8373 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c @@ -46,7 +46,7 @@ static void nr_ice_socket_readable_cb(NR_SOCKET s, int how, void *cb_arg) int r; nr_ice_stun_ctx *sc1,*sc2; nr_ice_socket *sock=cb_arg; - UCHAR buf[8192]; + UCHAR buf[9216]; char string[256]; nr_transport_addr addr; int len; diff --git a/media/mtransport/transportlayerdtls.cpp b/media/mtransport/transportlayerdtls.cpp index 4c413a8f31f..10c32d39a18 100644 --- a/media/mtransport/transportlayerdtls.cpp +++ b/media/mtransport/transportlayerdtls.cpp @@ -969,26 +969,31 @@ void TransportLayerDtls::PacketReceived(TransportLayer* layer, // Now try a recv if we're open, since there might be data left if (state_ == TS_OPEN) { - unsigned char buf[2000]; + // nICEr uses a 9216 bytes buffer to allow support for jumbo frames + unsigned char buf[9216]; - int32_t rv = PR_Recv(ssl_fd_, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT); - if (rv > 0) { - // We have data - MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS"); - SignalPacketReceived(this, buf, rv); - } else if (rv == 0) { - TL_SET_STATE(TS_CLOSED); - } else { - int32_t err = PR_GetError(); - - if (err == PR_WOULD_BLOCK_ERROR) { - // This gets ignored - MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Receive would have blocked"); + int32_t rv; + // One packet might contain several DTLS packets + do { + rv = PR_Recv(ssl_fd_, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT); + if (rv > 0) { + // We have data + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS"); + SignalPacketReceived(this, buf, rv); + } else if (rv == 0) { + TL_SET_STATE(TS_CLOSED); } else { - MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err); - TL_SET_STATE(TS_ERROR); + int32_t err = PR_GetError(); + + if (err == PR_WOULD_BLOCK_ERROR) { + // This gets ignored + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Receive would have blocked"); + } else { + MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err); + TL_SET_STATE(TS_ERROR); + } } - } + } while (rv > 0); } } diff --git a/media/mtransport/transportlayerloopback.cpp b/media/mtransport/transportlayerloopback.cpp index a1a3d2ccdc6..11c3b4244df 100644 --- a/media/mtransport/transportlayerloopback.cpp +++ b/media/mtransport/transportlayerloopback.cpp @@ -78,13 +78,23 @@ TransportLayerLoopback::SendPacket(const unsigned char *data, size_t len) { nsresult TransportLayerLoopback::QueuePacket(const unsigned char *data, size_t len) { - MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << len); MOZ_ASSERT(packets_lock_); PR_Lock(packets_lock_); - packets_.push(new QueuedPacket()); - packets_.back()->Assign(data, len); + if (combinePackets_ && !packets_.empty()) { + QueuedPacket *packet = packets_.front(); + packets_.pop(); + + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " << packet->len() << " and " << len); + packets_.push(new QueuedPacket()); + packets_.back()->Assign(packet->data(), packet->len(), + data, len); + } else { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << len); + packets_.push(new QueuedPacket()); + packets_.back()->Assign(data, len); + } PRStatus r = PR_Unlock(packets_lock_); MOZ_ASSERT(r == PR_SUCCESS); diff --git a/media/mtransport/transportlayerloopback.h b/media/mtransport/transportlayerloopback.h index 59aac11c3a8..8ad5e28657f 100644 --- a/media/mtransport/transportlayerloopback.h +++ b/media/mtransport/transportlayerloopback.h @@ -36,7 +36,8 @@ class TransportLayerLoopback : public TransportLayer { timer_(nullptr), packets_(), packets_lock_(nullptr), - deliverer_(nullptr) {} + deliverer_(nullptr), + combinePackets_(false) {} ~TransportLayerLoopback() { while (!packets_.empty()) { @@ -67,6 +68,8 @@ class TransportLayerLoopback : public TransportLayer { } } + void CombinePackets(bool combine) { combinePackets_ = combine; } + // Overrides for TransportLayer virtual TransportResult SendPacket(const unsigned char *data, size_t len); @@ -93,6 +96,16 @@ class TransportLayerLoopback : public TransportLayer { len_ = len; } + void Assign(const unsigned char *data1, size_t len1, + const unsigned char *data2, size_t len2) { + data_ = new unsigned char[len1 + len2]; + memcpy(static_cast(data_), + static_cast(data1), len1); + memcpy(static_cast(data_ + len1), + static_cast(data2), len2); + len_ = len1 + len2; + } + const unsigned char *data() const { return data_; } size_t len() const { return len_; } @@ -133,6 +146,7 @@ class TransportLayerLoopback : public TransportLayer { std::queue packets_; PRLock *packets_lock_; RefPtr deliverer_; + bool combinePackets_; }; } // close namespace From 10fb43a543c217b3bd8d57cbf875231024326dba Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Wed, 16 Dec 2015 14:26:02 -0600 Subject: [PATCH 021/160] Bug 1231973 - Allow NAT simulator to be enabled with the pref system. r=drno --- media/mtransport/nr_socket_prsock.cpp | 4 ++ media/mtransport/nricectx.cpp | 68 ++++++++++++++++++- media/mtransport/nricectx.h | 20 ++---- media/mtransport/test/ice_unittest.cpp | 7 +- media/mtransport/test_nr_socket.cpp | 23 +++++++ media/mtransport/test_nr_socket.h | 7 ++ .../third_party/nICEr/src/ice/ice_socket.c | 4 +- 7 files changed, 111 insertions(+), 22 deletions(-) diff --git a/media/mtransport/nr_socket_prsock.cpp b/media/mtransport/nr_socket_prsock.cpp index 9166ba934b7..dfeda56ceda 100644 --- a/media/mtransport/nr_socket_prsock.cpp +++ b/media/mtransport/nr_socket_prsock.cpp @@ -89,6 +89,7 @@ nrappkit copyright: #include #include #include +#include #include "nspr.h" #include "prerror.h" @@ -110,6 +111,8 @@ nrappkit copyright: #include "nsTArray.h" #include "mozilla/dom/TCPSocketBinding.h" #include "nsITCPSocketCallback.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" #if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API) // csi_platform.h deep in nrappkit defines LOG_INFO and LOG_WARNING @@ -164,6 +167,7 @@ extern "C" { } #include "nr_socket_prsock.h" #include "simpletokenbucket.h" +#include "test_nr_socket.h" // Implement the nsISupports ref counting namespace mozilla { diff --git a/media/mtransport/nricectx.cpp b/media/mtransport/nricectx.cpp index b8804779792..781865b64ab 100644 --- a/media/mtransport/nricectx.cpp +++ b/media/mtransport/nricectx.cpp @@ -93,6 +93,7 @@ extern "C" { #include "nr_socket_prsock.h" #include "nrinterfaceprioritizer.h" #include "rlogringbuffer.h" +#include "test_nr_socket.h" namespace mozilla { @@ -268,6 +269,25 @@ nsresult NrIceTurnServer::ToNicerTurnStruct(nr_ice_turn_server *server) const { return NS_OK; } +NrIceCtx::NrIceCtx(const std::string& name, + bool offerer, + Policy policy) + : connection_state_(ICE_CTX_INIT), + gathering_state_(ICE_CTX_GATHER_INIT), + name_(name), + offerer_(offerer), + streams_(), + ctx_(nullptr), + peer_(nullptr), + ice_handler_vtbl_(nullptr), + ice_handler_(nullptr), + trickle_(true), + policy_(policy), + nat_ (nullptr) { + // XXX: offerer_ will be used eventually; placate clang in the meantime. + (void)offerer_; +} + // Handler callbacks int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream, int component_id, nr_ice_cand_pair **potentials, @@ -498,6 +518,42 @@ RefPtr NrIceCtx::Create(const std::string& name, } } + char* mapping_type = nullptr; + char* filtering_type = nullptr; + bool block_udp = false; + + nsresult rv; + nsCOMPtr pref_service = + do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv)) { + nsCOMPtr pref_branch; + rv = pref_service->GetBranch(nullptr, getter_AddRefs(pref_branch)); + if (NS_SUCCEEDED(rv)) { + rv = pref_branch->GetCharPref( + "media.peerconnection.nat_simulator.mapping_type", + &mapping_type); + rv = pref_branch->GetCharPref( + "media.peerconnection.nat_simulator.filtering_type", + &filtering_type); + rv = pref_branch->GetBoolPref( + "media.peerconnection.nat_simulator.block_udp", + &block_udp); + } + } + + MOZ_MTLOG(ML_DEBUG, "NAT filtering type: " << filtering_type); + MOZ_MTLOG(ML_DEBUG, "NAT mapping type: " << mapping_type); + + if (mapping_type && filtering_type) { + TestNat* test_nat = new TestNat; + test_nat->filtering_type_ = TestNat::ToNatBehavior(filtering_type); + test_nat->mapping_type_ = TestNat::ToNatBehavior(mapping_type); + test_nat->block_udp_ = block_udp; + test_nat->enabled_ = true; + ctx->SetNat(test_nat); + } + // Create the handler objects ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl(); ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair; @@ -522,7 +578,6 @@ RefPtr NrIceCtx::Create(const std::string& name, return nullptr; } - nsresult rv; ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); if (!NS_SUCCEEDED(rv)) @@ -531,6 +586,17 @@ RefPtr NrIceCtx::Create(const std::string& name, return ctx; } +int NrIceCtx::SetNat(const RefPtr& aNat) { + nat_ = aNat; + nr_socket_factory *fac; + int r = nat_->create_socket_factory(&fac); + if (r) { + return r; + } + nr_ice_ctx_set_socket_factory(ctx_, fac); + return 0; +} + // ONLY USE THIS FOR TESTING. Will cause totally unpredictable and possibly very // bad effects if ICE is still live. void NrIceCtx::internal_DeinitializeGlobal() { diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h index 081bc104e2e..bdf91721419 100644 --- a/media/mtransport/nricectx.h +++ b/media/mtransport/nricectx.h @@ -191,6 +191,7 @@ class NrIceProxyServer { std::string alpn_; }; +class TestNat; class NrIceCtx { public: @@ -223,6 +224,8 @@ class NrIceCtx { bool hide_non_default = false, Policy policy = ICE_POLICY_ALL); + int SetNat(const RefPtr& aNat); + // Deinitialize all ICE global state. Used only for testing. static void internal_DeinitializeGlobal(); @@ -332,21 +335,7 @@ class NrIceCtx { private: NrIceCtx(const std::string& name, bool offerer, - Policy policy) - : connection_state_(ICE_CTX_INIT), - gathering_state_(ICE_CTX_GATHER_INIT), - name_(name), - offerer_(offerer), - streams_(), - ctx_(nullptr), - peer_(nullptr), - ice_handler_vtbl_(nullptr), - ice_handler_(nullptr), - trickle_(true), - policy_(policy) { - // XXX: offerer_ will be used eventually; placate clang in the meantime. - (void)offerer_; - } + Policy policy); virtual ~NrIceCtx(); @@ -390,6 +379,7 @@ class NrIceCtx { bool trickle_; nsCOMPtr sts_target_; // The thread to run on Policy policy_; + RefPtr nat_; }; diff --git a/media/mtransport/test/ice_unittest.cpp b/media/mtransport/test/ice_unittest.cpp index c3891ee4109..1c3adb7ba36 100644 --- a/media/mtransport/test/ice_unittest.cpp +++ b/media/mtransport/test/ice_unittest.cpp @@ -316,12 +316,9 @@ class IceTestPeer : public sigslot::has_slots<> { this, &IceTestPeer::ConnectionStateChange); - nr_socket_factory *fac; - int r = nat_->create_socket_factory(&fac); + int r = ice_ctx_->SetNat(nat_); + (void)r; MOZ_ASSERT(!r); - if (!r) { - nr_ice_ctx_set_socket_factory(ice_ctx_->ctx(), fac); - } } ~IceTestPeer() { diff --git a/media/mtransport/test_nr_socket.cpp b/media/mtransport/test_nr_socket.cpp index e7bf83a437c..2363bc9b0a9 100644 --- a/media/mtransport/test_nr_socket.cpp +++ b/media/mtransport/test_nr_socket.cpp @@ -137,6 +137,21 @@ static nr_socket_factory_vtbl test_nat_socket_factory_vtbl = { test_nat_socket_factory_destroy }; +/* static */ +TestNat::NatBehavior +TestNat::ToNatBehavior(const std::string& type) { + if (!type.compare("ENDPOINT_INDEPENDENT")) { + return TestNat::ENDPOINT_INDEPENDENT; + } else if (!type.compare("ADDRESS_DEPENDENT")) { + return TestNat::ADDRESS_DEPENDENT; + } else if (!type.compare("PORT_DEPENDENT")) { + return TestNat::PORT_DEPENDENT; + } + + MOZ_ASSERT(false, "Invalid NAT behavior"); + return TestNat::ENDPOINT_INDEPENDENT; +} + bool TestNat::has_port_mappings() const { for (TestNrSocket *sock : sockets_) { if (sock->has_port_mappings()) { @@ -512,6 +527,10 @@ int TestNrSocket::async_wait(int how, NR_async_cb cb, void *cb_arg, } if (r) { + r_log(LOG_GENERIC, LOG_ERR, "TestNrSocket %s failed to async_wait for " + "internal socket: %d\n", + internal_socket_->my_addr().as_string, + r); return r; } @@ -541,6 +560,10 @@ int TestNrSocket::async_wait(int how, NR_async_cb cb, void *cb_arg, function, line); if (r) { + r_log(LOG_GENERIC, LOG_ERR, "TestNrSocket %s failed to async_wait for " + "port mapping: %d\n", + internal_socket_->my_addr().as_string, + r); return r; } } diff --git a/media/mtransport/test_nr_socket.h b/media/mtransport/test_nr_socket.h index cf34cd57c92..c975812b707 100644 --- a/media/mtransport/test_nr_socket.h +++ b/media/mtransport/test_nr_socket.h @@ -83,6 +83,10 @@ nrappkit copyright: #ifndef test_nr_socket__ #define test_nr_socket__ +extern "C" { +#include "transport_addr.h" +} + #include "nr_socket_prsock.h" extern "C" { @@ -93,6 +97,7 @@ extern "C" { #include #include #include +#include #include "mozilla/UniquePtr.h" #include "prinrval.h" @@ -152,6 +157,8 @@ class TestNat { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestNat); + static NatBehavior ToNatBehavior(const std::string& type); + bool enabled_; TestNat::NatBehavior filtering_type_; TestNat::NatBehavior mapping_type_; diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c index 3f205be8373..f693d253fa9 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c @@ -61,8 +61,10 @@ static void nr_ice_socket_readable_cb(NR_SOCKET s, int how, void *cb_arg) r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Socket ready to read",sock->ctx->label); /* Re-arm first! */ - if (sock->type != NR_ICE_SOCKET_TYPE_STREAM_TCP) + if (sock->type != NR_ICE_SOCKET_TYPE_STREAM_TCP) { + r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): rearming",sock->ctx->label); NR_ASYNC_WAIT(s,how,nr_ice_socket_readable_cb,cb_arg); + } if(r=nr_socket_recvfrom(sock->sock,buf,sizeof(buf),&len_s,0,&addr)){ if (r != R_WOULDBLOCK && (sock->type != NR_ICE_SOCKET_TYPE_DGRAM)) { From 2cf25d9dd1a2b9c64c965261e135ecb931e22814 Mon Sep 17 00:00:00 2001 From: dimi Date: Wed, 3 Feb 2016 14:37:55 +0800 Subject: [PATCH 022/160] Bug 1241929 - remove PurgeActiveWorker() from install job when skip waiting is set. r=bkelly --- dom/workers/ServiceWorkerManager.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp index 7f4af258525..2a0d81ae540 100644 --- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -1242,11 +1242,6 @@ public: swm->InvalidateServiceWorkerRegistrationWorker(mRegistration, WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER); - // "If registration's waiting worker's skip waiting flag is set" - if (mRegistration->mWaitingWorker->SkipWaitingFlag()) { - mRegistration->PurgeActiveWorker(); - } - Done(NS_OK); // Activate() is invoked out of band of atomic. mRegistration->TryToActivate(); From d44c72edc28f57a832aea5a23bdf2cd9dc711b73 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 1 Feb 2016 14:17:24 +0100 Subject: [PATCH 023/160] Bug 1243810: Remove storage class of SimdOperation; r=jolesen --- js/src/builtin/SIMD.cpp | 2 ++ js/src/builtin/SIMD.h | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/js/src/builtin/SIMD.cpp b/js/src/builtin/SIMD.cpp index 9ba70fd5865..9413dba3cc6 100644 --- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -213,6 +213,8 @@ static const JSFunctionSpec SimdTypedObjectMethods[] = { namespace js { namespace jit { +static_assert(uint64_t(SimdOperation::Last) <= UINT16_MAX, "SimdOperation must fit in uint16_t"); + // See also JitInfo_* in MCallOptimize.cpp. We provide a JSJitInfo for all the // named functions here. The default JitInfo_SimdInt32x4 etc structs represent the // SimdOperation::Constructor. diff --git a/js/src/builtin/SIMD.h b/js/src/builtin/SIMD.h index 6ea4d065215..85ce1bf84db 100644 --- a/js/src/builtin/SIMD.h +++ b/js/src/builtin/SIMD.h @@ -878,7 +878,11 @@ GetBooleanSimdType(SimdType t) // // C++ defines keywords and/or/xor/not, so prepend Fn_ to all named functions to // avoid clashes. -enum class SimdOperation : uint8_t { +// +// Note: because of a gcc < v4.8's compiler bug, uint8_t can't be used as the +// storage class here. See bug 1243810. See also +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64037 . +enum class SimdOperation { // The constructor call. No Fn_ prefix here. Constructor, @@ -901,6 +905,8 @@ enum class SimdOperation : uint8_t { Fn_fromUint32x4Bits, Fn_fromFloat32x4Bits, Fn_fromFloat64x2Bits, + + Last = Fn_fromFloat64x2Bits }; class SimdObject : public JSObject From 62f41e7f7ed1cd7da08eeee78cfb45cc34d3944c Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Mon, 25 Jan 2016 21:14:58 -0500 Subject: [PATCH 024/160] Bug 1242794 - make SkGrPixelRef::deepCopy preserve alpha type. r=jmuizelaar --- gfx/skia/skia/src/gpu/SkGrPixelRef.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp b/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp index 6e014feded1..ad4f33f7d9e 100644 --- a/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp +++ b/gfx/skia/skia/src/gpu/SkGrPixelRef.cpp @@ -51,7 +51,8 @@ bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const { /////////////////////////////////////////////////////////////////////////////// static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorType dstCT, - SkColorProfileType dstPT, const SkIRect* subset) { + SkAlphaType dstAT, SkColorProfileType dstPT, + const SkIRect* subset) { if (nullptr == texture || kUnknown_SkColorType == dstCT) { return nullptr; } @@ -75,7 +76,7 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp srcRect = *subset; } desc.fFlags = kRenderTarget_GrSurfaceFlag; - desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT); + desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, dstAT, dstPT); GrTexture* dst = context->textureProvider()->createTexture(desc, false, nullptr, 0); if (nullptr == dst) { @@ -88,8 +89,7 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp context->copySurface(dst->asRenderTarget(), texture, srcRect, SkIPoint::Make(0,0), GrContext::kFlushWrites_PixelOp); - SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, kPremul_SkAlphaType, - dstPT); + SkImageInfo info = SkImageInfo::Make(desc.fWidth, desc.fHeight, dstCT, dstAT, dstPT); SkGrPixelRef* pixelRef = new SkGrPixelRef(info, dst); SkSafeUnref(dst); return pixelRef; @@ -142,7 +142,8 @@ SkPixelRef* SkGrPixelRef::deepCopy(SkColorType dstCT, SkColorProfileType dstPT, // a GrTexture owned elsewhere (e.g., SkGpuDevice), and cannot live // independently of that texture. Texture-backed pixel refs, on the other // hand, own their GrTextures, and are thus self-contained. - return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, dstPT, subset); + return copy_to_new_texture_pixelref(fSurface->asTexture(), dstCT, this->info().alphaType(), + dstPT, subset); } static bool tryAllocBitmapPixels(SkBitmap* bitmap) { From 739be3ec56c244db11b81fa2c780a5127b987aae Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Mon, 1 Feb 2016 12:46:10 -0800 Subject: [PATCH 025/160] Bug 1242731 - Convert callsites to use channel.async0pen2() within browser/extensions/shumway. r=yury --- .../shumway/content/ShumwayStreamConverter.jsm | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm index f0627d61179..53c6d99f411 100644 --- a/browser/extensions/shumway/content/ShumwayStreamConverter.jsm +++ b/browser/extensions/shumway/content/ShumwayStreamConverter.jsm @@ -32,6 +32,7 @@ const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}'; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); +Cu.import('resource://gre/modules/NetUtil.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils', 'resource://gre/modules/PrivateBrowsingUtils.jsm'); @@ -304,17 +305,10 @@ ShumwayStreamConverterBase.prototype = { // Create a new channel that loads the viewer as a chrome resource. var viewerUrl = 'chrome://shumway/content/viewer.wrapper.html'; - // TODO use only newChannel2 after FF37 is released. - var channel = Services.io.newChannel2 ? - Services.io.newChannel2(viewerUrl, - null, - null, - null, // aLoadingNode - Services.scriptSecurityManager.getSystemPrincipal(), - null, // aTriggeringPrincipal - Ci.nsILoadInfo.SEC_NORMAL, - Ci.nsIContentPolicy.TYPE_OTHER) : - Services.io.newChannel(viewerUrl, null, null); + var channel = NetUtil.newChannel({ + uri: viewerUrl, + loadUsingSystemPrincipal: true + }); var converter = this; var listener = this.listener; @@ -370,7 +364,7 @@ ShumwayStreamConverterBase.prototype = { .getService(Ci.nsIScriptSecurityManager); var resourcePrincipal = securityManager.getSystemPrincipal(); aRequest.owner = resourcePrincipal; - channel.asyncOpen(proxy, aContext); + channel.asyncOpen2(proxy); }, // nsIRequestObserver::onStopRequest From 9787a458604e0695682b7f135a75f4fc7515c94f Mon Sep 17 00:00:00 2001 From: Cykesiopka Date: Wed, 3 Feb 2016 01:51:00 +0100 Subject: [PATCH 026/160] Bug 1243180 - Enable eslint "no-trailing-spaces" rule for PSM. r=keeler Also does some minor cleanup. --- security/manager/.eslintrc | 3 + .../pki/resources/content/certManager.js | 64 +++++++---------- .../pki/resources/content/certpicker.js | 27 ++++---- .../pki/resources/content/clientauthask.js | 5 +- .../pki/resources/content/createCertInfo.js | 9 +-- .../pki/resources/content/deletecert.js | 6 +- .../pki/resources/content/device_manager.js | 32 ++++----- .../pki/resources/content/downloadcert.js | 6 +- .../pki/resources/content/exceptionDialog.js | 69 ++++++++++--------- .../manager/pki/resources/content/password.js | 26 +++---- .../manager/pki/resources/content/pippki.js | 6 +- .../pki/resources/content/protectedAuth.js | 51 +++++++------- .../pki/resources/content/resetpassword.js | 4 +- .../mixedcontent/bug383369step2.html | 8 +-- .../mixedcontent/test_bug329869.html | 3 +- .../mixedcontent/test_bug383369.html | 20 +++--- .../test_dynUnsecureBackground.html | 3 +- .../test_dynUnsecureIframeRedirect.html | 2 +- .../test_innerHtmlDelayedUnsecurePicture.html | 10 ++- .../test_innerHtmlUnsecurePicture.html | 4 +- .../test_stricttransportsecurity.html | 6 +- .../ssl/tests/unit/test_hash_algorithms.js | 29 ++------ .../ssl/tests/unit/test_signed_apps.js | 12 ++-- 23 files changed, 182 insertions(+), 223 deletions(-) diff --git a/security/manager/.eslintrc b/security/manager/.eslintrc index fdb997bcaa6..fcde4fe4c50 100644 --- a/security/manager/.eslintrc +++ b/security/manager/.eslintrc @@ -87,6 +87,9 @@ // No spaces between function name and parentheses "no-spaced-func": 2, + // No trailing whitespace + "no-trailing-spaces": 2, + // Error on newline where a semicolon is needed "no-unexpected-multiline": 2, diff --git a/security/manager/pki/resources/content/certManager.js b/security/manager/pki/resources/content/certManager.js index 0011be8083f..85a0491e5cb 100644 --- a/security/manager/pki/resources/content/certManager.js +++ b/security/manager/pki/resources/content/certManager.js @@ -301,8 +301,8 @@ function backupCerts() fp.appendFilters(nsIFilePicker.filterAll); var rv = fp.show(); if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { - certdb.exportPKCS12File(null, fp.file, - selected_certs.length, selected_certs); + certdb.exportPKCS12File(null, fp.file, selected_certs.length, + selected_certs); } } @@ -404,52 +404,35 @@ function deleteCerts() var selTab = document.getElementById('certMgrTabbox').selectedItem; var selTabID = selTab.getAttribute('id'); - var t; - params.SetNumberStrings(numcerts+1); + params.SetNumberStrings(numcerts + 1); - if (selTabID == 'mine_tab') - { - params.SetString(0, selTabID); - } - else if (selTabID == "websites_tab") - { - params.SetString(0, selTabID); - } - else if (selTabID == "ca_tab") - { - params.SetString(0, selTabID); - } - else if (selTabID == "others_tab") - { - params.SetString(0, selTabID); - } - else if (selTabID == "orphan_tab") - { - params.SetString(0, selTabID); - } - else - { - return; + switch (selTabID) { + case "mine_tab": + case "websites_tab": + case "ca_tab": + case "others_tab": + case "orphan_tab": + params.SetString(0, selTabID); + break; + default: + return; } - params.SetInt(0,numcerts); - for (t=0; t=0; t--) - { + for (let t = numcerts - 1; t >= 0; t--) { treeView.deleteEntryObject(selected_index[t]); } diff --git a/security/manager/pki/resources/content/certpicker.js b/security/manager/pki/resources/content/certpicker.js index 596449d6636..dac338d1a99 100644 --- a/security/manager/pki/resources/content/certpicker.js +++ b/security/manager/pki/resources/content/certpicker.js @@ -16,22 +16,23 @@ function onLoad() itemCount = dialogParams.GetInt(0); var selIndex = dialogParams.GetInt(1); - if (selIndex < 0) + if (selIndex < 0) { selIndex = 0; - - for (var i=0; i < itemCount; i++) { - var menuItemNode = document.createElement("menuitem"); - var nick = dialogParams.GetString(i); - menuItemNode.setAttribute("value", i); - menuItemNode.setAttribute("label", nick); // this is displayed - selectElement.firstChild.appendChild(menuItemNode); - - if (selIndex == i) { - selectElement.selectedItem = menuItemNode; - } } - dialogParams.SetInt(0,0); // set cancel return value + for (let i = 0; i < itemCount; i++) { + let menuItemNode = document.createElement("menuitem"); + let nick = dialogParams.GetString(i); + menuItemNode.setAttribute("value", i); + menuItemNode.setAttribute("label", nick); // This is displayed. + selectElement.firstChild.appendChild(menuItemNode); + + if (selIndex == i) { + selectElement.selectedItem = menuItemNode; + } + } + + dialogParams.SetInt(0, 0); // Set cancel return value. setDetails(); } diff --git a/security/manager/pki/resources/content/clientauthask.js b/security/manager/pki/resources/content/clientauthask.js index 7bb73f70a43..2c5ca6d1fa0 100644 --- a/security/manager/pki/resources/content/clientauthask.js +++ b/security/manager/pki/resources/content/clientauthask.js @@ -32,10 +32,9 @@ function onLoad() if (pref) { pref = pref.getBranch(null); try { - rememberSetting = + rememberSetting = pref.getBoolPref("security.remember_cert_checkbox_default_setting"); - } - catch(e) { + } catch (e) { // pref is missing } } diff --git a/security/manager/pki/resources/content/createCertInfo.js b/security/manager/pki/resources/content/createCertInfo.js index 99fd60be0d8..e0baa47372a 100644 --- a/security/manager/pki/resources/content/createCertInfo.js +++ b/security/manager/pki/resources/content/createCertInfo.js @@ -9,21 +9,22 @@ var keygenThread; function onLoad() { keygenThread = window.arguments[0].QueryInterface(Components.interfaces.nsIKeygenThread); - + if (!keygenThread) { window.close(); return; } - + setCursor("wait"); var obs = { observe : function keygenListenerObserve(subject, topic, data) { - if (topic == "keygen-finished") + if (topic == "keygen-finished") { window.close(); + } } }; - + keygenThread.startKeyGeneration(obs); } diff --git a/security/manager/pki/resources/content/deletecert.js b/security/manager/pki/resources/content/deletecert.js index 4a94ef52ec6..12c75ee380f 100644 --- a/security/manager/pki/resources/content/deletecert.js +++ b/security/manager/pki/resources/content/deletecert.js @@ -13,15 +13,15 @@ var gParams; function setWindowName() { gParams = window.arguments[0].QueryInterface(nsIDialogParamBlock); - + var typeFlag = gParams.GetString(0); var numberOfCerts = gParams.GetInt(0); - + var bundle = document.getElementById("pippki_bundle"); var title; var confirm; var impact; - + if(typeFlag == "mine_tab") { title = bundle.getString("deleteUserCertTitle"); diff --git a/security/manager/pki/resources/content/device_manager.js b/security/manager/pki/resources/content/device_manager.js index 689a956d48c..b5e39acfa6e 100644 --- a/security/manager/pki/resources/content/device_manager.js +++ b/security/manager/pki/resources/content/device_manager.js @@ -258,11 +258,12 @@ function ClearDeviceList() tree.view.selection.clearSelection(); skip_enable_buttons = false; - // Remove the existing listed modules so that refresh doesn't - // display the module that just changed. - var device_list = document.getElementById("device_list"); - while (device_list.hasChildNodes()) - device_list.removeChild(device_list.firstChild); + // Remove the existing listed modules so that a refresh doesn't display the + // module that just changed. + let deviceList = document.getElementById("device_list"); + while (deviceList.hasChildNodes()) { + deviceList.removeChild(deviceList.firstChild); + } } @@ -356,7 +357,7 @@ function doLogin() selected_token.login(false); var tok_status = document.getElementById("tok_status"); if (selected_token.isLoggedIn()) { - tok_status.setAttribute("label", + tok_status.setAttribute("label", bundle.getString("devinfo_stat_loggedin")); } else { tok_status.setAttribute("label", @@ -378,7 +379,7 @@ function doLogout() selected_token.logoutAndDropAuthenticatedResources(); var tok_status = document.getElementById("tok_status"); if (selected_token.isLoggedIn()) { - tok_status.setAttribute("label", + tok_status.setAttribute("label", bundle.getString("devinfo_stat_loggedin")); } else { tok_status.setAttribute("label", @@ -392,8 +393,7 @@ function doLogout() // load a new device function doLoad() { - window.open("load_device.xul", "loaddevice", - "chrome,centerscreen,modal"); + window.open("load_device.xul", "loaddevice", "chrome,centerscreen,modal"); ClearDeviceList(); RefreshDeviceList(); } @@ -439,11 +439,11 @@ function onSmartCardChange() function changePassword() { getSelectedItem(); - var params = Components.classes[nsDialogParamBlock].createInstance(nsIDialogParamBlock); - params.SetString(1,selected_slot.tokenName); - window.openDialog("changepassword.xul", - "", - "chrome,centerscreen,modal", params); + let params = Components.classes[nsDialogParamBlock] + .createInstance(nsIDialogParamBlock); + params.SetString(1, selected_slot.tokenName); + window.openDialog("changepassword.xul", "", "chrome,centerscreen,modal", + params); showSlotInfo(); enableButtons(); } @@ -526,8 +526,8 @@ function toggleFIPS() return; } - //Remove the existing listed modules so that re-fresh doesn't - //display the module that just changed. + // Remove the existing listed modules so that a refresh doesn't display the + // module that just changed. ClearDeviceList(); RefreshDeviceList(); diff --git a/security/manager/pki/resources/content/downloadcert.js b/security/manager/pki/resources/content/downloadcert.js index 8f486196536..a6a7eabe5bb 100644 --- a/security/manager/pki/resources/content/downloadcert.js +++ b/security/manager/pki/resources/content/downloadcert.js @@ -14,12 +14,12 @@ function onLoad() params = window.arguments[0].QueryInterface(nsIDialogParamBlock); cert = params.objects.queryElementAt(0, nsIX509Cert); - caName = cert.commonName; - var bundle = document.getElementById("pippki_bundle"); - if (!caName.length) + caName = cert.commonName; + if (caName.length == 0) { caName = bundle.getString("unnamedCA"); + } var message2 = bundle.getFormattedString("newCAMessage1", [caName]); setText("message2", message2); diff --git a/security/manager/pki/resources/content/exceptionDialog.js b/security/manager/pki/resources/content/exceptionDialog.js index 640791f898f..3e72e083174 100644 --- a/security/manager/pki/resources/content/exceptionDialog.js +++ b/security/manager/pki/resources/content/exceptionDialog.js @@ -28,7 +28,7 @@ badCertListener.prototype = { return this; throw Components.results.NS_ERROR_NO_INTERFACE; - }, + }, handle_test_result: function () { if (gSSLStatus) gCert = gSSLStatus.QueryInterface(Components.interfaces.nsISSLStatus).serverCert; @@ -54,14 +54,14 @@ function initExceptionDialog() { var brandName = gBundleBrand.getString("brandShortName"); setText("warningText", gPKIBundle.getFormattedString("addExceptionBrandedWarning2", [brandName])); gDialog.getButton("extra1").disabled = true; - + var args = window.arguments; if (args && args[0]) { if (args[0].location) { // We were pre-seeded with a location. document.getElementById("locationTextBox").value = args[0].location; document.getElementById('checkCertButton').disabled = false; - + if (args[0].sslStatus) { gSSLStatus = args[0].sslStatus; gCert = gSSLStatus.serverCert; @@ -77,13 +77,13 @@ function initExceptionDialog() { document.getElementById("checkCertButton").disabled = true; gChecking = true; updateCertStatus(); - + window.setTimeout(checkCert, 0); } } - + // Set out parameter to false by default - args[0].exceptionAdded = false; + args[0].exceptionAdded = false; } } @@ -92,7 +92,6 @@ function initExceptionDialog() { * the Certificate Status section with the result. */ function checkCert() { - gCert = null; gSSLStatus = null; gChecking = true; @@ -118,14 +117,15 @@ function checkCert() { } finally { gChecking = false; } - - if(req.channel && req.channel.securityInfo) { + + if (req.channel && req.channel.securityInfo) { const Ci = Components.interfaces; gSSLStatus = req.channel.securityInfo .QueryInterface(Ci.nsISSLStatusProvider).SSLStatus; gCert = gSSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert; } - updateCertStatus(); + + updateCertStatus(); } /** @@ -133,21 +133,25 @@ function checkCert() { * Certificate Location fields */ function getURI() { - // Use fixup service instead of just ioservice's newURI since it's quite likely - // that the host will be supplied without a protocol prefix, resulting in malformed - // uri exceptions being thrown. - var fus = Components.classes["@mozilla.org/docshell/urifixup;1"] + // Use fixup service instead of just ioservice's newURI since it's quite + // likely that the host will be supplied without a protocol prefix, resulting + // in malformed uri exceptions being thrown. + let fus = Components.classes["@mozilla.org/docshell/urifixup;1"] .getService(Components.interfaces.nsIURIFixup); - var uri = fus.createFixupURI(document.getElementById("locationTextBox").value, 0); - - if(!uri) + let locationTextBox = document.getElementById("locationTextBox"); + let uri = fus.createFixupURI(locationTextBox.value, 0); + + if (!uri) { return null; + } - if(uri.scheme == "http") + if (uri.scheme == "http") { uri.scheme = "https"; + } - if (uri.port == -1) + if (uri.port == -1) { uri.port = 443; + } return uri; } @@ -184,8 +188,8 @@ function updateCertStatus() { var use2 = false; var use3 = false; let bucketId = gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_BASE; - if(gCert) { - if(gBroken) { + if (gCert) { + if (gBroken) { var mms = "addExceptionDomainMismatchShort"; var mml = "addExceptionDomainMismatchLong2"; var exs = "addExceptionExpiredShort"; @@ -218,13 +222,11 @@ function updateCertStatus() { use1 = true; shortDesc = uts; longDesc = utl; - } - else if (!use2) { + } else if (!use2) { use2 = true; shortDesc2 = uts; longDesc2 = utl; - } - else { + } else { use3 = true; shortDesc3 = uts; longDesc3 = utl; @@ -281,7 +283,7 @@ function updateCertStatus() { gDialog.getButton("extra1").disabled = true; document.getElementById("permanent").disabled = true; } - + setText("statusDescription", gPKIBundle.getString(shortDesc)); setText("statusLongDescription", gPKIBundle.getString(longDesc)); @@ -303,9 +305,9 @@ function updateCertStatus() { */ function viewCertButtonClick() { gSecHistogram.add(gNsISecTel.WARNING_BAD_CERT_TOP_CLICK_VIEW_CERT); - if (gCert) + if (gCert) { viewCertHelper(this, gCert); - + } } /** @@ -331,7 +333,7 @@ function addException() { flags |= overrideService.ERROR_TIME; confirmBucketId += gNsISecTel.WARNING_BAD_CERT_TOP_CONFIRM_ADD_EXCEPTION_FLAG_TIME; } - + var permanentCheckbox = document.getElementById("permanent"); var shouldStorePermanently = permanentCheckbox.checked && !inPrivateBrowsingMode(); if(!permanentCheckbox.checked) @@ -344,11 +346,12 @@ function addException() { gCert, flags, !shouldStorePermanently); - - var args = window.arguments; - if (args && args[0]) + + let args = window.arguments; + if (args && args[0]) { args[0].exceptionAdded = true; - + } + gDialog.acceptDialog(); } diff --git a/security/manager/pki/resources/content/password.js b/security/manager/pki/resources/content/password.js index f1c3683725d..2f602c2c944 100644 --- a/security/manager/pki/resources/content/password.js +++ b/security/manager/pki/resources/content/password.js @@ -35,11 +35,10 @@ function onLoad() // previously trying to assign unicode to the window's name. // I checked all the places where we get a password prompt and // all of them pass an argument as part of this patch. - tokenName=""; + tokenName = ""; } - - if(tokenName=="") { + if (tokenName == "") { var sectokdb = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB); var tokenList = sectokdb.listTokens(); var enumElement; @@ -97,7 +96,7 @@ function process() var status = slot.status; if (status == nsIPKCS11Slot.SLOT_UNINITIALIZED || status == nsIPKCS11Slot.SLOT_READY) { - + oldpwbox.setAttribute("hidden", "true"); msgBox.setAttribute("value", bundle.getString("password_not_set")); msgBox.setAttribute("hidden", "false"); @@ -107,10 +106,9 @@ function process() } else { oldpwbox.setAttribute("inited", "true"); } - + // Select first password field document.getElementById('pw1').focus(); - } else { // Select old password field oldpwbox.setAttribute("hidden", "false"); @@ -124,7 +122,7 @@ function process() // Return value 0 means "canceled" params.SetInt(1, 0); } - + checkPasswords(); } @@ -147,23 +145,22 @@ function setPassword() var bundle = document.getElementById("pippki_bundle"); var success = false; - + if (initpw == "false" || initpw == "empty") { try { var oldpw = ""; var passok = 0; - + if (initpw == "empty") { passok = 1; } else { oldpw = oldpwbox.value; passok = token.checkPassword(oldpw); } - + if (passok) { if (initpw == "empty" && pw1.value == "") { - // This makes no sense that we arrive here, - // we reached a case that should have been prevented by checkPasswords. + // checkPasswords() should have prevented this path from being reached. } else { if (pw1.value == "") { var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB); @@ -196,9 +193,8 @@ function setPassword() } else { token.initPassword(pw1.value); if (pw1.value == "") { - doPrompt(bundle.getString("pw_not_wanted") - + " " - + bundle.getString("pw_empty_warning")); + doPrompt(bundle.getString("pw_not_wanted") + " " + + bundle.getString("pw_empty_warning")); } success = true; } diff --git a/security/manager/pki/resources/content/pippki.js b/security/manager/pki/resources/content/pippki.js index c2719fe1c7c..967e73fad8d 100644 --- a/security/manager/pki/resources/content/pippki.js +++ b/security/manager/pki/resources/content/pippki.js @@ -54,14 +54,14 @@ function getPKCS7String(cert, chainMode) function getPEMString(cert) { var derb64 = btoa(getDERString(cert)); - // Wrap the Base64 string into lines of 64 characters, - // with CRLF line breaks (as specified in RFC 1421). + // Wrap the Base64 string into lines of 64 characters with CRLF line breaks + // (as specified in RFC 1421). var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n"); return "-----BEGIN CERTIFICATE-----\r\n" + wrapped + "\r\n-----END CERTIFICATE-----\r\n"; } - + function alertPromptService(title, message) { var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. diff --git a/security/manager/pki/resources/content/protectedAuth.js b/security/manager/pki/resources/content/protectedAuth.js index 1b68220fbfa..a89a0d5d445 100644 --- a/security/manager/pki/resources/content/protectedAuth.js +++ b/security/manager/pki/resources/content/protectedAuth.js @@ -4,40 +4,37 @@ function onLoad() { - protectedAuthThread = window.arguments[0].QueryInterface(Components.interfaces.nsIProtectedAuthThread); + protectedAuthThread = + window.arguments[0].QueryInterface(Components.interfaces.nsIProtectedAuthThread); - if (!protectedAuthThread) - { - window.close(); - return; - } + if (!protectedAuthThread) { + window.close(); + return; + } - try - { - var tokenName = protectedAuthThread.getTokenName(); + try { + let tokenName = protectedAuthThread.getTokenName(); - var tag = document.getElementById("tokenName"); - tag.setAttribute("value",tokenName); + let tag = document.getElementById("tokenName"); + tag.setAttribute("value", tokenName); - setCursor("wait"); - - var obs = { - observe : function protectedAuthListenerObserve(subject, topic, data) { - if (topic == "operation-completed") - window.close(); - } - }; - - protectedAuthThread.login(obs); + setCursor("wait"); - } catch (exception) - { - window.close(); - return; - } + let obs = { + observe: function protectedAuthListenerObserve(subject, topic, data) { + if (topic == "operation-completed") { + window.close(); + } + } + }; + + protectedAuthThread.login(obs); + } catch (exception) { + window.close(); + } } function onClose() { - setCursor("default"); + setCursor("default"); } diff --git a/security/manager/pki/resources/content/resetpassword.js b/security/manager/pki/resources/content/resetpassword.js index 16aeb2431ef..f3840d4d79e 100644 --- a/security/manager/pki/resources/content/resetpassword.js +++ b/security/manager/pki/resources/content/resetpassword.js @@ -54,8 +54,8 @@ function resetPassword() promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService); if (promptService && bundle) { promptService.alert(window, - bundle.getString("resetPasswordConfirmationTitle"), - bundle.getString("resetPasswordConfirmationMessage")); + bundle.getString("resetPasswordConfirmationTitle"), + bundle.getString("resetPasswordConfirmationMessage")); } return true; diff --git a/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html b/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html index be8925e98f2..fcf7531ac45 100644 --- a/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html +++ b/security/manager/ssl/tests/mochitest/mixedcontent/bug383369step2.html @@ -8,11 +8,9 @@ diff --git a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html index 352ae52efc6..7060c20e470 100644 --- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html +++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureBackground.html @@ -20,8 +20,7 @@ document.body.background = "http://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/moonsurface.jpg"; - waitForSecurityState("broken", function() - { + waitForSecurityState("broken", function () { isSecurityState("broken", "document.body.background='http://...' changed to broken"); finish(); }); diff --git a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html index a9967228b4c..c8223a2cd52 100644 --- a/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html +++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_dynUnsecureIframeRedirect.html @@ -23,7 +23,7 @@ self.isSecurityState("broken", "src='redirect to unsecure' changed to broken"); self.finish(); } - + iframe.src = "https://example.com/tests/security/manager/ssl/tests/mochitest/mixedcontent/iframeunsecredirect.sjs"; } diff --git a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html index e226fd16be0..d0c53c44a55 100644 --- a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html +++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlDelayedUnsecurePicture.html @@ -15,15 +15,13 @@ function runTest() { isSecurityState("secure"); - - window.setTimeout(function() - { + + window.setTimeout(function () { document.getElementById("buddy").innerHTML = ""; }, 1); - waitForSecurityState("broken", function() - { + waitForSecurityState("broken", function () { isSecurityState("broken", "innerHTML loading insecure changed to broken"); finish(); }); @@ -33,7 +31,7 @@ { is(document.getElementById("buddy").innerHTML, "", "innerHTML back to previous"); isSecurityState("secure"); - finish(); + finish(); } diff --git a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html index 43e27d414be..4264981c2af 100644 --- a/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html +++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_innerHtmlUnsecurePicture.html @@ -15,7 +15,7 @@ function runTest() { isSecurityState("secure"); - + document.getElementById("buddy").innerHTML = ""; @@ -29,7 +29,7 @@ { is(document.getElementById("buddy").innerHTML, "", "innerHTML back to previous"); isSecurityState("secure"); - finish(); + finish(); } diff --git a/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_stricttransportsecurity.html b/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_stricttransportsecurity.html index 5905865685e..a6ff74ae4f8 100644 --- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_stricttransportsecurity.html +++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_stricttransportsecurity.html @@ -82,7 +82,7 @@ } // check if the result (SECURE/INSECURE) is expected for this round/test combo - SimpleTest.is(result[0], testframes[result[1]].expected[round], + SimpleTest.is(result[0], testframes[result[1]].expected[round], "in ROUND " + round + ", test " + result[1]); testsleft[round]--; @@ -95,8 +95,8 @@ // defer this so it doesn't muck with the stack too much. if (roundsLeft == 1) setTimeout(function () { - startRound('subdom'); - }, 0); + startRound("subdom"); + }, 0); } if (roundsLeft < 1) { diff --git a/security/manager/ssl/tests/unit/test_hash_algorithms.js b/security/manager/ssl/tests/unit/test_hash_algorithms.js index 79247846ee9..31ceac91ef0 100644 --- a/security/manager/ssl/tests/unit/test_hash_algorithms.js +++ b/security/manager/ssl/tests/unit/test_hash_algorithms.js @@ -30,7 +30,7 @@ var hashes = { sha384: [ "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1", "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" - ], + ], sha512: [ "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" @@ -38,28 +38,11 @@ var hashes = { }; function hexdigest(data) { - /* - * Coment taken from bug 383390: - * - * First, |data| is the final string value produced by the cryptohash. |for (i in - * data)| uses the Mozilla JS extension that iterating over a string iterates over - * its character indexes, so that's 0..length-1 over the hash string. - * - * Returning to the left, the |charCodeAt| gets the value of the character at that - * index in the string. - * - * |slice(-2)| is equivalent to |slice(length of this string - 2)| as a convenient - * way of wrapping around to the other end of a string without doing the actual - * calculation. When provided with only one argument, slice selects to the end of - * the string, so this chomps off the last two characters of the string. - * - * The last-two-characters part clarifies the |"0" +| -- if the Unicode value is - * <10, we have a single-character hex string when we want one that's two - * characters, and unconditionally prepending a "0" solves the problem. - * - * The array comprehension just creates an array whose elements are these - * two-character strings. - */ + // |slice(-2)| chomps off the last two characters of a string. + // + // Therefore, if the Unicode value is < 10, we have a single-character hex + // string when we want one that's two characters, and unconditionally + // prepending a "0" solves the problem. return Array.from(data, (c, i) => ("0" + data.charCodeAt(i).toString(16)).slice(-2)).join(""); } diff --git a/security/manager/ssl/tests/unit/test_signed_apps.js b/security/manager/ssl/tests/unit/test_signed_apps.js index 0eaf5fc6492..2b84a009ff7 100644 --- a/security/manager/ssl/tests/unit/test_signed_apps.js +++ b/security/manager/ssl/tests/unit/test_signed_apps.js @@ -5,18 +5,18 @@ PATH=$NSS/bin:$NSS/lib:$PATH ./generate.sh cd ../../../../../.. make -C $OBJDIR/security/manager/ssl/tests - - $NSS is the path to NSS binaries and libraries built for the host platform. + + $NSS is the path to NSS binaries and libraries built for the host platform. If you get error messages about "CertUtil" on Windows, then it means that the Windows CertUtil.exe is ahead of the NSS certutil.exe in $PATH. - + Check in the generated files. These steps are not done as part of the build because we do not want to add a build-time dependency on the OpenSSL or NSS tools or libraries built for the host platform. */ // XXX from prio.h -const PR_RDWR = 0x04; +const PR_RDWR = 0x04; const PR_CREATE_FILE = 0x08; const PR_TRUNCATE = 0x20; @@ -68,7 +68,7 @@ function tamper(inFilePath, outFilePath, modifications, newEntries) { } finally { reader.close(); } - + // Any leftover modification means that we were expecting to modify an entry // in the input file that wasn't there. for(var name in modifications) { @@ -76,7 +76,7 @@ function tamper(inFilePath, outFilePath, modifications, newEntries) { throw "input file was missing expected entries: " + name; } } - + // Now, append any new entries to the end newEntries.forEach(function(newEntry) { var sis = Cc["@mozilla.org/io/string-input-stream;1"] From 0a71a5327ad5feb860e738365c9872233f05db95 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Wed, 27 Jan 2016 01:17:08 -0800 Subject: [PATCH 027/160] Bug 1243647 - Fix -Wimplicit-fallthrough warnings by breaking at unintentional switch fallthroughs in AsmJS.cpp. r=bbouvier js/src/asmjs/AsmJS.cpp:2598:7: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough] js/src/asmjs/AsmJS.cpp:2601:7: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough] js/src/asmjs/AsmJS.cpp:2604:7: warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough] --- js/src/asmjs/AsmJS.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/asmjs/AsmJS.cpp b/js/src/asmjs/AsmJS.cpp index 02964e962e6..9c27c0ba6ee 100644 --- a/js/src/asmjs/AsmJS.cpp +++ b/js/src/asmjs/AsmJS.cpp @@ -2584,12 +2584,15 @@ SimdToExpr(SimdType type, SimdOperation op) switch (type) { case SimdType::Int32x4: { ENUMERATE(I32x4, FORALL_INT32X4_ASMJS_OP, I32CASE) + break; } case SimdType::Float32x4: { ENUMERATE(F32x4, FORALL_FLOAT32X4_ASMJS_OP, F32CASE) + break; } case SimdType::Bool32x4: { ENUMERATE(B32x4, FORALL_BOOL_SIMD_OP, B32CASE) + break; } default: break; } From aebaefad06514fe43ffd2b25ed32d67d9bd39854 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Mon, 1 Feb 2016 16:22:17 -0600 Subject: [PATCH 028/160] Bug 1244338 - Don't try to clean up |ctx| if null. r=drno --- media/mtransport/third_party/nICEr/src/ice/ice_ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c index e33049f509b..97211469f2d 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c @@ -418,7 +418,7 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp) _status=0; abort: - if(_status) + if(_status && ctx) nr_ice_ctx_destroy_cb(0,0,ctx); return(_status); From 90aae564540fa6574e9675bf1cac794cc9f3d02e Mon Sep 17 00:00:00 2001 From: Paul Bignier Date: Tue, 2 Feb 2016 06:41:00 +0100 Subject: [PATCH 029/160] Bug 1245099 - Fixed uninitialized variable warning. r=bsmedberg --- xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp index f4853bee136..b44fd21a821 100644 --- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp +++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp @@ -47,9 +47,9 @@ static void invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s, uint64_t * gpregs, double * fpregs) { - uint32_t nr_gpr = 1; // skip one GP register for 'that' - uint32_t nr_fpr = 0; - uint64_t value; + uint32_t nr_gpr = 1u; // skip one GP register for 'that' + uint32_t nr_fpr = 0u; + uint64_t value = 0u; for (uint32_t i = 0; i < paramCount; i++, s++) { if (s->IsPtrData()) From f071856bc247b22a5a72d696b8e6c91189d519b7 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 2 Feb 2016 15:27:50 +0100 Subject: [PATCH 030/160] Bug 1242835: Check for OOM in AnalyzeNewScriptDefiniteProperties; r=jonco --- js/src/jit/IonAnalysis.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 36ab64bde01..6fd562a0b81 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -3695,8 +3695,12 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun, &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr); if (!builder.build()) { - if (cx->isThrowingOverRecursed() || builder.abortReason() == AbortReason_Alloc) + if (cx->isThrowingOverRecursed() || + cx->isThrowingOutOfMemory() || + builder.abortReason() == AbortReason_Alloc) + { return false; + } MOZ_ASSERT(!cx->isExceptionPending()); return true; } From cfa8042bdf732f12fedf7e0e5e3d513af9fa2366 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:04:19 +0100 Subject: [PATCH 031/160] Backed out changeset b64710d45b28 (bug 1187464) --- gfx/layers/basic/BasicCompositor.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 8febcc215ad..7c3a992a356 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -176,11 +176,6 @@ DrawSurfaceWithTextureCoords(DrawTarget *aDest, SourceSurface *aMask, const Matrix* aMaskTransform) { - if (!aSource || !aMask) { - gfxWarning() << "DrawSurfaceWithTextureCoords problem " << gfx::hexa(aSource) << " and " << gfx::hexa(aMask); - return; - } - // Convert aTextureCoords into aSource's coordinate space gfxRect sourceRect(aTextureCoords.x * aSource->GetSize().width, aTextureCoords.y * aSource->GetSize().height, @@ -402,9 +397,6 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { EffectMask *effectMask = static_cast(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest); - if (!sourceMask) { - gfxWarning() << "Invalid sourceMask effect"; - } MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!"); MOZ_ASSERT(!effectMask->mIs3D); maskTransform = effectMask->mMaskTransform.As2D(); @@ -447,9 +439,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); } else if (source) { - SourceSurface* srcSurf = source->GetSurface(dest); - if (srcSurf) { - RefPtr srcData = srcSurf->GetDataSurface(); + RefPtr srcData = source->GetSurface(dest)->GetDataSurface(); // Yes, we re-create the premultiplied data every time. // This might be better with a cache, eventually. @@ -461,9 +451,8 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); - } } else { - gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name() << " and " << gfx::hexa(sourceMask); + gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name(); } break; From 258b852cedfd715dda898e577af180978d2dc972 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:04:21 +0100 Subject: [PATCH 032/160] Backed out changeset 0cee3cdcce99 (bug 1187464) --- gfx/layers/basic/BasicCompositor.cpp | 3 +-- gfx/layers/basic/BasicCompositor.h | 2 -- gfx/layers/basic/MacIOSurfaceTextureHostBasic.h | 2 -- gfx/layers/basic/X11BasicCompositor.h | 2 -- gfx/layers/basic/X11TextureSourceBasic.h | 2 -- gfx/layers/composite/TextureHost.cpp | 7 ------- gfx/layers/composite/TextureHost.h | 6 ------ gfx/layers/composite/X11TextureHost.h | 2 -- gfx/layers/d3d11/TextureD3D11.h | 3 --- gfx/layers/d3d9/TextureD3D9.h | 4 ---- gfx/layers/opengl/CompositingRenderTargetOGL.h | 2 -- gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h | 2 -- gfx/layers/opengl/TextureHostOGL.h | 7 ------- 13 files changed, 1 insertion(+), 43 deletions(-) diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 7c3a992a356..05b92a614ea 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -34,7 +34,6 @@ class DataTextureSourceBasic : public DataTextureSource , public TextureSourceBasic { public: - virtual const char* Name() const override { return "DataTextureSourceBasic"; } virtual TextureSourceBasic* AsSourceBasic() override { return this; } @@ -452,7 +451,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); } else { - gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic with " << texturedEffect->mTexture->Name(); + gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic"; } break; diff --git a/gfx/layers/basic/BasicCompositor.h b/gfx/layers/basic/BasicCompositor.h index dfc7d8491fc..05e64e2fcb1 100644 --- a/gfx/layers/basic/BasicCompositor.h +++ b/gfx/layers/basic/BasicCompositor.h @@ -23,8 +23,6 @@ public: , mSize(aRect.Size()) { } - virtual const char* Name() const override { return "BasicCompositingRenderTarget"; } - virtual gfx::IntSize GetSize() const override { return mSize; } void BindRenderTarget(); diff --git a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h index 3dd6afb468f..19a8a707805 100644 --- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h +++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h @@ -31,8 +31,6 @@ public: MacIOSurface* aSurface); virtual ~MacIOSurfaceTextureSourceBasic(); - virtual const char* Name() const override { return "MacIOSurfaceTextureSourceBasic"; } - virtual TextureSourceBasic* AsSourceBasic() override { return this; } virtual gfx::IntSize GetSize() const override; diff --git a/gfx/layers/basic/X11BasicCompositor.h b/gfx/layers/basic/X11BasicCompositor.h index 48d2f8e81cb..4e3cf037d8f 100644 --- a/gfx/layers/basic/X11BasicCompositor.h +++ b/gfx/layers/basic/X11BasicCompositor.h @@ -22,8 +22,6 @@ class X11DataTextureSourceBasic : public DataTextureSource public: X11DataTextureSourceBasic() {}; - virtual const char* Name() const override { return "X11DataTextureSourceBasic"; } - virtual bool Update(gfx::DataSourceSurface* aSurface, nsIntRegion* aDestRegion = nullptr, gfx::IntPoint* aSrcOffset = nullptr) override; diff --git a/gfx/layers/basic/X11TextureSourceBasic.h b/gfx/layers/basic/X11TextureSourceBasic.h index f813560e04e..92c9f6c63d0 100644 --- a/gfx/layers/basic/X11TextureSourceBasic.h +++ b/gfx/layers/basic/X11TextureSourceBasic.h @@ -24,8 +24,6 @@ class X11TextureSourceBasic public: X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXlibSurface* aSurface); - virtual const char* Name() const override { return "X11TextureSourceBasic"; } - virtual X11TextureSourceBasic* AsSourceBasic() override { return this; } virtual gfx::IntSize GetSize() const override; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 75aa85b30fa..dcf9278717c 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -374,13 +374,6 @@ TextureSource::~TextureSource() MOZ_COUNT_DTOR(TextureSource); } -const char* -TextureSource::Name() const -{ - MOZ_CRASH("TextureSource without class name"); - return "TextureSource"; -} - BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc, TextureFlags aFlags) : TextureHost(aFlags) diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 4c4a882246a..4de69a787ab 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -88,8 +88,6 @@ public: virtual ~TextureSource(); - virtual const char* Name() const = 0; - /** * Should be overridden in order to deallocate the data that is associated * with the rendering backend, such as GL textures. @@ -235,8 +233,6 @@ public: : mUpdateSerial(0) {} - virtual const char* Name() const override { return "DataTextureSource"; } - virtual DataTextureSource* AsDataTextureSource() override { return this; } /** @@ -728,8 +724,6 @@ public: {} virtual ~CompositingRenderTarget() {} - virtual const char* Name() const override { return "CompositingRenderTarget"; } - #ifdef MOZ_DUMP_PAINTING virtual already_AddRefed Dump(Compositor* aCompositor) { return nullptr; } #endif diff --git a/gfx/layers/composite/X11TextureHost.h b/gfx/layers/composite/X11TextureHost.h index 7c6cc7d72bb..4ac586f01b1 100644 --- a/gfx/layers/composite/X11TextureHost.h +++ b/gfx/layers/composite/X11TextureHost.h @@ -21,8 +21,6 @@ public: // Called when the underlying X surface has been changed. // Useful for determining whether to rebind a GLXPixmap to a texture. virtual void Updated() = 0; - - virtual const char* Name() const override { return "X11TextureSource"; } }; // TextureHost for Xlib-backed TextureSources. diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 1c91a3c06e4..f4bc9f69582 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -253,7 +253,6 @@ public: virtual ~DataTextureSourceD3D11(); - virtual const char* Name() const override { return "DataTextureSourceD3D11"; } // DataTextureSource @@ -409,8 +408,6 @@ public: const gfx::IntPoint& aOrigin, DXGI_FORMAT aFormatOverride = DXGI_FORMAT_UNKNOWN); - virtual const char* Name() const override { return "CompositingRenderTargetD3D11"; } - virtual TextureSourceD3D11* AsSourceD3D11() override { return this; } void BindRenderTarget(ID3D11DeviceContext* aContext); diff --git a/gfx/layers/d3d9/TextureD3D9.h b/gfx/layers/d3d9/TextureD3D9.h index 4e341463a1f..83a1b0b0a45 100644 --- a/gfx/layers/d3d9/TextureD3D9.h +++ b/gfx/layers/d3d9/TextureD3D9.h @@ -112,8 +112,6 @@ public: virtual ~DataTextureSourceD3D9(); - virtual const char* Name() const override { return "DataTextureSourceD3D9"; } - // DataTextureSource virtual bool Update(gfx::DataSourceSurface* aSurface, @@ -400,8 +398,6 @@ public: const gfx::IntRect& aRect); virtual ~CompositingRenderTargetD3D9(); - virtual const char* Name() const override { return "CompositingRenderTargetD3D9"; } - virtual TextureSourceD3D9* AsSourceD3D9() override { MOZ_ASSERT(mTexture, diff --git a/gfx/layers/opengl/CompositingRenderTargetOGL.h b/gfx/layers/opengl/CompositingRenderTargetOGL.h index cca94410a06..3b6b055c522 100644 --- a/gfx/layers/opengl/CompositingRenderTargetOGL.h +++ b/gfx/layers/opengl/CompositingRenderTargetOGL.h @@ -77,8 +77,6 @@ public: ~CompositingRenderTargetOGL(); - virtual const char* Name() const override { return "CompositingRenderTargetOGL"; } - /** * Create a render target around the default FBO, for rendering straight to * the window. diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index 48250e1a9df..f408244acc4 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -28,8 +28,6 @@ public: MacIOSurface* aSurface); virtual ~MacIOSurfaceTextureSourceOGL(); - virtual const char* Name() const override { return "MacIOSurfaceTextureSourceOGL"; } - virtual TextureSourceOGL* AsSourceOGL() override { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 5d6334a1fbe..efdc19a7ce3 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -142,7 +142,6 @@ public: , mIterating(false) {} - virtual const char* Name() const override { return "TextureImageTextureSourceOGL"; } // DataTextureSource virtual bool Update(gfx::DataSourceSurface* aSurface, @@ -238,8 +237,6 @@ public: ~GLTextureSource(); - virtual const char* Name() const override { return "GLTextureSource"; } - virtual GLTextureSource* AsGLTextureSource() override { return this; } virtual TextureSourceOGL* AsSourceOGL() override { return this; } @@ -347,8 +344,6 @@ public: GLenum aWrapMode, gfx::IntSize aSize); - virtual const char* Name() const override { return "SurfaceTextureSource"; } - virtual TextureSourceOGL* AsSourceOGL() { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; @@ -441,8 +436,6 @@ public: GLenum aWrapMode, gfx::IntSize aSize); - virtual const char* Name() const override { return "EGLImageTextureSource"; } - virtual TextureSourceOGL* AsSourceOGL() override { return this; } virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) override; From 614c7828e6d39c35a18ad16300820a43d1da97e5 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:04:37 +0100 Subject: [PATCH 033/160] Backed out changeset 63e2a056311a (bug 1187464) for reftest failures --- gfx/2d/Logging.h | 1 - gfx/layers/basic/BasicCompositor.cpp | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/gfx/2d/Logging.h b/gfx/2d/Logging.h index ad5c3c6892a..11c3390f46e 100644 --- a/gfx/2d/Logging.h +++ b/gfx/2d/Logging.h @@ -131,7 +131,6 @@ enum class LogReason : int { GlyphAllocFailedCG, InvalidRect, CannotDraw3D, // 20 - IncompatibleBasicTexturedEffect, // End MustBeLessThanThis = 101, }; diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 05b92a614ea..8191d7190d4 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -430,14 +430,14 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, static_cast(aEffectChain.mPrimaryEffect.get()); TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic(); - if (source && texturedEffect->mPremultiplied) { + if (texturedEffect->mPremultiplied) { DrawSurfaceWithTextureCoords(dest, aRect, source->GetSurface(dest), texturedEffect->mTextureCoords, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); - } else if (source) { + } else { RefPtr srcData = source->GetSurface(dest)->GetDataSurface(); // Yes, we re-create the premultiplied data every time. @@ -450,10 +450,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect, texturedEffect->mFilter, DrawOptions(aOpacity, blendMode), sourceMask, &maskTransform); - } else { - gfxDevCrash(LogReason::IncompatibleBasicTexturedEffect) << "Bad for basic"; } - break; } case EffectTypes::YCBCR: { From 9aaab24d3ad4c9199758889343f8ecd12fe3dfd5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 034/160] Bug 1194721: Add |Saturate| template for saturation arithmetics, r=nfroyd |Saturate| implements saturation arithmetics for arbitrary basic types. Operations on its value won't over- or underflow the type's range. --- mfbt/Saturate.h | 287 ++++++++++++++++++++++++++++++++++++ mfbt/moz.build | 1 + mfbt/tests/TestSaturate.cpp | 215 +++++++++++++++++++++++++++ mfbt/tests/moz.build | 1 + testing/cppunittest.ini | 1 + 5 files changed, 505 insertions(+) create mode 100644 mfbt/Saturate.h create mode 100644 mfbt/tests/TestSaturate.cpp diff --git a/mfbt/Saturate.h b/mfbt/Saturate.h new file mode 100644 index 00000000000..5d3315e17be --- /dev/null +++ b/mfbt/Saturate.h @@ -0,0 +1,287 @@ +/* -*- 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/. */ + +/* Provides saturation arithmetics for scalar types. */ + +#ifndef mozilla_Saturate_h +#define mozilla_Saturate_h + +#include "mozilla/Attributes.h" +#include "mozilla/Move.h" +#include "mozilla/NumericLimits.h" +#include "mozilla/TypeTraits.h" + +namespace mozilla { +namespace detail { + +/** + * |SaturateOp| wraps scalar values for saturation arithmetics. Usage: + * + * uint32_t value = 1; + * + * ++SaturateOp(value); // value is 2 + * --SaturateOp(value); // value is 1 + * --SaturateOp(value); // value is 0 + * --SaturateOp(value); // value is still 0 + * + * Please add new operators when required. + * + * |SaturateOp| will saturate at the minimum and maximum values of + * type T. If you need other bounds, implement a clamped-type class and + * specialize the type traits accordingly. + */ +template +class SaturateOp +{ +public: + explicit SaturateOp(T& aValue) + : mValue(aValue) + { + // We should actually check for |std::is_scalar::value| to be + // true, but this type trait is not available everywhere. Relax + // this assertion if you want to use floating point values as well. + static_assert(IsIntegral::value, + "Integral type required in instantiation"); + } + + // Add and subtract operators + + T operator+(const T& aRhs) const + { + return T(mValue) += aRhs; + } + + T operator-(const T& aRhs) const + { + return T(mValue) -= aRhs; + } + + // Compound operators + + const T& operator+=(const T& aRhs) const + { + const T min = NumericLimits::min(); + const T max = NumericLimits::max(); + + if (aRhs > static_cast(0)) { + mValue = (max - aRhs) < mValue ? max : mValue + aRhs; + } else { + mValue = (min - aRhs) > mValue ? min : mValue + aRhs; + } + return mValue; + } + + const T& operator-=(const T& aRhs) const + { + const T min = NumericLimits::min(); + const T max = NumericLimits::max(); + + if (aRhs > static_cast(0)) { + mValue = (min + aRhs) > mValue ? min : mValue - aRhs; + } else { + mValue = (max + aRhs) < mValue ? max : mValue - aRhs; + } + return mValue; + } + + // Increment and decrement operators + + const T& operator++() const // prefix + { + return operator+=(static_cast(1)); + } + + T operator++(int) const // postfix + { + const T value(mValue); + operator++(); + return value; + } + + const T& operator--() const // prefix + { + return operator-=(static_cast(1)); + } + + T operator--(int) const // postfix + { + const T value(mValue); + operator--(); + return value; + } + +private: + SaturateOp(const SaturateOp&) = delete; + SaturateOp(SaturateOp&&) = delete; + SaturateOp& operator=(const SaturateOp&) = delete; + SaturateOp& operator=(SaturateOp&&) = delete; + + T& mValue; +}; + +/** + * |Saturate| is a value type for saturation arithmetics. It's + * build on top of |SaturateOp|. + */ +template +class Saturate +{ +public: + Saturate() = default; + MOZ_IMPLICIT Saturate(const Saturate&) = default; + + MOZ_IMPLICIT Saturate(Saturate&& aValue) + { + mValue = Move(aValue.mValue); + } + + explicit Saturate(const T& aValue) + : mValue(aValue) + { } + + const T& value() const + { + return mValue; + } + + // Compare operators + + bool operator==(const Saturate& aRhs) const + { + return mValue == aRhs.mValue; + } + + bool operator!=(const Saturate& aRhs) const + { + return !operator==(aRhs); + } + + bool operator==(const T& aRhs) const + { + return mValue == aRhs; + } + + bool operator!=(const T& aRhs) const + { + return !operator==(aRhs); + } + + // Assignment operators + + Saturate& operator=(const Saturate&) = default; + + Saturate& operator=(Saturate&& aRhs) + { + mValue = Move(aRhs.mValue); + return *this; + } + + // Add and subtract operators + + Saturate operator+(const Saturate& aRhs) const + { + Saturate lhs(mValue); + return lhs += aRhs.mValue; + } + + Saturate operator+(const T& aRhs) const + { + Saturate lhs(mValue); + return lhs += aRhs; + } + + Saturate operator-(const Saturate& aRhs) const + { + Saturate lhs(mValue); + return lhs -= aRhs.mValue; + } + + Saturate operator-(const T& aRhs) const + { + Saturate lhs(mValue); + return lhs -= aRhs; + } + + // Compound operators + + Saturate& operator+=(const Saturate& aRhs) + { + SaturateOp(mValue) += aRhs.mValue; + return *this; + } + + Saturate& operator+=(const T& aRhs) + { + SaturateOp(mValue) += aRhs; + return *this; + } + + Saturate& operator-=(const Saturate& aRhs) + { + SaturateOp(mValue) -= aRhs.mValue; + return *this; + } + + Saturate& operator-=(const T& aRhs) + { + SaturateOp(mValue) -= aRhs; + return *this; + } + + // Increment and decrement operators + + Saturate& operator++() // prefix + { + ++SaturateOp(mValue); + return *this; + } + + Saturate operator++(int) // postfix + { + return Saturate(SaturateOp(mValue)++); + } + + Saturate& operator--() // prefix + { + --SaturateOp(mValue); + return *this; + } + + Saturate operator--(int) // postfix + { + return Saturate(SaturateOp(mValue)--); + } + +private: + T mValue; +}; + +} // namespace detail + +typedef detail::Saturate SaturateInt8; +typedef detail::Saturate SaturateInt16; +typedef detail::Saturate SaturateInt32; +typedef detail::Saturate SaturateUint8; +typedef detail::Saturate SaturateUint16; +typedef detail::Saturate SaturateUint32; + +} // namespace mozilla + +template +bool +operator==(LhsT aLhs, const mozilla::detail::Saturate& aRhs) +{ + return aRhs.operator==(static_cast(aLhs)); +} + +template +bool +operator!=(LhsT aLhs, const mozilla::detail::Saturate& aRhs) +{ + return !(aLhs == aRhs); +} + +#endif // mozilla_Saturate_h diff --git a/mfbt/moz.build b/mfbt/moz.build index f6acbe8d5c5..38d424dd2ed 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -73,6 +73,7 @@ EXPORTS.mozilla = [ 'RefPtr.h', 'ReverseIterator.h', 'RollingMean.h', + 'Saturate.h', 'Scoped.h', 'ScopeExit.h', 'SegmentedVector.h', diff --git a/mfbt/tests/TestSaturate.cpp b/mfbt/tests/TestSaturate.cpp new file mode 100644 index 00000000000..cd1208ff8f3 --- /dev/null +++ b/mfbt/tests/TestSaturate.cpp @@ -0,0 +1,215 @@ +/* -*- 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 + +#include +#include + +using mozilla::detail::Saturate; +using mozilla::NumericLimits; + +#define A(a) MOZ_RELEASE_ASSERT(a, "Test \'" #a "\' failed.") + +static const unsigned long sNumOps = 32; + +template +static T +StartValue() +{ + // Specialize |StartValue| for the given type. + A(false); +} + +template<> +int8_t +StartValue() +{ + return 0; +} + +template<> +int16_t +StartValue() +{ + return 0; +} + +template<> +int32_t +StartValue() +{ + return 0; +} + +template<> +uint8_t +StartValue() +{ + // Picking a value near middle of uint8_t's range. + return static_cast(NumericLimits::max()); +} + +template<> +uint16_t +StartValue() +{ + // Picking a value near middle of uint16_t's range. + return static_cast(NumericLimits::max()); +} + +template<> +uint32_t +StartValue() +{ + // Picking a value near middle of uint32_t's range. + return static_cast(NumericLimits::max()); +} + +// Add +// + +template +static void +TestPrefixIncr() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A(++value == ++satValue); + } +} + +template +static void +TestPostfixIncr() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A(value++ == satValue++); + } +} + +template +static void +TestAdd() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A((value + i) == (satValue + i)); + } +} + +// Subtract +// + +template +static void +TestPrefixDecr() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A(--value == --satValue); + } +} + +template +static void +TestPostfixDecr() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A(value-- == satValue--); + } +} + +template +static void +TestSub() +{ + T value = StartValue(); + Saturate satValue(value); + + for (T i = 0; i < static_cast(sNumOps); ++i) { + A((value - i) == (satValue - i)); + } +} + +// Corner cases near bounds +// + +template +static void +TestUpperBound() +{ + Saturate satValue(NumericLimits::max()); + + A(--satValue == (NumericLimits::max() - 1)); + A(++satValue == (NumericLimits::max())); + A(++satValue == (NumericLimits::max())); // don't overflow here + A(++satValue == (NumericLimits::max())); // don't overflow here + A(--satValue == (NumericLimits::max() - 1)); // back at (max - 1) + A(--satValue == (NumericLimits::max() - 2)); +} + +template +static void +TestLowerBound() +{ + Saturate satValue(NumericLimits::min()); + + A(++satValue == (NumericLimits::min() + 1)); + A(--satValue == (NumericLimits::min())); + A(--satValue == (NumericLimits::min())); // don't overflow here + A(--satValue == (NumericLimits::min())); // don't overflow here + A(++satValue == (NumericLimits::min() + 1)); // back at (max + 1) + A(++satValue == (NumericLimits::min() + 2)); +} + +// Framework +// + +template +static void +TestAll() +{ + // Assert that we don't accidently hit type's range limits in tests. + const T value = StartValue(); + A(NumericLimits::min() + static_cast(sNumOps) <= value); + A(NumericLimits::max() - static_cast(sNumOps) >= value); + + TestPrefixIncr(); + TestPostfixIncr(); + TestAdd(); + + TestPrefixDecr(); + TestPostfixDecr(); + TestSub(); + + TestUpperBound(); + TestLowerBound(); +} + +int +main() +{ + TestAll(); + TestAll(); + TestAll(); + TestAll(); + TestAll(); + TestAll(); + return 0; +} diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index c75ee8eec15..499cd730de4 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -31,6 +31,7 @@ CppUnitTests([ 'TestPair', 'TestRefPtr', 'TestRollingMean', + 'TestSaturate', 'TestScopeExit', 'TestSegmentedVector', 'TestSHA1', diff --git a/testing/cppunittest.ini b/testing/cppunittest.ini index 05899358c4b..a3e5da5d317 100644 --- a/testing/cppunittest.ini +++ b/testing/cppunittest.ini @@ -67,6 +67,7 @@ skip-if = os == 'android' # Bug 1147630 [TestRollingMean] [TestSHA1] [TestSTSParser] +[TestSaturate] [TestSplayTree] [TestStartupCache] skip-if = os == 'b2g' || os == 'android' # Bug 929655 From 727a5aed92cd3d4075fc6887779dd7c2bfc38047 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 035/160] Bug 1194721: Add PDU_ prefix to daemon PDU constants, r=shuang Something defines HEADER_SIZE when including the PDU headers from hal/gonk. This break the HEADER_SIZE constant in |DaemonSocketPDU|. This patch adds the prefix PDU_ to all PDU constants. --- ipc/hal/DaemonSocket.cpp | 2 +- ipc/hal/DaemonSocketPDU.cpp | 26 +++++++++++++------------- ipc/hal/DaemonSocketPDU.h | 12 ++++++------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ipc/hal/DaemonSocket.cpp b/ipc/hal/DaemonSocket.cpp index 41765acc2c0..6ba49c8c889 100644 --- a/ipc/hal/DaemonSocket.cpp +++ b/ipc/hal/DaemonSocket.cpp @@ -103,7 +103,7 @@ DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) if (!mPDU) { /* There's only one PDU for receiving. We reuse it every time. */ - mPDU = new DaemonSocketPDU(DaemonSocketPDU::MAX_PAYLOAD_LENGTH); + mPDU = new DaemonSocketPDU(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH); } *aBuffer = mPDU.get(); diff --git a/ipc/hal/DaemonSocketPDU.cpp b/ipc/hal/DaemonSocketPDU.cpp index d8cb3070c9a..08184f872c2 100644 --- a/ipc/hal/DaemonSocketPDU.cpp +++ b/ipc/hal/DaemonSocketPDU.cpp @@ -35,17 +35,17 @@ DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); // Allocate memory - size_t availableSpace = HEADER_SIZE + aPayloadSize; + size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize; ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); // Reserve PDU header - uint8_t* data = Append(HEADER_SIZE); + uint8_t* data = Append(PDU_HEADER_SIZE); MOZ_ASSERT(data); // Setup PDU header - data[OFF_SERVICE] = aService; - data[OFF_OPCODE] = aOpcode; - memcpy(data + OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); + data[PDU_OFF_SERVICE] = aService; + data[PDU_OFF_OPCODE] = aOpcode; + memcpy(data + PDU_OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); } DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize) @@ -53,7 +53,7 @@ DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize) { MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); - size_t availableSpace = HEADER_SIZE + aPayloadSize; + size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize; ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); } @@ -69,9 +69,9 @@ void DaemonSocketPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode, uint16_t& aPayloadSize) { - memcpy(&aService, GetData(OFF_SERVICE), sizeof(aService)); - memcpy(&aOpcode, GetData(OFF_OPCODE), sizeof(aOpcode)); - memcpy(&aPayloadSize, GetData(OFF_LENGTH), sizeof(aPayloadSize)); + memcpy(&aService, GetData(PDU_OFF_SERVICE), sizeof(aService)); + memcpy(&aOpcode, GetData(PDU_OFF_OPCODE), sizeof(aOpcode)); + memcpy(&aPayloadSize, GetData(PDU_OFF_LENGTH), sizeof(aPayloadSize)); } ssize_t @@ -164,12 +164,12 @@ nsresult DaemonSocketPDU::UpdateHeader() { size_t len = GetPayloadSize(); - if (len >= MAX_PAYLOAD_LENGTH) { + if (len >= PDU_MAX_PAYLOAD_LENGTH) { return NS_ERROR_ILLEGAL_VALUE; } uint16_t len16 = static_cast(len); - memcpy(GetData(OFF_LENGTH), &len16, sizeof(len16)); + memcpy(GetData(PDU_OFF_LENGTH), &len16, sizeof(len16)); return NS_OK; } @@ -177,9 +177,9 @@ DaemonSocketPDU::UpdateHeader() size_t DaemonSocketPDU::GetPayloadSize() const { - MOZ_ASSERT(GetSize() >= HEADER_SIZE); + MOZ_ASSERT(GetSize() >= PDU_HEADER_SIZE); - return GetSize() - HEADER_SIZE; + return GetSize() - PDU_HEADER_SIZE; } void diff --git a/ipc/hal/DaemonSocketPDU.h b/ipc/hal/DaemonSocketPDU.h index 2f0c9b152cc..006b3ac3a2c 100644 --- a/ipc/hal/DaemonSocketPDU.h +++ b/ipc/hal/DaemonSocketPDU.h @@ -39,12 +39,12 @@ class DaemonSocketPDU final : public UnixSocketIOBuffer { public: enum { - OFF_SERVICE = 0, - OFF_OPCODE = 1, - OFF_LENGTH = 2, - OFF_PAYLOAD = 4, - HEADER_SIZE = OFF_PAYLOAD, - MAX_PAYLOAD_LENGTH = 1 << 16 + PDU_OFF_SERVICE = 0, + PDU_OFF_OPCODE = 1, + PDU_OFF_LENGTH = 2, + PDU_OFF_PAYLOAD = 4, + PDU_HEADER_SIZE = PDU_OFF_PAYLOAD, + PDU_MAX_PAYLOAD_LENGTH = 1 << 16 }; DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize); From 78440c7569b3814e1e248e79303bf0d1575a5b7f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 036/160] Bug 1194721: Add |DaemonRunnable8|, r=shuang The runnable template |DaemonRunnable8| runs an operation with 8 arguments. --- ipc/hal/DaemonRunnables.h | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/ipc/hal/DaemonRunnables.h b/ipc/hal/DaemonRunnables.h index 03d6fa01a3b..e067dd14119 100644 --- a/ipc/hal/DaemonRunnables.h +++ b/ipc/hal/DaemonRunnables.h @@ -713,6 +713,94 @@ private: Tin6 mArg6; }; +template +class DaemonNotificationRunnable8 final : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef DaemonNotificationRunnable8 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), + const InitOp& aInitOp) + { + RefPtr runnable(new SelfType(aMethod)); + if (NS_FAILED(runnable->Init(aInitOp))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), + const InitOp& aInitOp) + { + RefPtr runnable = Create(aMethod, aInitOp); + if (!runnable) { + return; + } + Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable))); + } + + NS_IMETHODIMP Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + if (!obj) { + NS_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, + mArg5, mArg6, mArg7, mArg8); + } + return NS_OK; + } + +private: + DaemonNotificationRunnable8( + Res (ObjectType::*aMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult Init(const InitOp& aInitOp) + { + nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, + mArg5, mArg6, mArg7, mArg8); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)( + Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; + Tin7 mArg7; + Tin8 mArg8; +}; + template Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 037/160] Bug 1194721: Add additional PDU pack and unpack functions, r=shuang This patch adds PDU pack and unpack functions for 64-bit integer values and floating-point values. --- ipc/hal/DaemonSocketPDUHelpers.h | 48 ++++++++++++++++++++++++++++++++ ipc/unixsocket/SocketBase.h | 40 ++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/ipc/hal/DaemonSocketPDUHelpers.h b/ipc/hal/DaemonSocketPDUHelpers.h index 3c9fb775e87..219a0ce0198 100644 --- a/ipc/hal/DaemonSocketPDUHelpers.h +++ b/ipc/hal/DaemonSocketPDUHelpers.h @@ -188,6 +188,30 @@ PackPDU(uint32_t aIn, DaemonSocketPDU& aPDU) return aPDU.Write(aIn); } +inline nsresult +PackPDU(int64_t aIn, DaemonSocketPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(uint64_t aIn, DaemonSocketPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(float aIn, DaemonSocketPDU& aPDU) +{ + return aPDU.Write(aIn); +} + +inline nsresult +PackPDU(double aIn, DaemonSocketPDU& aPDU) +{ + return aPDU.Write(aIn); +} + nsresult PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU); @@ -646,6 +670,30 @@ UnpackPDU(DaemonSocketPDU& aPDU, uint32_t& aOut) return aPDU.Read(aOut); } +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, int64_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, uint64_t& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, float& aOut) +{ + return aPDU.Read(aOut); +} + +inline nsresult +UnpackPDU(DaemonSocketPDU& aPDU, double& aOut) +{ + return aPDU.Read(aOut); +} + inline nsresult UnpackPDU(DaemonSocketPDU& aPDU, DaemonSocketPDUHeader& aOut) { diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h index e59d4dea14f..65d912cefd7 100644 --- a/ipc/unixsocket/SocketBase.h +++ b/ipc/unixsocket/SocketBase.h @@ -73,6 +73,26 @@ public: return Read(&aValue, sizeof(aValue)); } + nsresult Read(int64_t& aValue) + { + return Read(&aValue, sizeof(aValue)); + } + + nsresult Read(uint64_t& aValue) + { + return Read(&aValue, sizeof(aValue)); + } + + nsresult Read(float& aValue) + { + return Read(&aValue, sizeof(aValue)); + } + + nsresult Read(double& aValue) + { + return Read(&aValue, sizeof(aValue)); + } + uint8_t* Append(size_t aLen); nsresult Write(const void* aValue, size_t aLen); @@ -107,6 +127,26 @@ public: return Write(&aValue, sizeof(aValue)); } + nsresult Write(int64_t aValue) + { + return Write(&aValue, sizeof(aValue)); + } + + nsresult Write(uint64_t aValue) + { + return Write(&aValue, sizeof(aValue)); + } + + nsresult Write(float aValue) + { + return Write(&aValue, sizeof(aValue)); + } + + nsresult Write(double aValue) + { + return Write(&aValue, sizeof(aValue)); + } + protected: UnixSocketBuffer(); From 25e228390d59dee0f0599347f1b15fe51ae7165e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 038/160] Bug 1194721: Add helpers for Gonk sensors daemon, r=gsvelto This patch adds helpers for using the Gonk sensors daemon. The types and functions allow for packing and unpacking messages of the daemon's IPC protocol. --- hal/gonk/GonkSensorsHelpers.cpp | 112 +++++++++++++++ hal/gonk/GonkSensorsHelpers.h | 226 +++++++++++++++++++++++++++++++ hal/gonk/SensorsTypes.h | 140 +++++++++++++++++++ hal/moz.build | 1 + ipc/hal/DaemonSocketPDUHelpers.h | 130 ++++++++++++++++++ 5 files changed, 609 insertions(+) create mode 100644 hal/gonk/GonkSensorsHelpers.cpp create mode 100644 hal/gonk/GonkSensorsHelpers.h create mode 100644 hal/gonk/SensorsTypes.h diff --git a/hal/gonk/GonkSensorsHelpers.cpp b/hal/gonk/GonkSensorsHelpers.cpp new file mode 100644 index 00000000000..ccc940c7c08 --- /dev/null +++ b/hal/gonk/GonkSensorsHelpers.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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 "GonkSensorsHelpers.h" + +namespace mozilla { +namespace hal { + +// +// Unpacking +// + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut) +{ + nsresult rv = UnpackPDU(aPDU, aOut.mType); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mTimestamp); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mStatus); + if (NS_FAILED(rv)) { + return rv; + } + + size_t i = 0; + + switch (aOut.mType) { + case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED: + case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED: + /* 6 data values */ + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + /* fall through */ + case SENSORS_TYPE_ROTATION_VECTOR: + case SENSORS_TYPE_GAME_ROTATION_VECTOR: + case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR: + /* 5 data values */ + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + /* fall through */ + case SENSORS_TYPE_ACCELEROMETER: + case SENSORS_TYPE_GEOMAGNETIC_FIELD: + case SENSORS_TYPE_ORIENTATION: + case SENSORS_TYPE_GYROSCOPE: + case SENSORS_TYPE_GRAVITY: + case SENSORS_TYPE_LINEAR_ACCELERATION: + /* 3 data values */ + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + /* fall through */ + case SENSORS_TYPE_LIGHT: + case SENSORS_TYPE_PRESSURE: + case SENSORS_TYPE_TEMPERATURE: + case SENSORS_TYPE_PROXIMITY: + case SENSORS_TYPE_RELATIVE_HUMIDITY: + case SENSORS_TYPE_AMBIENT_TEMPERATURE: + case SENSORS_TYPE_HEART_RATE: + case SENSORS_TYPE_TILT_DETECTOR: + case SENSORS_TYPE_WAKE_GESTURE: + case SENSORS_TYPE_GLANCE_GESTURE: + case SENSORS_TYPE_PICK_UP_GESTURE: + case SENSORS_TYPE_WRIST_TILT_GESTURE: + case SENSORS_TYPE_SIGNIFICANT_MOTION: + case SENSORS_TYPE_STEP_DETECTED: + /* 1 data value */ + rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); + if (NS_FAILED(rv)) { + return rv; + } + break; + case SENSORS_TYPE_STEP_COUNTER: + /* 1 data value */ + rv = UnpackPDU(aPDU, aOut.mData.mUint[0]); + if (NS_FAILED(rv)) { + return rv; + } + break; + default: + if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) { + return NS_ERROR_ILLEGAL_VALUE; + } + } + rv = UnpackPDU(aPDU, aOut.mDeliveryMode); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; +} + +} // namespace hal +} // namespace mozilla diff --git a/hal/gonk/GonkSensorsHelpers.h b/hal/gonk/GonkSensorsHelpers.h new file mode 100644 index 00000000000..5218af53afd --- /dev/null +++ b/hal/gonk/GonkSensorsHelpers.h @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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/. */ + +#ifndef hal_gonk_GonkSensorsHelpers_h +#define hal_gonk_GonkSensorsHelpers_h + +#include +#include +#include "SensorsTypes.h" + +namespace mozilla { +namespace hal { + +using mozilla::ipc::DaemonSocketPDU; +using mozilla::ipc::DaemonSocketPDUHeader; +using mozilla::ipc::DaemonSocketPDUHelpers::Convert; +using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU; +using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU; + +using namespace mozilla::ipc::DaemonSocketPDUHelpers; + +// +// Conversion +// +// The functions below convert the input value to the output value's +// type and perform extension tests on the validity of the result. On +// success the output value will be returned in |aOut|. The functions +// return NS_OK on success, or an XPCOM error code otherwise. +// +// See the documentation of the HAL IPC framework for more information +// on conversion functions. +// + +nsresult +Convert(int32_t aIn, SensorsStatus& aOut) +{ + static const uint8_t sStatus[] = { + [0] = SENSORS_STATUS_NO_CONTACT, // '-1' + [1] = SENSORS_STATUS_UNRELIABLE, // '0' + [2] = SENSORS_STATUS_ACCURACY_LOW, // '1' + [3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2' + [4] = SENSORS_STATUS_ACCURACY_HIGH // '3' + }; + static const int8_t sOffset = -1; // '-1' is the lower bound of the status + + if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) || + MOZ_HAL_IPC_CONVERT_WARN_IF( + aIn >= (static_cast(MOZ_ARRAY_LENGTH(sStatus)) + sOffset), + int32_t, SensorsStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(sStatus[aIn - sOffset]); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, SensorsDeliveryMode& aOut) +{ + static const uint8_t sMode[] = { + [0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT, + [0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE + }; + if (MOZ_HAL_IPC_CONVERT_WARN_IF( + aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(sMode[aIn]); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, SensorsError& aOut) +{ + static const uint8_t sError[] = { + [0x00] = SENSORS_ERROR_NONE, + [0x01] = SENSORS_ERROR_FAIL, + [0x02] = SENSORS_ERROR_NOT_READY, + [0x03] = SENSORS_ERROR_NOMEM, + [0x04] = SENSORS_ERROR_BUSY, + [0x05] = SENSORS_ERROR_DONE, + [0x06] = SENSORS_ERROR_UNSUPPORTED, + [0x07] = SENSORS_ERROR_PARM_INVALID + }; + if (MOZ_HAL_IPC_CONVERT_WARN_IF( + aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(sError[aIn]); + return NS_OK; +} + +nsresult +Convert(uint8_t aIn, SensorsTriggerMode& aOut) +{ + static const uint8_t sMode[] = { + [0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS, + [0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE, + [0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT, + [0x03] = SENSORS_TRIGGER_MODE_SPECIAL + }; + if (MOZ_HAL_IPC_CONVERT_WARN_IF( + aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(sMode[aIn]); + return NS_OK; +} + +nsresult +Convert(uint32_t aIn, SensorsType& aOut) +{ + static const uint8_t sType[] = { + [0x00] = 0, // invalid, required by gcc + [0x01] = SENSORS_TYPE_ACCELEROMETER, + [0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD, + [0x03] = SENSORS_TYPE_ORIENTATION, + [0x04] = SENSORS_TYPE_GYROSCOPE, + [0x05] = SENSORS_TYPE_LIGHT, + [0x06] = SENSORS_TYPE_PRESSURE, + [0x07] = SENSORS_TYPE_TEMPERATURE, + [0x08] = SENSORS_TYPE_PROXIMITY, + [0x09] = SENSORS_TYPE_GRAVITY, + [0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION, + [0x0b] = SENSORS_TYPE_ROTATION_VECTOR, + [0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY, + [0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE, + [0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, + [0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR, + [0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, + [0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION, + [0x12] = SENSORS_TYPE_STEP_DETECTED, + [0x13] = SENSORS_TYPE_STEP_COUNTER, + [0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, + [0x15] = SENSORS_TYPE_HEART_RATE, + [0x16] = SENSORS_TYPE_TILT_DETECTOR, + [0x17] = SENSORS_TYPE_WAKE_GESTURE, + [0x18] = SENSORS_TYPE_GLANCE_GESTURE, + [0x19] = SENSORS_TYPE_PICK_UP_GESTURE, + [0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE + }; + if (MOZ_HAL_IPC_CONVERT_WARN_IF( + !aIn, uint32_t, SensorsType) || + MOZ_HAL_IPC_CONVERT_WARN_IF( + aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = static_cast(sType[aIn]); + return NS_OK; +} + +nsresult +Convert(nsresult aIn, SensorsError& aOut) +{ + if (NS_SUCCEEDED(aIn)) { + aOut = SENSORS_ERROR_NONE; + } else if (aIn == NS_ERROR_OUT_OF_MEMORY) { + aOut = SENSORS_ERROR_NOMEM; + } else if (aIn == NS_ERROR_ILLEGAL_VALUE) { + aOut = SENSORS_ERROR_PARM_INVALID; + } else { + aOut = SENSORS_ERROR_FAIL; + } + return NS_OK; +} + +// +// Packing +// +// Pack functions store a value in PDU. See the documentation of the +// HAL IPC framework for more information. +// +// There are currently no sensor-specific pack functions necessary. If +// you add one, put it below. +// + +// +// Unpacking +// +// Unpack function retrieve a value from a PDU. The functions return +// NS_OK on success, or an XPCOM error code otherwise. On sucess, the +// returned value is stored in the second argument |aOut|. +// +// See the documentation of the HAL IPC framework for more information +// on unpack functions. +// + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut); + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +nsresult +UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut) +{ + return UnpackPDU(aPDU, UnpackConversion(aOut)); +} + +} // namespace hal +} // namespace mozilla + +#endif // hal_gonk_GonkSensorsHelpers_h diff --git a/hal/gonk/SensorsTypes.h b/hal/gonk/SensorsTypes.h new file mode 100644 index 00000000000..35c852f5a80 --- /dev/null +++ b/hal/gonk/SensorsTypes.h @@ -0,0 +1,140 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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/. */ + +#ifndef hal_gonk_SensorsTypes_h +#define hal_gonk_SensorsTypes_h + +namespace mozilla { +namespace hal { + +enum SensorsDeliveryMode { + SENSORS_DELIVERY_MODE_BEST_EFFORT, + SENSORS_DELIVERY_MODE_IMMEDIATE +}; + +enum SensorsError { + SENSORS_ERROR_NONE, + SENSORS_ERROR_FAIL, + SENSORS_ERROR_NOT_READY, + SENSORS_ERROR_NOMEM, + SENSORS_ERROR_BUSY, + SENSORS_ERROR_DONE, + SENSORS_ERROR_UNSUPPORTED, + SENSORS_ERROR_PARM_INVALID +}; + +enum SensorsStatus { + SENSORS_STATUS_NO_CONTACT, + SENSORS_STATUS_UNRELIABLE, + SENSORS_STATUS_ACCURACY_LOW, + SENSORS_STATUS_ACCURACY_MEDIUM, + SENSORS_STATUS_ACCURACY_HIGH +}; + +enum SensorsTriggerMode { + SENSORS_TRIGGER_MODE_CONTINUOUS, + SENSORS_TRIGGER_MODE_ON_CHANGE, + SENSORS_TRIGGER_MODE_ONE_SHOT, + SENSORS_TRIGGER_MODE_SPECIAL +}; + +enum SensorsType { + SENSORS_TYPE_ACCELEROMETER, + SENSORS_TYPE_GEOMAGNETIC_FIELD, + SENSORS_TYPE_ORIENTATION, + SENSORS_TYPE_GYROSCOPE, + SENSORS_TYPE_LIGHT, + SENSORS_TYPE_PRESSURE, + SENSORS_TYPE_TEMPERATURE, + SENSORS_TYPE_PROXIMITY, + SENSORS_TYPE_GRAVITY, + SENSORS_TYPE_LINEAR_ACCELERATION, + SENSORS_TYPE_ROTATION_VECTOR, + SENSORS_TYPE_RELATIVE_HUMIDITY, + SENSORS_TYPE_AMBIENT_TEMPERATURE, + SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, + SENSORS_TYPE_GAME_ROTATION_VECTOR, + SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, + SENSORS_TYPE_SIGNIFICANT_MOTION, + SENSORS_TYPE_STEP_DETECTED, + SENSORS_TYPE_STEP_COUNTER, + SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, + SENSORS_TYPE_HEART_RATE, + SENSORS_TYPE_TILT_DETECTOR, + SENSORS_TYPE_WAKE_GESTURE, + SENSORS_TYPE_GLANCE_GESTURE, + SENSORS_TYPE_PICK_UP_GESTURE, + SENSORS_TYPE_WRIST_TILT_GESTURE, + SENSORS_NUM_TYPES +}; + +struct SensorsEvent { + SensorsType mType; + SensorsStatus mStatus; + SensorsDeliveryMode mDeliveryMode; + int64_t mTimestamp; + union { + float mFloat[6]; + uint64_t mUint[1]; + } mData; +}; + +/** + * |SensorsSensor| represents a device sensor; either single or composite. + */ +struct SensorsSensor { + SensorsSensor(int32_t aId, SensorsType aType, + float aRange, float aResolution, + float aPower, int32_t aMinPeriod, + int32_t aMaxPeriod, + SensorsTriggerMode aTriggerMode, + SensorsDeliveryMode aDeliveryMode) + : mId(aId) + , mType(aType) + , mRange(aRange) + , mResolution(aResolution) + , mPower(aPower) + , mMinPeriod(aMinPeriod) + , mMaxPeriod(aMaxPeriod) + , mTriggerMode(aTriggerMode) + , mDeliveryMode(aDeliveryMode) + { } + + int32_t mId; + SensorsType mType; + float mRange; + float mResolution; + float mPower; + int32_t mMinPeriod; + int32_t mMaxPeriod; + SensorsTriggerMode mTriggerMode; + SensorsDeliveryMode mDeliveryMode; +}; + +/** + * |SensorClass| represents the status of a specific sensor type. + */ +struct SensorsSensorClass { + SensorsSensorClass() + : mActivated(0) + , mMinValue(0) + , mMaxValue(0) + { } + + void UpdateFromSensor(const SensorsSensor& aSensor) + { + mMaxValue = std::max(aSensor.mRange, mMaxValue); + } + + uint32_t mActivated; + float mMinValue; + float mMaxValue; +}; + +} // namespace hal +} // namespace mozilla + +#endif // hal_gonk_SensorsTypes_h diff --git a/hal/moz.build b/hal/moz.build index e0328816851..0a0c5cd8b51 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -51,6 +51,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkDiskSpaceWatcher.cpp', 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', + 'gonk/GonkSensorsHelpers.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', 'gonk/UeventPoller.cpp', diff --git a/ipc/hal/DaemonSocketPDUHelpers.h b/ipc/hal/DaemonSocketPDUHelpers.h index 219a0ce0198..02f672f0ed5 100644 --- a/ipc/hal/DaemonSocketPDUHelpers.h +++ b/ipc/hal/DaemonSocketPDUHelpers.h @@ -1142,6 +1142,136 @@ public: WarnAboutTrailingData(); return NS_OK; } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, + T5& aArg5, T6& aArg6, T7& aArg7) const + { + DaemonSocketPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg6); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg7); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, + T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8) const + { + DaemonSocketPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg6); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg7); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg8); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } + + template + nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, + T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8, + T9& aArg9) const + { + DaemonSocketPDU& pdu = GetPDU(); + + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg6); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg7); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg8); + if (NS_FAILED(rv)) { + return rv; + } + rv = UnpackPDU(pdu, aArg9); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } }; } // namespace DaemonSocketPDUHelpers From e9dc67bab48460705625838abb5445a7d9c0df1c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 039/160] Bug 1194721: Add registry interface and module for Gonk sensors, r=gsvelto A system daemon can contain several services. One of them is the registry service that manages all other services. This patch adds support for this service in the Gonk sensors daemon. --- hal/gonk/GonkSensorsRegistryInterface.cpp | 212 ++++++++++++++++++++++ hal/gonk/GonkSensorsRegistryInterface.h | 185 +++++++++++++++++++ hal/moz.build | 1 + 3 files changed, 398 insertions(+) create mode 100644 hal/gonk/GonkSensorsRegistryInterface.cpp create mode 100644 hal/gonk/GonkSensorsRegistryInterface.h diff --git a/hal/gonk/GonkSensorsRegistryInterface.cpp b/hal/gonk/GonkSensorsRegistryInterface.cpp new file mode 100644 index 00000000000..0fc318fe2a8 --- /dev/null +++ b/hal/gonk/GonkSensorsRegistryInterface.cpp @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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 "GonkSensorsRegistryInterface.h" +#include "GonkSensorsHelpers.h" +#include "HalLog.h" + +namespace mozilla { +namespace hal { + +using namespace mozilla::ipc; + +// +// GonkSensorsRegistryResultHandler +// + +void +GonkSensorsRegistryResultHandler::OnError(SensorsError aError) +{ + HAL_ERR("Received error code %d", static_cast(aError)); +} + +void +GonkSensorsRegistryResultHandler::RegisterModule(uint32_t aProtocolVersion) +{ } + +void +GonkSensorsRegistryResultHandler::UnregisterModule() +{ } + +GonkSensorsRegistryResultHandler::~GonkSensorsRegistryResultHandler() +{ } + +// +// GonkSensorsRegistryModule +// + +GonkSensorsRegistryModule::~GonkSensorsRegistryModule() +{ } + +void +GonkSensorsRegistryModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (GonkSensorsRegistryModule::* const HandleRsp[])( + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, + GonkSensorsRegistryResultHandler*) = { + [OPCODE_ERROR] = &GonkSensorsRegistryModule::ErrorRsp, + [OPCODE_REGISTER_MODULE] = &GonkSensorsRegistryModule::RegisterModuleRsp, + [OPCODE_UNREGISTER_MODULE] = &GonkSensorsRegistryModule::UnregisterModuleRsp + }; + + if ((aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) || + !HandleRsp[aHeader.mOpcode]) { + HAL_ERR("Sensors registry response opcode %d unknown", aHeader.mOpcode); + return; + } + + RefPtr res = + static_cast(aRes); + + if (!res) { + return; // Return early if no result handler has been set + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Commands +// + +nsresult +GonkSensorsRegistryModule::RegisterModuleCmd( + uint8_t aId, GonkSensorsRegistryResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_REGISTER_MODULE, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + Unused << pdu.forget(); + return NS_OK; +} + +nsresult +GonkSensorsRegistryModule::UnregisterModuleCmd( + uint8_t aId, GonkSensorsRegistryResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + Unused << pdu.forget(); + return NS_OK; +} + +// Responses +// + +void +GonkSensorsRegistryModule::ErrorRsp( + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, GonkSensorsRegistryResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &GonkSensorsRegistryResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsRegistryModule::RegisterModuleRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + GonkSensorsRegistryResultHandler* aRes) +{ + Uint32ResultRunnable::Dispatch( + aRes, + &GonkSensorsRegistryResultHandler::RegisterModule, + UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsRegistryModule::UnregisterModuleRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + GonkSensorsRegistryResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, + &GonkSensorsRegistryResultHandler::UnregisterModule, + UnpackPDUInitOp(aPDU)); +} + +// +// GonkSensorsRegistryInterface +// + +GonkSensorsRegistryInterface::GonkSensorsRegistryInterface( + GonkSensorsRegistryModule* aModule) + : mModule(aModule) +{ } + +GonkSensorsRegistryInterface::~GonkSensorsRegistryInterface() +{ } + +void +GonkSensorsRegistryInterface::RegisterModule( + uint8_t aId, GonkSensorsRegistryResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->RegisterModuleCmd(aId, aRes); + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +GonkSensorsRegistryInterface::UnregisterModule( + uint8_t aId, GonkSensorsRegistryResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->UnregisterModuleCmd(aId, aRes); + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +GonkSensorsRegistryInterface::DispatchError( + GonkSensorsRegistryResultHandler* aRes, SensorsError aError) +{ + DaemonResultRunnable1::Dispatch( + aRes, &GonkSensorsRegistryResultHandler::OnError, + ConstantInitOp1(aError)); +} + +void +GonkSensorsRegistryInterface::DispatchError( + GonkSensorsRegistryResultHandler* aRes, nsresult aRv) +{ + SensorsError error; + + if (NS_FAILED(Convert(aRv, error))) { + error = SENSORS_ERROR_FAIL; + } + DispatchError(aRes, error); +} + +} // namespace hal +} // namespace mozilla diff --git a/hal/gonk/GonkSensorsRegistryInterface.h b/hal/gonk/GonkSensorsRegistryInterface.h new file mode 100644 index 00000000000..e7d64cb1d81 --- /dev/null +++ b/hal/gonk/GonkSensorsRegistryInterface.h @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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/. */ + +/* + * The registry interface gives yo access to the Sensors daemon's Registry + * service. The purpose of the service is to register and setup all other + * services, and make them available. + * + * All public methods and callback methods run on the main thread. + */ + +#ifndef hal_gonk_GonkSensorsRegistryInterface_h +#define hal_gonk_GonkSensorsRegistryInterface_h + +#include +#include +#include "SensorsTypes.h" + +namespace mozilla { +namespace ipc { + +class DaemonSocketPDU; +class DaemonSocketPDUHeader; + +} +} + +namespace mozilla { +namespace hal { + +class SensorsInterface; + +using mozilla::ipc::DaemonSocketPDU; +using mozilla::ipc::DaemonSocketPDUHeader; +using mozilla::ipc::DaemonSocketResultHandler; + +/** + * This class is the result-handler interface for the Sensors + * Registry interface. Methods always run on the main thread. + */ +class GonkSensorsRegistryResultHandler : public DaemonSocketResultHandler +{ +public: + + /** + * Called if a registry command failed. + * + * @param aError The error code. + */ + virtual void OnError(SensorsError aError); + + /** + * The callback method for |GonkSensorsRegistryInterface::RegisterModule|. + * + * @param aProtocolVersion The daemon's protocol version. Make sure it's + * compatible with Gecko's implementation. + */ + virtual void RegisterModule(uint32_t aProtocolVersion); + + /** + * The callback method for |SensorsRegsitryInterface::UnregisterModule|. + */ + virtual void UnregisterModule(); + +protected: + virtual ~GonkSensorsRegistryResultHandler(); +}; + +/** + * This is the module class for the Sensors registry component. It handles + * PDU packing and unpacking. Methods are either executed on the main thread + * or the I/O thread. + * + * This is an internal class, use |GonkSensorsRegistryInterface| instead. + */ +class GonkSensorsRegistryModule +{ +public: + enum { + SERVICE_ID = 0x00 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_REGISTER_MODULE = 0x01, + OPCODE_UNREGISTER_MODULE = 0x02 + }; + + virtual nsresult Send(DaemonSocketPDU* aPDU, + DaemonSocketResultHandler* aRes) = 0; + + // + // Commands + // + + nsresult RegisterModuleCmd(uint8_t aId, + GonkSensorsRegistryResultHandler* aRes); + + nsresult UnregisterModuleCmd(uint8_t aId, + GonkSensorsRegistryResultHandler* aRes); + +protected: + virtual ~GonkSensorsRegistryModule(); + + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); + + // + // Responses + // + + typedef mozilla::ipc::DaemonResultRunnable0< + GonkSensorsRegistryResultHandler, void> + ResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable1< + GonkSensorsRegistryResultHandler, void, uint32_t, uint32_t> + Uint32ResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable1< + GonkSensorsRegistryResultHandler, void, SensorsError, SensorsError> + ErrorRunnable; + + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsRegistryResultHandler* aRes); + + void RegisterModuleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsRegistryResultHandler* aRes); + + void UnregisterModuleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsRegistryResultHandler* aRes); +}; + +/** + * This class implements the public interface to the Sensors Registry + * component. Use |SensorsInterface::GetRegistryInterface| to retrieve + * an instance. All methods run on the main thread. + */ +class GonkSensorsRegistryInterface final +{ +public: + friend class GonkSensorsInterface; + + /** + * Sends a RegisterModule command to the Sensors daemon. When the + * result handler's |RegisterModule| method gets called, the service + * has been registered successfully and can be used. + * + * @param aId The id of the service that is to be registered. + * @param aRes The result handler. + */ + void RegisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); + + /** + * Sends an UnregisterModule command to the Sensors daemon. The service + * should not be used afterwards until it has been registered again. + * + * @param aId The id of the service that is to be unregistered. + * @param aRes The result handler. + */ + void UnregisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); + + ~GonkSensorsRegistryInterface(); + +private: + GonkSensorsRegistryInterface(GonkSensorsRegistryModule* aModule); + + void DispatchError(GonkSensorsRegistryResultHandler* aRes, + SensorsError aError); + void DispatchError(GonkSensorsRegistryResultHandler* aRes, + nsresult aRv); + + GonkSensorsRegistryModule* mModule; +}; + +} // namespace hal +} // namespace mozilla + +#endif // hal_gonk_GonkSensorsRegistryInterface_h diff --git a/hal/moz.build b/hal/moz.build index 0a0c5cd8b51..bba3f138670 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,6 +52,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', + 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', 'gonk/UeventPoller.cpp', From b89bc893d6c08a4e3ae1d823a2517626689ac272 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 040/160] Bug 1194721: Add poll interface and module for Gonk sensors, r=gsvelto The sensor daemon's poll service reads events from the device's sensors. This patch adds Gecko support for this service. Gecko receives information about existing sensors and can subscribe to sensor events. Events will be delivered for each enabled sensor. --- hal/gonk/GonkSensorsPollInterface.cpp | 430 ++++++++++++++++++++++++++ hal/gonk/GonkSensorsPollInterface.h | 343 ++++++++++++++++++++ hal/moz.build | 1 + 3 files changed, 774 insertions(+) create mode 100644 hal/gonk/GonkSensorsPollInterface.cpp create mode 100644 hal/gonk/GonkSensorsPollInterface.h diff --git a/hal/gonk/GonkSensorsPollInterface.cpp b/hal/gonk/GonkSensorsPollInterface.cpp new file mode 100644 index 00000000000..010deb656a7 --- /dev/null +++ b/hal/gonk/GonkSensorsPollInterface.cpp @@ -0,0 +1,430 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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 "GonkSensorsPollInterface.h" +#include "HalLog.h" + +namespace mozilla { +namespace hal { + +using namespace mozilla::ipc; + +// +// GonkSensorsPollResultHandler +// + +void +GonkSensorsPollResultHandler::OnError(SensorsError aError) +{ + HAL_ERR("Received error code %d", static_cast(aError)); +} + +void +GonkSensorsPollResultHandler::EnableSensor() +{ } + +void +GonkSensorsPollResultHandler::DisableSensor() +{ } + +void +GonkSensorsPollResultHandler::SetPeriod() +{ } + +GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler() +{ } + +// +// GonkSensorsPollNotificationHandler +// + +void +GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError) +{ + HAL_ERR("Received error code %d", static_cast(aError)); +} + +void +GonkSensorsPollNotificationHandler::SensorDetectedNotification( + int32_t aId, + SensorsType aType, + float aRange, + float aResolution, + float aPower, + int32_t aMinPeriod, + int32_t aMaxPeriod, + SensorsTriggerMode aTriggerMode, + SensorsDeliveryMode aDeliveryMode) +{ } + +void +GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId) +{ } + +void +GonkSensorsPollNotificationHandler::EventNotification(int32_t aId, + const SensorsEvent& aEvent) +{ } + +GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler() +{ } + +// +// GonkSensorsPollModule +// + +GonkSensorsPollModule::GonkSensorsPollModule() + : mProtocolVersion(0) +{ } + +GonkSensorsPollModule::~GonkSensorsPollModule() +{ } + +nsresult +GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion) +{ + if ((aProtocolVersion < MIN_PROTOCOL_VERSION) || + (aProtocolVersion > MAX_PROTOCOL_VERSION)) { + HAL_ERR("Sensors Poll protocol version %lu not supported", + aProtocolVersion); + return NS_ERROR_ILLEGAL_VALUE; + } + mProtocolVersion = aProtocolVersion; + return NS_OK; +} + +void +GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (GonkSensorsPollModule::* const HandleOp[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&, + DaemonSocketResultHandler*) = { + [0] = &GonkSensorsPollModule::HandleRsp, + [1] = &GonkSensorsPollModule::HandleNtf + }; + + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread + + // Negate twice to map bit to 0/1 + unsigned long isNtf = !!(aHeader.mOpcode & 0x80); + + (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes); +} + +// Commands +// + +nsresult +GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + Unused << pdu.forget(); + return NS_OK; +} + +nsresult +GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + Unused << pdu.forget(); + return NS_OK; +} + +nsresult +GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod, + GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PERIOD, 0)); + + nsresult rv = PackPDU(aId, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = PackPDU(aPeriod, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + Unused << pdu.forget(); + return NS_OK; +} + +// Responses +// + +void +GonkSensorsPollModule::ErrorRsp( + const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::EnableSensorRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::DisableSensorRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::SetPeriodRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::HandleRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (GonkSensorsPollModule::* const sHandleRsp[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&, + GonkSensorsPollResultHandler*) = { + [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp, + [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp, + [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp, + [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp, + }; + + MOZ_ASSERT(!NS_IsMainThread()); // I/O thread + + if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) || + !sHandleRsp[aHeader.mOpcode]) { + HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode); + return; + } + + RefPtr res = + static_cast(aRes); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Notifications +// + +// Returns the current notification handler to a notification runnable +class GonkSensorsPollModule::NotificationHandlerWrapper final +{ +public: + typedef GonkSensorsPollNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } + + static GonkSensorsPollNotificationHandler* sNotificationHandler; +}; + +GonkSensorsPollNotificationHandler* + GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler; + +void +GonkSensorsPollModule::ErrorNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + ErrorNotification::Dispatch( + &GonkSensorsPollNotificationHandler::ErrorNotification, + UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::SensorDetectedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + SensorDetectedNotification::Dispatch( + &GonkSensorsPollNotificationHandler::SensorDetectedNotification, + UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::SensorLostNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + SensorLostNotification::Dispatch( + &GonkSensorsPollNotificationHandler::SensorLostNotification, + UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::EventNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + EventNotification::Dispatch( + &GonkSensorsPollNotificationHandler::EventNotification, + UnpackPDUInitOp(aPDU)); +} + +void +GonkSensorsPollModule::HandleNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (GonkSensorsPollModule::* const sHandleNtf[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { + [0] = &GonkSensorsPollModule::ErrorNtf, + [1] = &GonkSensorsPollModule::SensorDetectedNtf, + [2] = &GonkSensorsPollModule::SensorLostNtf, + [3] = &GonkSensorsPollModule::EventNtf + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x80; + + if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) { + HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode); + return; + } + + (this->*(sHandleNtf[index]))(aHeader, aPDU); +} + +// +// GonkSensorsPollInterface +// + +GonkSensorsPollInterface::GonkSensorsPollInterface( + GonkSensorsPollModule* aModule) + : mModule(aModule) +{ } + +GonkSensorsPollInterface::~GonkSensorsPollInterface() +{ } + +void +GonkSensorsPollInterface::SetNotificationHandler( + GonkSensorsPollNotificationHandler* aNotificationHandler) +{ + MOZ_ASSERT(NS_IsMainThread()); + + GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler = + aNotificationHandler; +} + +nsresult +GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion) +{ + MOZ_ASSERT(mModule); + + return mModule->SetProtocolVersion(aProtocolVersion); +} + +void +GonkSensorsPollInterface::EnableSensor(int32_t aId, + GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->EnableSensorCmd(aId, aRes); + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +GonkSensorsPollInterface::DisableSensor(int32_t aId, + GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->DisableSensorCmd(aId, aRes); + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod, + GonkSensorsPollResultHandler* aRes) +{ + MOZ_ASSERT(mModule); + + nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes); + if (NS_FAILED(rv)) { + DispatchError(aRes, rv); + } +} + +void +GonkSensorsPollInterface::DispatchError( + GonkSensorsPollResultHandler* aRes, SensorsError aError) +{ + DaemonResultRunnable1::Dispatch( + aRes, &GonkSensorsPollResultHandler::OnError, + ConstantInitOp1(aError)); +} + +void +GonkSensorsPollInterface::DispatchError( + GonkSensorsPollResultHandler* aRes, nsresult aRv) +{ + SensorsError error; + + if (NS_FAILED(Convert(aRv, error))) { + error = SENSORS_ERROR_FAIL; + } + DispatchError(aRes, error); +} + +} // namespace hal +} // namespace mozilla diff --git a/hal/gonk/GonkSensorsPollInterface.h b/hal/gonk/GonkSensorsPollInterface.h new file mode 100644 index 00000000000..d25fed4f3ea --- /dev/null +++ b/hal/gonk/GonkSensorsPollInterface.h @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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/. */ + +/* + * The poll interface gives yo access to the Sensors daemon's Poll service, + * which handles sensors. The poll service will inform you when sensors are + * detected or removed from the system. You can activate (or deactivate) + * existing sensors and poll will deliver the sensors' events. + * + * All public methods and callback methods run on the main thread. + */ + +#ifndef hal_gonk_GonkSensorsPollInterface_h +#define hal_gonk_GonkSensorsPollInterface_h + +#include +#include +#include "SensorsTypes.h" + +namespace mozilla { +namespace ipc { + +class DaemonSocketPDU; +class DaemonSocketPDUHeader; + +} +} + +namespace mozilla { +namespace hal { + +class SensorsInterface; + +using mozilla::ipc::DaemonSocketPDU; +using mozilla::ipc::DaemonSocketPDUHeader; +using mozilla::ipc::DaemonSocketResultHandler; + +/** + * This class is the result-handler interface for the Sensors + * Poll interface. Methods always run on the main thread. + */ +class GonkSensorsPollResultHandler : public DaemonSocketResultHandler +{ +public: + + /** + * Called if a poll command failed. + * + * @param aError The error code. + */ + virtual void OnError(SensorsError aError); + + /** + * The callback method for |GonkSensorsPollInterface::EnableSensor|. + */ + virtual void EnableSensor(); + + /** + * The callback method for |GonkSensorsPollInterface::DisableSensor|. + */ + virtual void DisableSensor(); + + /** + * The callback method for |GonkSensorsPollInterface::SetPeriod|. + */ + virtual void SetPeriod(); + +protected: + virtual ~GonkSensorsPollResultHandler(); +}; + +/** + * This is the notification-handler interface. Implement this classes + * methods to handle event and notifications from the sensors daemon. + */ +class GonkSensorsPollNotificationHandler +{ +public: + + /** + * The notification handler for errors. You'll receive this call if + * there's been a critical error in the daemon. Either try to handle + * the error, or restart the daemon. + * + * @param aError The error code. + */ + virtual void ErrorNotification(SensorsError aError); + + /** + * This methods gets call when a new sensor has been detected. + * + * @param aId The sensor's id. + * @param aType The sensor's type. + * @param aRange The sensor's maximum value. + * @param aResolution The minimum difference between two consecutive values. + * @param aPower The sensor's power consumption (in mA). + * @param aMinPeriod The minimum time between two events (in ns). + * @param aMaxPeriod The maximum time between two events (in ns). + * @param aTriggerMode The sensor's mode for triggering events. + * @param aDeliveryMode The sensor's urgency for event delivery. + */ + virtual void SensorDetectedNotification(int32_t aId, SensorsType aType, + float aRange, float aResolution, + float aPower, int32_t aMinPeriod, + int32_t aMaxPeriod, + SensorsTriggerMode aTriggerMode, + SensorsDeliveryMode aDeliveryMode); + + /** + * This methods gets call when an existing sensor has been removed. + * + * @param aId The sensor's id. + */ + virtual void SensorLostNotification(int32_t aId); + + /** + * This is the callback methods for sensor events. Only activated sensors + * generate events. All sensors are disabled by default. The actual data + * of the event depends on the sensor type. + * + * @param aId The sensor's id. + * @param aEvent The event's data. + */ + virtual void EventNotification(int32_t aId, const SensorsEvent& aEvent); + +protected: + virtual ~GonkSensorsPollNotificationHandler(); +}; + +/** + * This is the module class for the Sensors poll component. It handles PDU + * packing and unpacking. Methods are either executed on the main thread or + * the I/O thread. + * + * This is an internal class, use |GonkSensorsPollInterface| instead. + */ +class GonkSensorsPollModule +{ +public: + class NotificationHandlerWrapper; + + enum { + SERVICE_ID = 0x01 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_ENABLE_SENSOR = 0x01, + OPCODE_DISABLE_SENSOR = 0x02, + OPCODE_SET_PERIOD = 0x03 + }; + + enum { + MIN_PROTOCOL_VERSION = 1, + MAX_PROTOCOL_VERSION = 1 + }; + + virtual nsresult Send(DaemonSocketPDU* aPDU, + DaemonSocketResultHandler* aRes) = 0; + + nsresult SetProtocolVersion(unsigned long aProtocolVersion); + + // + // Commands + // + + nsresult EnableSensorCmd(int32_t aId, + GonkSensorsPollResultHandler* aRes); + + nsresult DisableSensorCmd(int32_t aId, + GonkSensorsPollResultHandler* aRes); + + nsresult SetPeriodCmd(int32_t aId, uint64_t aPeriod, + GonkSensorsPollResultHandler* aRes); + +protected: + GonkSensorsPollModule(); + virtual ~GonkSensorsPollModule(); + + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes); + +private: + + // + // Responses + // + + typedef mozilla::ipc::DaemonResultRunnable0< + GonkSensorsPollResultHandler, void> + ResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable1< + GonkSensorsPollResultHandler, void, SensorsError, SensorsError> + ErrorRunnable; + + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes); + + void EnableSensorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes); + + void DisableSensorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes); + + void SetPeriodRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + GonkSensorsPollResultHandler* aRes); + + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes); + + // + // Notifications + // + + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, SensorsError> + ErrorNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable9< + NotificationHandlerWrapper, void, int32_t, SensorsType, + float, float, float, int32_t, int32_t, SensorsTriggerMode, + SensorsDeliveryMode> + SensorDetectedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, int32_t> + SensorLostNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, int32_t, SensorsEvent, int32_t, + const SensorsEvent&> + EventNotification; + + class SensorDetectedInitOp; + class SensorLostInitOp; + class EventInitOp; + + void ErrorNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void SensorDetectedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void SensorLostNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void EventNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes); + +private: + unsigned long mProtocolVersion; +}; + +/** + * This class implements the public interface to the Sensors poll + * component. Use |SensorsInterface::GetPollInterface| to retrieve + * an instance. All methods run on the main thread. + */ +class GonkSensorsPollInterface final +{ +public: + friend class GonkSensorsInterface; + + /** + * This method sets the notification handler for poll notifications. Call + * this method immediately after registering the module. Otherwise you won't + * be able able to receive poll notifications. You may not free the handler + * class while the poll component is regsitered. + * + * @param aNotificationHandler An instance of a poll notification handler. + */ + void SetNotificationHandler( + GonkSensorsPollNotificationHandler* aNotificationHandler); + + /** + * This method sets the protocol version. You should set it to the + * value that has been returned from the backend when registering the + * Poll service. You cannot send or receive messages before setting + * the protocol version. + * + * @param aProtocolVersion + * @return NS_OK for supported versions, or an XPCOM error code otherwise. + */ + nsresult SetProtocolVersion(unsigned long aProtocolVersion); + + /** + * Enables an existing sensor. The sensor id will have been delivered in + * a SensorDetectedNotification. + * + * @param aId The sensor's id. + * @param aRes The result handler. + */ + void EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); + + /** + * Disables an existing sensor. The sensor id will have been delivered in + * a SensorDetectedNotification. + * + * @param aId The sensor's id. + * @param aRes The result handler. + */ + void DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); + + /** + * Sets the period for a sensor. The sensor id will have been delivered in + * a SensorDetectedNotification. The value for the period should be between + * the sensor's minimum and maximum period. + * + * @param aId The sensor's id. + * @param aPeriod The sensor's new period. + * @param aRes The result handler. + */ + void SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes); + + ~GonkSensorsPollInterface(); + +private: + GonkSensorsPollInterface(GonkSensorsPollModule* aModule); + + void DispatchError(GonkSensorsPollResultHandler* aRes, SensorsError aError); + void DispatchError(GonkSensorsPollResultHandler* aRes, nsresult aRv); + + GonkSensorsPollModule* mModule; +}; + +} // hal +} // namespace mozilla + +#endif // hal_gonk_GonkSensorsPollInterface_h diff --git a/hal/moz.build b/hal/moz.build index bba3f138670..2381b5628a1 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,6 +52,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', + 'gonk/GonkSensorsPollInterface.cpp', 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', From bb802cedf0ef3e5e79c68240b51d511f4eb2ddcd Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 041/160] Bug 1194721: Add interface for Gonk sensors daemon, r=gsvelto This patch adds the interface for the Gonk sensors daemon. There are only two major interfaces: connect and disconnect. The sensors daemon is started before connecting and stopped after a disconnect. Connections are race-free: we first set up a listen socket and let Gecko listen for connections. Then the daemon gets started with the socket's address as parameter. When the daemon connects to the socket, Gecko will continue the startup and signal success to the caller. --- hal/gonk/GonkSensorsInterface.cpp | 494 ++++++++++++++++++++++++++++++ hal/gonk/GonkSensorsInterface.h | 190 ++++++++++++ hal/moz.build | 1 + 3 files changed, 685 insertions(+) create mode 100644 hal/gonk/GonkSensorsInterface.cpp create mode 100644 hal/gonk/GonkSensorsInterface.h diff --git a/hal/gonk/GonkSensorsInterface.cpp b/hal/gonk/GonkSensorsInterface.cpp new file mode 100644 index 00000000000..c6c7658065b --- /dev/null +++ b/hal/gonk/GonkSensorsInterface.cpp @@ -0,0 +1,494 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 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 "GonkSensorsInterface.h" +#include "GonkSensorsPollInterface.h" +#include "GonkSensorsRegistryInterface.h" +#include "HalLog.h" +#include +#include +#include + +namespace mozilla { +namespace hal { + +using namespace mozilla::ipc; + +// +// GonkSensorsResultHandler +// + +void +GonkSensorsResultHandler::OnError(SensorsError aError) +{ + HAL_ERR("Received error code %d", static_cast(aError)); +} + +void +GonkSensorsResultHandler::Connect() +{ } + +void +GonkSensorsResultHandler::Disconnect() +{ } + +GonkSensorsResultHandler::~GonkSensorsResultHandler() +{ } + +// +// GonkSensorsNotificationHandler +// + +void +GonkSensorsNotificationHandler::BackendErrorNotification(bool aCrashed) +{ + if (aCrashed) { + HAL_ERR("Sensors backend crashed"); + } else { + HAL_ERR("Error in sensors backend"); + } +} + +GonkSensorsNotificationHandler::~GonkSensorsNotificationHandler() +{ } + +// +// GonkSensorsProtocol +// + +class GonkSensorsProtocol final + : public DaemonSocketIOConsumer + , public GonkSensorsRegistryModule + , public GonkSensorsPollModule +{ +public: + GonkSensorsProtocol(); + + void SetConnection(DaemonSocket* aConnection); + + already_AddRefed FetchResultHandler( + const DaemonSocketPDUHeader& aHeader); + + // Methods for |SensorsRegistryModule| and |SensorsPollModule| + // + + nsresult Send(DaemonSocketPDU* aPDU, + DaemonSocketResultHandler* aRes) override; + + // Methods for |DaemonSocketIOConsumer| + // + + void Handle(DaemonSocketPDU& aPDU) override; + void StoreResultHandler(const DaemonSocketPDU& aPDU) override; + +private: + void HandleRegistrySvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes); + void HandlePollSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes); + + DaemonSocket* mConnection; + nsTArray> mResultHandlerQ; +}; + +GonkSensorsProtocol::GonkSensorsProtocol() +{ } + +void +GonkSensorsProtocol::SetConnection(DaemonSocket* aConnection) +{ + mConnection = aConnection; +} + +already_AddRefed +GonkSensorsProtocol::FetchResultHandler(const DaemonSocketPDUHeader& aHeader) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + if (aHeader.mOpcode & 0x80) { + return nullptr; // Ignore notifications + } + + RefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + + return res.forget(); +} + +void +GonkSensorsProtocol::HandleRegistrySvc( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + GonkSensorsRegistryModule::HandleSvc(aHeader, aPDU, aRes); +} + +void +GonkSensorsProtocol::HandlePollSvc( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + GonkSensorsPollModule::HandleSvc(aHeader, aPDU, aRes); +} + +// |SensorsRegistryModule|, |SensorsPollModule| + +nsresult +GonkSensorsProtocol::Send(DaemonSocketPDU* aPDU, + DaemonSocketResultHandler* aRes) +{ + MOZ_ASSERT(mConnection); + MOZ_ASSERT(aPDU); + + aPDU->SetConsumer(this); + aPDU->SetResultHandler(aRes); + aPDU->UpdateHeader(); + + if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) { + HAL_ERR("Sensors socket is disconnected"); + return NS_ERROR_FAILURE; + } + + mConnection->SendSocketData(aPDU); // Forward PDU to data channel + + return NS_OK; +} + +// |DaemonSocketIOConsumer| + +void +GonkSensorsProtocol::Handle(DaemonSocketPDU& aPDU) +{ + static void (GonkSensorsProtocol::* const HandleSvc[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&, + DaemonSocketResultHandler*) = { + [GonkSensorsRegistryModule::SERVICE_ID] = + &GonkSensorsProtocol::HandleRegistrySvc, + [GonkSensorsPollModule::SERVICE_ID] = + &GonkSensorsProtocol::HandlePollSvc + }; + + DaemonSocketPDUHeader header; + + if (NS_FAILED(UnpackPDU(aPDU, header))) { + return; + } + if (!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc)) || + !HandleSvc[header.mService]) { + HAL_ERR("Sensors service %d unknown", header.mService); + return; + } + + RefPtr res = FetchResultHandler(header); + + (this->*(HandleSvc[header.mService]))(header, aPDU, res); +} + +void +GonkSensorsProtocol::StoreResultHandler(const DaemonSocketPDU& aPDU) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + mResultHandlerQ.AppendElement(aPDU.GetResultHandler()); +} + +// +// GonkSensorsInterface +// + +GonkSensorsInterface* +GonkSensorsInterface::GetInstance() +{ + static GonkSensorsInterface* sGonkSensorsInterface; + + if (sGonkSensorsInterface) { + return sGonkSensorsInterface; + } + + sGonkSensorsInterface = new GonkSensorsInterface(); + + return sGonkSensorsInterface; +} + +void +GonkSensorsInterface::SetNotificationHandler( + GonkSensorsNotificationHandler* aNotificationHandler) +{ + MOZ_ASSERT(NS_IsMainThread()); + + mNotificationHandler = aNotificationHandler; +} + +/* + * The connect procedure consists of several steps. + * + * (1) Start listening for the command channel's socket connection: We + * do this before anything else, so that we don't miss connection + * requests from the Sensors daemon. This step will create a listen + * socket. + * + * (2) Start the Sensors daemon: When the daemon starts up it will open + * a socket connection to Gecko and thus create the data channel. + * Gecko already opened the listen socket in step (1). Step (2) ends + * with the creation of the data channel. + * + * (3) Signal success to the caller. + * + * If any step fails, we roll-back the procedure and signal an error to the + * caller. + */ +void +GonkSensorsInterface::Connect(GonkSensorsNotificationHandler* aNotificationHandler, + GonkSensorsResultHandler* aRes) +{ +#define BASE_SOCKET_NAME "sensorsd" + static unsigned long POSTFIX_LENGTH = 16; + + // If we could not cleanup properly before and an old + // instance of the daemon is still running, we kill it + // here. + mozilla::hal::StopSystemService("sensorsd"); + + mNotificationHandler = aNotificationHandler; + + mResultHandlerQ.AppendElement(aRes); + + if (!mProtocol) { + mProtocol = new GonkSensorsProtocol(); + } + + if (!mListenSocket) { + mListenSocket = new ListenSocket(this, LISTEN_SOCKET); + } + + // Init, step 1: Listen for data channel... */ + + if (!mDataSocket) { + mDataSocket = new DaemonSocket(mProtocol, this, DATA_SOCKET); + } else if (mDataSocket->GetConnectionStatus() == SOCKET_CONNECTED) { + // Command channel should not be open; let's close it. + mDataSocket->Close(); + } + + // The listen socket's name is generated with a random postfix. This + // avoids naming collisions if we still have a listen socket from a + // previously failed cleanup. It also makes it hard for malicious + // external programs to capture the socket name or connect before + // the daemon can do so. If no random postfix can be generated, we + // simply use the base name as-is. + nsresult rv = DaemonSocketConnector::CreateRandomAddressString( + NS_LITERAL_CSTRING(BASE_SOCKET_NAME), POSTFIX_LENGTH, mListenSocketName); + if (NS_FAILED(rv)) { + mListenSocketName.AssignLiteral(BASE_SOCKET_NAME); + } + + rv = mListenSocket->Listen(new DaemonSocketConnector(mListenSocketName), + mDataSocket); + if (NS_FAILED(rv)) { + OnConnectError(DATA_SOCKET); + return; + } + + // The protocol implementation needs a data channel for + // sending commands to the daemon. We set it here, because + // this is the earliest time when it's available. + mProtocol->SetConnection(mDataSocket); +} + +/* + * Disconnecting is inverse to connecting. + * + * (1) Close data socket: We close the data channel and the daemon will + * will notice. Once we see the socket's disconnect, we continue with + * the cleanup. + * + * (2) Close listen socket: The listen socket is not active any longer + * and we simply close it. + * + * (3) Signal success to the caller. + * + * We don't have to stop the daemon explicitly. It will cleanup and quit + * after it noticed the closing of the data channel + * + * Rolling back half-completed cleanups is not possible. In the case of + * an error, we simply push forward and try to recover during the next + * initialization. + */ +void +GonkSensorsInterface::Disconnect(GonkSensorsResultHandler* aRes) +{ + mNotificationHandler = nullptr; + + // Cleanup, step 1: Close data channel + mDataSocket->Close(); + + mResultHandlerQ.AppendElement(aRes); +} + +GonkSensorsRegistryInterface* +GonkSensorsInterface::GetSensorsRegistryInterface() +{ + if (mRegistryInterface) { + return mRegistryInterface; + } + + mRegistryInterface = new GonkSensorsRegistryInterface(mProtocol); + + return mRegistryInterface; +} + +GonkSensorsPollInterface* +GonkSensorsInterface::GetSensorsPollInterface() +{ + if (mPollInterface) { + return mPollInterface; + } + + mPollInterface = new GonkSensorsPollInterface(mProtocol); + + return mPollInterface; +} + +GonkSensorsInterface::GonkSensorsInterface() + : mNotificationHandler(nullptr) +{ } + +GonkSensorsInterface::~GonkSensorsInterface() +{ } + +void +GonkSensorsInterface::DispatchError(GonkSensorsResultHandler* aRes, + SensorsError aError) +{ + DaemonResultRunnable1::Dispatch( + aRes, &GonkSensorsResultHandler::OnError, + ConstantInitOp1(aError)); +} + +void +GonkSensorsInterface::DispatchError( + GonkSensorsResultHandler* aRes, nsresult aRv) +{ + SensorsError error; + + if (NS_FAILED(Convert(aRv, error))) { + error = SENSORS_ERROR_FAIL; + } + DispatchError(aRes, error); +} + +// |DaemonSocketConsumer|, |ListenSocketConsumer| + +void +GonkSensorsInterface::OnConnectSuccess(int aIndex) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); + + switch (aIndex) { + case LISTEN_SOCKET: { + // Init, step 2: Start Sensors daemon + nsCString args("-a "); + args.Append(mListenSocketName); + mozilla::hal::StartSystemService("sensorsd", args.get()); + } + break; + case DATA_SOCKET: + if (!mResultHandlerQ.IsEmpty()) { + // Init, step 3: Signal success + RefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + if (res) { + res->Connect(); + } + } + break; + } +} + +void +GonkSensorsInterface::OnConnectError(int aIndex) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); + + switch (aIndex) { + case DATA_SOCKET: + // Stop daemon and close listen socket + mozilla::hal::StopSystemService("sensorsd"); + mListenSocket->Close(); + // fall through + case LISTEN_SOCKET: + if (!mResultHandlerQ.IsEmpty()) { + // Signal error to caller + RefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + if (res) { + DispatchError(res, SENSORS_ERROR_FAIL); + } + } + break; + } +} + +/* + * Disconnects can happend + * + * (a) during startup, + * (b) during regular service, or + * (c) during shutdown. + * + * For cases (a) and (c), |mResultHandlerQ| contains an element. For + * case (b) |mResultHandlerQ| will be empty. This distinguishes a crash in + * the daemon. The following procedure to recover from crashes consists of + * several steps for case (b). + * + * (1) Close listen socket. + * (2) Wait for all sockets to be disconnected and inform caller about + * the crash. + * (3) After all resources have been cleaned up, let the caller restart + * the daemon. + */ +void +GonkSensorsInterface::OnDisconnect(int aIndex) +{ + MOZ_ASSERT(NS_IsMainThread()); + + switch (aIndex) { + case DATA_SOCKET: + // Cleanup, step 2 (Recovery, step 1): Close listen socket + mListenSocket->Close(); + break; + case LISTEN_SOCKET: + // Cleanup, step 3: Signal success to caller + if (!mResultHandlerQ.IsEmpty()) { + RefPtr res = mResultHandlerQ.ElementAt(0); + mResultHandlerQ.RemoveElementAt(0); + if (res) { + res->Disconnect(); + } + } + break; + } + + /* For recovery make sure all sockets disconnected, in order to avoid + * the remaining disconnects interfere with the restart procedure. + */ + if (mNotificationHandler && mResultHandlerQ.IsEmpty()) { + if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED && + mDataSocket->GetConnectionStatus() == SOCKET_DISCONNECTED) { + // Recovery, step 2: Notify the caller to prepare the restart procedure. + mNotificationHandler->BackendErrorNotification(true); + mNotificationHandler = nullptr; + } + } +} + +} // namespace hal +} // namespace mozilla diff --git a/hal/gonk/GonkSensorsInterface.h b/hal/gonk/GonkSensorsInterface.h new file mode 100644 index 00000000000..44126ce8762 --- /dev/null +++ b/hal/gonk/GonkSensorsInterface.h @@ -0,0 +1,190 @@ +/* -*- 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/. */ + +/* + * The sensors interface gives you access to the low-level sensors code + * in a platform-independent manner. The interfaces in this file allow + * for starting an stopping the sensors driver. Specific functionality + * is implemented in sub-interfaces. + */ + +#ifndef hal_gonk_GonkSensorsInterface_h +#define hal_gonk_GonkSensorsInterface_h + +#include +#include +#include +#include "SensorsTypes.h" + +namespace mozilla { +namespace ipc { + +class DaemonSocket; +class ListenSocket; + +} +} + +namespace mozilla { +namespace hal { + +class GonkSensorsPollInterface; +class GonkSensorsProtocol; +class GonkSensorsRegistryInterface; + +/** + * This class is the result-handler interface for the Sensors + * interface. Methods always run on the main thread. + */ +class GonkSensorsResultHandler + : public mozilla::ipc::DaemonSocketResultHandler +{ +public: + + /** + * Called if a command failed. + * + * @param aError The error code. + */ + virtual void OnError(SensorsError aError); + + /** + * The callback method for |GonkSensorsInterface::Connect|. + */ + virtual void Connect(); + + /** + * The callback method for |GonkSensorsInterface::Connect|. + */ + virtual void Disconnect(); + +protected: + virtual ~GonkSensorsResultHandler(); +}; + +/** + * This is the notification-handler interface. Implement this classes + * methods to handle event and notifications from the sensors daemon. + * All methods run on the main thread. + */ +class GonkSensorsNotificationHandler +{ +public: + + /** + * This notification is called when the backend code fails + * unexpectedly. Save state in the high-level code and restart + * the driver. + * + * @param aCrash True is the sensors driver crashed. + */ + virtual void BackendErrorNotification(bool aCrashed); + +protected: + virtual ~GonkSensorsNotificationHandler(); +}; + +/** + * This class implements the public interface to the Sensors functionality + * and driver. Use |GonkSensorsInterface::GetInstance| to retrieve an instance. + * All methods run on the main thread. + */ +class GonkSensorsInterface final + : public mozilla::ipc::DaemonSocketConsumer + , public mozilla::ipc::ListenSocketConsumer +{ +public: + /** + * Returns an instance of the Sensors backend. This code can return + * |nullptr| if no Sensors backend is available. + * + * @return An instance of |GonkSensorsInterface|. + */ + static GonkSensorsInterface* GetInstance(); + + /** + * This method sets the notification handler for sensor notifications. Call + * this method immediately after retreiving an instance of the class, or you + * won't be able able to receive notifications. You may not free the handler + * class while the Sensors backend is connected. + * + * @param aNotificationHandler An instance of a notification handler. + */ + void SetNotificationHandler( + GonkSensorsNotificationHandler* aNotificationHandler); + + /** + * This method starts the Sensors backend and establishes ad connection + * with Gecko. This is a multi-step process and errors are signalled by + * |GonkSensorsNotificationHandler::BackendErrorNotification|. If you see + * this notification before the connection has been established, it's + * certainly best to assume the Sensors backend to be not evailable. + * + * @param aRes The result handler. + */ + void Connect(GonkSensorsNotificationHandler* aNotificationHandler, + GonkSensorsResultHandler* aRes); + + /** + * This method disconnects Gecko from the Sensors backend and frees + * the backend's resources. This will invalidate all interfaces and + * state. Don't use any sensors functionality without reconnecting + * first. + * + * @param aRes The result handler. + */ + void Disconnect(GonkSensorsResultHandler* aRes); + + /** + * Returns the Registry interface for the connected Sensors backend. + * + * @return An instance of the Sensors Registry interface. + */ + GonkSensorsRegistryInterface* GetSensorsRegistryInterface(); + + /** + * Returns the Poll interface for the connected Sensors backend. + * + * @return An instance of the Sensors Poll interface. + */ + GonkSensorsPollInterface* GetSensorsPollInterface(); + +private: + enum Channel { + LISTEN_SOCKET, + DATA_SOCKET + }; + + GonkSensorsInterface(); + ~GonkSensorsInterface(); + + void DispatchError(GonkSensorsResultHandler* aRes, SensorsError aError); + void DispatchError(GonkSensorsResultHandler* aRes, nsresult aRv); + + // Methods for |DaemonSocketConsumer| and |ListenSocketConsumer| + // + + void OnConnectSuccess(int aIndex) override; + void OnConnectError(int aIndex) override; + void OnDisconnect(int aIndex) override; + + nsCString mListenSocketName; + RefPtr mListenSocket; + RefPtr mDataSocket; + nsAutoPtr mProtocol; + + nsTArray > mResultHandlerQ; + + GonkSensorsNotificationHandler* mNotificationHandler; + + nsAutoPtr mRegistryInterface; + nsAutoPtr mPollInterface; +}; + +} // namespace hal +} // namespace mozilla + +#endif // hal_gonk_GonkSensorsInterface_h diff --git a/hal/moz.build b/hal/moz.build index 2381b5628a1..195cd895228 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,6 +52,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', + 'gonk/GonkSensorsInterface.cpp', 'gonk/GonkSensorsPollInterface.cpp', 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', From 3dac25b5048c4ae438cf86f375d0a175b40e5744 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 3 Feb 2016 15:16:00 +0100 Subject: [PATCH 042/160] Bug 1194721: Support Gonk sensors daemon, r=gsvelto This patch adds th state machine for supporting the Gonk sensors daemon in Gecko. The daemon gets started when the first sensor is enabled. Sensors can be enabled and disabled at will. The daemon will send events about detected sensors and sensor events. Gecko's state machine receives themand forwards them as DOM events. The old support for device sensors is still present for devices without sensorsd. A future patch will remove this code. --- hal/gonk/GonkSensor.cpp | 533 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 529 insertions(+), 4 deletions(-) diff --git a/hal/gonk/GonkSensor.cpp b/hal/gonk/GonkSensor.cpp index 9f94e9b6926..e977652d20f 100644 --- a/hal/gonk/GonkSensor.cpp +++ b/hal/gonk/GonkSensor.cpp @@ -18,10 +18,14 @@ #include #include "mozilla/DebugOnly.h" +#include "mozilla/Saturate.h" #include "base/basictypes.h" #include "base/thread.h" +#include "GonkSensorsInterface.h" +#include "GonkSensorsPollInterface.h" +#include "GonkSensorsRegistryInterface.h" #include "Hal.h" #include "HalLog.h" #include "HalSensor.h" @@ -32,6 +36,10 @@ using namespace mozilla::hal; namespace mozilla { +// +// Internal implementation +// + // The value from SensorDevice.h (Android) #define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/ // ProcessOrientation.cpp needs smaller poll rate to detect delay between @@ -285,8 +293,8 @@ SetSensorState(SensorType aSensor, bool activate) } } -void -EnableSensorNotifications(SensorType aSensor) +static void +EnableSensorNotificationsInternal(SensorType aSensor) { if (!sSensorModule) { hw_get_module(SENSORS_HARDWARE_MODULE_ID, @@ -322,8 +330,8 @@ EnableSensorNotifications(SensorType aSensor) SetSensorState(aSensor, true); } -void -DisableSensorNotifications(SensorType aSensor) +static void +DisableSensorNotificationsInternal(SensorType aSensor) { if (!sSensorModule) { return; @@ -331,5 +339,522 @@ DisableSensorNotifications(SensorType aSensor) SetSensorState(aSensor, false); } +// +// Daemon +// + +typedef detail::SaturateOp SaturateOpUint32; + +/** + * The poll notification handler receives all events about sensors and + * sensor events. + */ +class SensorsPollNotificationHandler final + : public GonkSensorsPollNotificationHandler +{ +public: + SensorsPollNotificationHandler(GonkSensorsPollInterface* aPollInterface) + : mPollInterface(aPollInterface) + { + MOZ_ASSERT(mPollInterface); + + mPollInterface->SetNotificationHandler(this); + } + + void EnableSensorsByType(SensorsType aType) + { + if (SaturateOpUint32(mClasses[aType].mActivated)++) { + return; + } + + SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); + + // Old ref-count for the sensor type was 0, so we + // activate all sensors of the type. + for (size_t i = 0; i < mSensors.Length(); ++i) { + if (mSensors[i].mType == aType && + mSensors[i].mDeliveryMode == deliveryMode) { + mPollInterface->EnableSensor(mSensors[i].mId, nullptr); + mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), + nullptr); + } + } + } + + void DisableSensorsByType(SensorsType aType) + { + if (SaturateOpUint32(mClasses[aType].mActivated)-- != 1) { + return; + } + + SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); + + // Old ref-count for the sensor type was 1, so we + // deactivate all sensors of the type. + for (size_t i = 0; i < mSensors.Length(); ++i) { + if (mSensors[i].mType == aType && + mSensors[i].mDeliveryMode == deliveryMode) { + mPollInterface->DisableSensor(mSensors[i].mId, nullptr); + } + } + } + + void ClearSensorClasses() + { + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mClasses); ++i) { + mClasses[i] = SensorsSensorClass(); + } + } + + void ClearSensors() + { + mSensors.Clear(); + } + + // Methods for SensorsPollNotificationHandler + // + + void ErrorNotification(SensorsError aError) override + { + // XXX: Bug 1206056: Try to repair some of the errors or restart cleanly. + } + + void SensorDetectedNotification(int32_t aId, SensorsType aType, + float aRange, float aResolution, + float aPower, int32_t aMinPeriod, + int32_t aMaxPeriod, + SensorsTriggerMode aTriggerMode, + SensorsDeliveryMode aDeliveryMode) override + { + auto i = FindSensorIndexById(aId); + if (i == -1) { + // Add a new sensor... + i = mSensors.Length(); + mSensors.AppendElement(SensorsSensor(aId, aType, aRange, aResolution, + aPower, aMinPeriod, aMaxPeriod, + aTriggerMode, aDeliveryMode)); + } else { + // ...or update an existing one. + mSensors[i] = SensorsSensor(aId, aType, aRange, aResolution, aPower, + aMinPeriod, aMaxPeriod, aTriggerMode, + aDeliveryMode); + } + + mClasses[aType].UpdateFromSensor(mSensors[i]); + + if (mClasses[aType].mActivated && + mSensors[i].mDeliveryMode == DefaultSensorsDeliveryMode(aType)) { + // The new sensor's type is enabled, so enable sensor. + mPollInterface->EnableSensor(aId, nullptr); + mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), + nullptr); + } + } + + void SensorLostNotification(int32_t aId) override + { + auto i = FindSensorIndexById(aId); + if (i != -1) { + mSensors.RemoveElementAt(i); + } + } + + void EventNotification(int32_t aId, const SensorsEvent& aEvent) override + { + auto i = FindSensorIndexById(aId); + if (i == -1) { + HAL_ERR("Sensor %d not registered", aId); + return; + } + + SensorData sensorData; + auto rv = CreateSensorData(aEvent, mClasses[mSensors[i].mType], + sensorData); + if (NS_FAILED(rv)) { + return; + } + + NotifySensorChange(sensorData); + } + +private: + ssize_t FindSensorIndexById(int32_t aId) const + { + for (size_t i = 0; i < mSensors.Length(); ++i) { + if (mSensors[i].mId == aId) { + return i; + } + } + return -1; + } + + uint64_t DefaultSensorPeriod(SensorsType aType) const + { + return aType == SENSORS_TYPE_ACCELEROMETER ? ACCELEROMETER_POLL_RATE + : DEFAULT_DEVICE_POLL_RATE; + } + + SensorsDeliveryMode DefaultSensorsDeliveryMode(SensorsType aType) const + { + if (aType == SENSORS_TYPE_PROXIMITY || + aType == SENSORS_TYPE_SIGNIFICANT_MOTION) { + return SENSORS_DELIVERY_MODE_IMMEDIATE; + } + return SENSORS_DELIVERY_MODE_BEST_EFFORT; + } + + SensorType HardwareSensorToHalSensor(SensorsType aType) const + { + // FIXME: bug 802004, add proper support for the magnetic-field sensor. + switch (aType) { + case SENSORS_TYPE_ORIENTATION: + return SENSOR_ORIENTATION; + case SENSORS_TYPE_ACCELEROMETER: + return SENSOR_ACCELERATION; + case SENSORS_TYPE_PROXIMITY: + return SENSOR_PROXIMITY; + case SENSORS_TYPE_LIGHT: + return SENSOR_LIGHT; + case SENSORS_TYPE_GYROSCOPE: + return SENSOR_GYROSCOPE; + case SENSORS_TYPE_LINEAR_ACCELERATION: + return SENSOR_LINEAR_ACCELERATION; + case SENSORS_TYPE_ROTATION_VECTOR: + return SENSOR_ROTATION_VECTOR; + case SENSORS_TYPE_GAME_ROTATION_VECTOR: + return SENSOR_GAME_ROTATION_VECTOR; + default: + NS_NOTREACHED("Invalid sensors type"); + } + return SENSOR_UNKNOWN; + } + + SensorAccuracyType HardwareStatusToHalAccuracy(SensorsStatus aStatus) const + { + return static_cast(aStatus - 1); + } + + nsresult CreateSensorData(const SensorsEvent& aEvent, + const SensorsSensorClass& aSensorClass, + SensorData& aSensorData) const + { + nsAutoTArray sensorValues; + + auto sensor = HardwareSensorToHalSensor(aEvent.mType); + + if (sensor == SENSOR_UNKNOWN) { + return NS_ERROR_ILLEGAL_VALUE; + } + + aSensorData.sensor() = sensor; + aSensorData.accuracy() = HardwareStatusToHalAccuracy(aEvent.mStatus); + aSensorData.timestamp() = aEvent.mTimestamp; + + if (aSensorData.sensor() == SENSOR_ORIENTATION) { + // Bug 938035: transfer HAL data for orientation sensor to meet W3C spec + // ex: HAL report alpha=90 means East but alpha=90 means West in W3C spec + sensorValues.AppendElement(360.0 - radToDeg(aEvent.mData.mFloat[0])); + sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[1])); + sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[2])); + } else if (aSensorData.sensor() == SENSOR_ACCELERATION) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + sensorValues.AppendElement(aEvent.mData.mFloat[1]); + sensorValues.AppendElement(aEvent.mData.mFloat[2]); + } else if (aSensorData.sensor() == SENSOR_PROXIMITY) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + sensorValues.AppendElement(aSensorClass.mMinValue); + sensorValues.AppendElement(aSensorClass.mMaxValue); + } else if (aSensorData.sensor() == SENSOR_LINEAR_ACCELERATION) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + sensorValues.AppendElement(aEvent.mData.mFloat[1]); + sensorValues.AppendElement(aEvent.mData.mFloat[2]); + } else if (aSensorData.sensor() == SENSOR_GYROSCOPE) { + sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[0])); + sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[1])); + sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[2])); + } else if (aSensorData.sensor() == SENSOR_LIGHT) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + } else if (aSensorData.sensor() == SENSOR_ROTATION_VECTOR) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + sensorValues.AppendElement(aEvent.mData.mFloat[1]); + sensorValues.AppendElement(aEvent.mData.mFloat[2]); + sensorValues.AppendElement(aEvent.mData.mFloat[3]); + } else if (aSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) { + sensorValues.AppendElement(aEvent.mData.mFloat[0]); + sensorValues.AppendElement(aEvent.mData.mFloat[1]); + sensorValues.AppendElement(aEvent.mData.mFloat[2]); + sensorValues.AppendElement(aEvent.mData.mFloat[3]); + } + + aSensorData.values() = sensorValues; + + return NS_OK; + } + + GonkSensorsPollInterface* mPollInterface; + nsTArray mSensors; + SensorsSensorClass mClasses[SENSORS_NUM_TYPES]; +}; + +static StaticAutoPtr sPollNotificationHandler; + +/** + * This is the notifiaction handler for the Sensors interface. If the backend + * crashes, we can restart it from here. + */ +class SensorsNotificationHandler final : public GonkSensorsNotificationHandler +{ +public: + SensorsNotificationHandler(GonkSensorsInterface* aInterface) + : mInterface(aInterface) + { + MOZ_ASSERT(mInterface); + + mInterface->SetNotificationHandler(this); + } + + void BackendErrorNotification(bool aCrashed) override + { + // XXX: Bug 1206056: restart sensorsd + } + +private: + GonkSensorsInterface* mInterface; +}; + +static StaticAutoPtr sNotificationHandler; + +/** + * |SensorsRegisterModuleResultHandler| implements the result-handler + * callback for registering the Poll service and activating the first + * sensors. If an error occures during the process, the result handler + * disconnects and closes the backend. + */ +class SensorsRegisterModuleResultHandler final + : public GonkSensorsRegistryResultHandler +{ +public: + SensorsRegisterModuleResultHandler( + uint32_t* aSensorsTypeActivated, + GonkSensorsInterface* aInterface) + : mSensorsTypeActivated(aSensorsTypeActivated) + , mInterface(aInterface) + { + MOZ_ASSERT(mSensorsTypeActivated); + MOZ_ASSERT(mInterface); + } + void OnError(SensorsError aError) override + { + GonkSensorsRegistryResultHandler::OnError(aError); // print error message + Disconnect(); // Registering failed, so close the connection completely + } + void RegisterModule(uint32_t aProtocolVersion) override + { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!sPollNotificationHandler); + + // Init, step 3: set notification handler for poll service and vice versa + auto pollInterface = mInterface->GetSensorsPollInterface(); + if (!pollInterface) { + Disconnect(); + return; + } + if (NS_FAILED(pollInterface->SetProtocolVersion(aProtocolVersion))) { + Disconnect(); + return; + } + + sPollNotificationHandler = + new SensorsPollNotificationHandler(pollInterface); + + // Init, step 4: activate sensors + for (int i = 0; i < SENSORS_NUM_TYPES; ++i) { + while (mSensorsTypeActivated[i]) { + sPollNotificationHandler->EnableSensorsByType( + static_cast(i)); + --mSensorsTypeActivated[i]; + } + } + } +public: + void Disconnect() + { + class DisconnectResultHandler final : public GonkSensorsResultHandler + { + public: + void OnError(SensorsError aError) + { + GonkSensorsResultHandler::OnError(aError); // print error message + sNotificationHandler = nullptr; + } + void Disconnect() override + { + sNotificationHandler = nullptr; + } + }; + mInterface->Disconnect(new DisconnectResultHandler()); + } +private: + uint32_t* mSensorsTypeActivated; + GonkSensorsInterface* mInterface; +}; + +/** + * |SensorsConnectResultHandler| implements the result-handler + * callback for starting the Sensors backend. + */ +class SensorsConnectResultHandler final : public GonkSensorsResultHandler +{ +public: + SensorsConnectResultHandler( + uint32_t* aSensorsTypeActivated, + GonkSensorsInterface* aInterface) + : mSensorsTypeActivated(aSensorsTypeActivated) + , mInterface(aInterface) + { + MOZ_ASSERT(mSensorsTypeActivated); + MOZ_ASSERT(mInterface); + } + void OnError(SensorsError aError) override + { + GonkSensorsResultHandler::OnError(aError); // print error message + sNotificationHandler = nullptr; + } + void Connect() override + { + MOZ_ASSERT(NS_IsMainThread()); + + // Init, step 2: register poll service + auto registryInterface = mInterface->GetSensorsRegistryInterface(); + if (!registryInterface) { + return; + } + registryInterface->RegisterModule( + GonkSensorsPollModule::SERVICE_ID, + new SensorsRegisterModuleResultHandler(mSensorsTypeActivated, + mInterface)); + } +private: + uint32_t* mSensorsTypeActivated; + GonkSensorsInterface* mInterface; +}; + +static uint32_t sSensorsTypeActivated[SENSORS_NUM_TYPES]; + +static const SensorsType sSensorsType[] = { + [SENSOR_ORIENTATION] = SENSORS_TYPE_ORIENTATION, + [SENSOR_ACCELERATION] = SENSORS_TYPE_ACCELEROMETER, + [SENSOR_PROXIMITY] = SENSORS_TYPE_PROXIMITY, + [SENSOR_LINEAR_ACCELERATION] = SENSORS_TYPE_LINEAR_ACCELERATION, + [SENSOR_GYROSCOPE] = SENSORS_TYPE_GYROSCOPE, + [SENSOR_LIGHT] = SENSORS_TYPE_LIGHT, + [SENSOR_ROTATION_VECTOR] = SENSORS_TYPE_ROTATION_VECTOR, + [SENSOR_GAME_ROTATION_VECTOR] = SENSORS_TYPE_GAME_ROTATION_VECTOR +}; + +void +EnableSensorNotificationsDaemon(SensorType aSensor) +{ + if ((aSensor < 0) || + (aSensor > static_cast(MOZ_ARRAY_LENGTH(sSensorsType)))) { + HAL_ERR("Sensor type %d not known", aSensor); + return; // Unsupported sensor type + } + + auto interface = GonkSensorsInterface::GetInstance(); + if (!interface) { + return; + } + + if (sPollNotificationHandler) { + // Everythings already up and running; enable sensor type. + sPollNotificationHandler->EnableSensorsByType(sSensorsType[aSensor]); + return; + } + + ++SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); + + if (sNotificationHandler) { + // We are in the middle of a pending start up; nothing else to do. + return; + } + + // Start up + + MOZ_ASSERT(!sPollNotificationHandler); + MOZ_ASSERT(!sNotificationHandler); + + sNotificationHandler = new SensorsNotificationHandler(interface); + + // Init, step 1: connect to Sensors backend + interface->Connect( + sNotificationHandler, + new SensorsConnectResultHandler(sSensorsTypeActivated, interface)); +} + +void +DisableSensorNotificationsDaemon(SensorType aSensor) +{ + if ((aSensor < 0) || + (aSensor > static_cast(MOZ_ARRAY_LENGTH(sSensorsType)))) { + HAL_ERR("Sensor type %d not known", aSensor); + return; // Unsupported sensor type + } + + if (sPollNotificationHandler) { + // Everthings up and running; disable sensors type + sPollNotificationHandler->DisableSensorsByType(sSensorsType[aSensor]); + return; + } + + // We might be in the middle of a startup; decrement type's ref-counter. + --SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); + + // TODO: stop sensorsd if all sensors are disabled +} + +// +// Public interface +// + +// TODO: Remove in-Gecko sensors code. Until all devices' base +// images come with sensorsd installed, we have to support the +// in-Gecko implementation as well. So we test for the existance +// of the binary. If it's there, we use it. Otherwise we run the +// old code. +static bool +HasDaemon() +{ + static bool tested; + static bool hasDaemon; + + if (MOZ_UNLIKELY(!tested)) { + hasDaemon = !access("/system/bin/sensorsd", X_OK); + tested = true; + } + + return hasDaemon; +} + +void +EnableSensorNotifications(SensorType aSensor) +{ + if (HasDaemon()) { + EnableSensorNotificationsDaemon(aSensor); + } else { + EnableSensorNotificationsInternal(aSensor); + } +} + +void +DisableSensorNotifications(SensorType aSensor) +{ + if (HasDaemon()) { + DisableSensorNotificationsDaemon(aSensor); + } else { + DisableSensorNotificationsInternal(aSensor); + } +} + } // hal_impl } // mozilla From 6394ca3d5587b9b316c061a44bc58b3e00ec2358 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 2 Feb 2016 14:15:37 -0500 Subject: [PATCH 043/160] Bug 1245269 - Make clang-plugin build with clang 3.8 and newer; r=mystor --- build/clang-plugin/clang-plugin.cpp | 33 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 9d442bdfc94..778e4e49548 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -28,6 +28,17 @@ typedef std::unique_ptr ASTConsumerPtr; typedef ASTConsumer *ASTConsumerPtr; #endif +#if CLANG_VERSION_FULL < 308 +// In clang 3.8, a number of AST matchers were renamed to better match the +// respective AST node. We use the new names, and #define them to the old +// ones for compatibility with older versions. +#define cxxConstructExpr constructExpr +#define cxxConstructorDecl constructorDecl +#define cxxMethodDecl methodDecl +#define cxxNewExpr newExpr +#define cxxRecordDecl recordDecl +#endif + namespace { using namespace clang::ast_matchers; @@ -893,7 +904,7 @@ bool isPlacementNew(const CXXNewExpr *Expr) { DiagnosticsMatcher::DiagnosticsMatcher() { astMatcher.addMatcher(varDecl().bind("node"), &scopeChecker); - astMatcher.addMatcher(newExpr().bind("node"), &scopeChecker); + astMatcher.addMatcher(cxxNewExpr().bind("node"), &scopeChecker); astMatcher.addMatcher(materializeTemporaryExpr().bind("node"), &scopeChecker); astMatcher.addMatcher( callExpr(callee(functionDecl(heapAllocator()))).bind("node"), @@ -919,7 +930,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("call"), &arithmeticArgChecker); astMatcher.addMatcher( - constructExpr( + cxxConstructExpr( allOf(hasDeclaration(noArithmeticExprInArgs()), anyOf(hasDescendant( binaryOperator( @@ -938,7 +949,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("call"), &arithmeticArgChecker); - astMatcher.addMatcher(recordDecl(hasTrivialCtorDtor()).bind("node"), + astMatcher.addMatcher(cxxRecordDecl(hasTrivialCtorDtor()).bind("node"), &trivialCtorDtorChecker); astMatcher.addMatcher( @@ -981,12 +992,12 @@ DiagnosticsMatcher::DiagnosticsMatcher() { // conversions as 'operator _Bool', but newer clang versions recognize these // as 'operator bool'. astMatcher.addMatcher( - methodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool"))) + cxxMethodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool"))) .bind("node"), &explicitOperatorBoolChecker); astMatcher.addMatcher( - recordDecl(allOf(decl().bind("decl"), hasRefCntMember())), + cxxRecordDecl(allOf(decl().bind("decl"), hasRefCntMember())), &noDuplicateRefCntMemberChecker); astMatcher.addMatcher( @@ -1005,20 +1016,20 @@ DiagnosticsMatcher::DiagnosticsMatcher() { &nonMemMovableChecker); astMatcher.addMatcher( - constructorDecl(isInterestingImplicitCtor(), - ofClass(allOf(isConcreteClass(), decl().bind("class"))), - unless(isMarkedImplicit())) + cxxConstructorDecl(isInterestingImplicitCtor(), + ofClass(allOf(isConcreteClass(), decl().bind("class"))), + unless(isMarkedImplicit())) .bind("ctor"), &explicitImplicitChecker); astMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"), &noAutoTypeChecker); - astMatcher.addMatcher(constructorDecl(isExplicitMoveConstructor()).bind("node"), + astMatcher.addMatcher(cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), &noExplicitMoveConstructorChecker); - astMatcher.addMatcher(constructExpr(hasDeclaration( - constructorDecl( + astMatcher.addMatcher(cxxConstructExpr(hasDeclaration( + cxxConstructorDecl( isCompilerProvidedCopyConstructor(), ofClass(hasRefCntMember())))).bind("node"), &refCountedCopyConstructorChecker); From e8f6b95f41f80bb9d8d74ee84f5d520f7299e4c7 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 2 Feb 2016 16:37:10 -0500 Subject: [PATCH 044/160] Bug 1245275 - Fix "Name is not a simple identifier" assertions in clang-plugin; r=mystor Some methods may not have names. NamedDecl::getName() already returns an empty string for those, but it also asserts the consumer is asking for something that makes sense. --- build/clang-plugin/clang-plugin.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 778e4e49548..44776c63ab4 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -435,6 +435,8 @@ public: bool overridden = false; for (CXXRecordDecl::method_iterator M = d->method_begin(); !overridden && M != d->method_end(); ++M) { + if (!M->getIdentifier() || !(*it)->getIdentifier()) + continue; // The way that Clang checks if a method M overrides its parent method // is if the method has the same name but would not overload. if (M->getName() == (*it)->getName() && @@ -509,6 +511,8 @@ bool classHasAddRefRelease(const CXXRecordDecl *D) { bool seenRelease = false; for (CXXRecordDecl::method_iterator method = D->method_begin(); method != D->method_end(); ++method) { + if (!method->getIdentifier()) + continue; const auto &name = method->getName(); if (name == "AddRef") { seenAddRef = true; From bc91b3836f44d045ecabb9d6d72093a9443eca17 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Wed, 3 Feb 2016 09:18:48 -0500 Subject: [PATCH 045/160] Reformat clang-plugin.cpp using clang-format, no bug --- build/clang-plugin/clang-plugin.cpp | 87 +++++++++++++++-------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 44776c63ab4..e050b87c82a 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -5,8 +5,8 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" -#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendPluginRegistry.h" @@ -990,7 +990,8 @@ DiagnosticsMatcher::DiagnosticsMatcher() { // lambda, where the declaration they reference is not inside the lambda. // This excludes arguments and local variables, leaving only captured // variables. - astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker); + astMatcher.addMatcher(lambdaExpr().bind("lambda"), + &refCountedInsideLambdaChecker); // Older clang versions such as the ones used on the infra recognize these // conversions as 'operator _Bool', but newer clang versions recognize these @@ -1019,24 +1020,26 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("specialization"), &nonMemMovableChecker); - astMatcher.addMatcher( - cxxConstructorDecl(isInterestingImplicitCtor(), - ofClass(allOf(isConcreteClass(), decl().bind("class"))), - unless(isMarkedImplicit())) - .bind("ctor"), - &explicitImplicitChecker); + astMatcher.addMatcher(cxxConstructorDecl(isInterestingImplicitCtor(), + ofClass(allOf(isConcreteClass(), + decl().bind("class"))), + unless(isMarkedImplicit())) + .bind("ctor"), + &explicitImplicitChecker); astMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"), &noAutoTypeChecker); - astMatcher.addMatcher(cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), - &noExplicitMoveConstructorChecker); + astMatcher.addMatcher( + cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), + &noExplicitMoveConstructorChecker); - astMatcher.addMatcher(cxxConstructExpr(hasDeclaration( - cxxConstructorDecl( - isCompilerProvidedCopyConstructor(), - ofClass(hasRefCntMember())))).bind("node"), - &refCountedCopyConstructorChecker); + astMatcher.addMatcher( + cxxConstructExpr( + hasDeclaration(cxxConstructorDecl(isCompilerProvidedCopyConstructor(), + ofClass(hasRefCntMember())))) + .bind("node"), + &refCountedCopyConstructorChecker); } // These enum variants determine whether an allocation has occured in the code. @@ -1051,7 +1054,8 @@ enum AllocationVariety { // XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it // probably will be used at some point in the future, in order to produce better // error messages. -typedef DenseMap AutomaticTemporaryMap; +typedef DenseMap + AutomaticTemporaryMap; AutomaticTemporaryMap AutomaticTemporaries; void DiagnosticsMatcher::ScopeChecker::run( @@ -1063,9 +1067,11 @@ void DiagnosticsMatcher::ScopeChecker::run( SourceLocation Loc; QualType T; - if (const ParmVarDecl *D = Result.Nodes.getNodeAs("parm_vardecl")) { + if (const ParmVarDecl *D = + Result.Nodes.getNodeAs("parm_vardecl")) { if (const Expr *Default = D->getDefaultArg()) { - if (const MaterializeTemporaryExpr *E = dyn_cast(Default)) { + if (const MaterializeTemporaryExpr *E = + dyn_cast(Default)) { // We have just found a ParmVarDecl which has, as its default argument, // a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as // automatic, by adding it to the AutomaticTemporaryMap. @@ -1104,18 +1110,17 @@ void DiagnosticsMatcher::ScopeChecker::run( // XXX We maybe should mark these lifetimes as being due to a temporary // which has had its lifetime extended, to improve the error messages. switch (E->getStorageDuration()) { - case SD_FullExpression: - { - // Check if this temporary is allocated as a default argument! - // if it is, we want to pretend that it is automatic. - AutomaticTemporaryMap::iterator AutomaticTemporary = AutomaticTemporaries.find(E); - if (AutomaticTemporary != AutomaticTemporaries.end()) { - Variety = AV_Automatic; - } else { - Variety = AV_Temporary; - } + case SD_FullExpression: { + // Check if this temporary is allocated as a default argument! + // if it is, we want to pretend that it is automatic. + AutomaticTemporaryMap::iterator AutomaticTemporary = + AutomaticTemporaries.find(E); + if (AutomaticTemporary != AutomaticTemporaries.end()) { + Variety = AV_Automatic; + } else { + Variety = AV_Temporary; } - break; + } break; case SD_Automatic: Variety = AV_Automatic; break; @@ -1180,8 +1185,8 @@ void DiagnosticsMatcher::ScopeChecker::run( case AV_Temporary: GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID); HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID); - NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc, - NonTemporaryID, TemporaryNoteID); + NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc, NonTemporaryID, + TemporaryNoteID); break; case AV_Heap: @@ -1291,8 +1296,8 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run( QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType(); if (!Pointee.isNull() && isClassRefCounted(Pointee)) { - Diag.Report(Capture.getLocation(), errorID) - << Capture.getCapturedVar() << Pointee; + Diag.Report(Capture.getLocation(), errorID) << Capture.getCapturedVar() + << Pointee; Diag.Report(Capture.getLocation(), noteID); } } @@ -1460,7 +1465,7 @@ void DiagnosticsMatcher::NoExplicitMoveConstructorChecker::run( // Everything we needed to know was checked in the matcher - we just report // the error here const CXXConstructorDecl *D = - Result.Nodes.getNodeAs("node"); + Result.Nodes.getNodeAs("node"); Diag.Report(D->getLocation(), ErrorID); } @@ -1472,16 +1477,16 @@ void DiagnosticsMatcher::RefCountedCopyConstructorChecker::run( DiagnosticIDs::Error, "Invalid use of compiler-provided copy constructor " "on refcounted type"); unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, "The default copy constructor also copies the " - "default mRefCnt property, leading to reference " - "count imbalance issues. Please provide your own " - "copy constructor which only copies the fields which " - "need to be copied"); + DiagnosticIDs::Note, + "The default copy constructor also copies the " + "default mRefCnt property, leading to reference " + "count imbalance issues. Please provide your own " + "copy constructor which only copies the fields which " + "need to be copied"); // Everything we needed to know was checked in the matcher - we just report // the error here - const CXXConstructExpr *E = - Result.Nodes.getNodeAs("node"); + const CXXConstructExpr *E = Result.Nodes.getNodeAs("node"); Diag.Report(E->getLocation(), ErrorID); Diag.Report(E->getLocation(), NoteID); From 27ea6f1a48e6cbb452acfcc3a1f27ebbcc78551b Mon Sep 17 00:00:00 2001 From: Sourabh Date: Wed, 3 Feb 2016 09:31:35 -0500 Subject: [PATCH 046/160] Bug 1241991 - Switch mTreeLock from a Monitor to a Mutex. r=kats --- gfx/layers/apz/src/APZCTreeManager.cpp | 26 +++++++++++++------------- gfx/layers/apz/src/APZCTreeManager.h | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index ea23b50c0f5..c28fc904b81 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -137,7 +137,7 @@ APZCTreeManager::UpdateHitTestingTree(CompositorParent* aCompositor, { APZThreadUtils::AssertOnCompositorThread(); - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // For testing purposes, we log some data to the APZTestData associated with // the layers id that originated this update. @@ -1186,7 +1186,7 @@ void APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, const Maybe& aConstraints) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC @@ -1245,7 +1245,7 @@ APZCTreeManager::FlushRepaintsToClearScreenToGeckoTransform() // matched APZCs is the same. It is simplest to ensure that by flushing the // pending repaint requests, which makes all of the untransforms empty (and // therefore equal). - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); mTreeLock.AssertCurrentThreadOwns(); ForEachNode(mRootNode.get(), @@ -1270,7 +1270,7 @@ APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid) void APZCTreeManager::AdjustScrollForSurfaceShift(const ScreenPoint& aShift) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr apzc = FindRootContentOrRootApzc(); if (apzc) { apzc->AdjustScrollForSurfaceShift(aShift); @@ -1286,7 +1286,7 @@ APZCTreeManager::ClearTree() APZThreadUtils::RunOnControllerThread(NewRunnableMethod( mInputQueue.get(), &InputQueue::Clear)); - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // Collect the nodes into a list, and then destroy each one. // We can't destroy them as we collect them, because ForEachNode() @@ -1308,7 +1308,7 @@ APZCTreeManager::ClearTree() RefPtr APZCTreeManager::GetRootNode() const { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); return mRootNode; } @@ -1500,7 +1500,7 @@ APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint) already_AddRefed APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr node = GetTargetNode(aGuid, nullptr); MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC RefPtr apzc = node ? node->GetApzc() : nullptr; @@ -1519,7 +1519,7 @@ APZCTreeManager::GetTargetNode(const ScrollableLayerGuid& aGuid, already_AddRefed APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint, HitTestResult* aOutHitResult) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); HitTestResult hitResult = HitNothing; ParentLayerPoint point = ViewAs(aPoint, PixelCastJustification::ScreenIsParentLayerForRoot); @@ -1552,7 +1552,7 @@ APZCTreeManager::BuildOverscrollHandoffChain(const RefPtr APZCTreeManager::FindScrollNode(const AsyncDragMetrics& aDragMetrics) { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); return DepthFirstSearch(mRootNode.get(), [&aDragMetrics](HitTestingTreeNode* aNode) { @@ -1877,7 +1877,7 @@ ScreenToParentLayerMatrix4x4 APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -1918,7 +1918,7 @@ ParentLayerToScreenMatrix4x4 APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const { Matrix4x4 result; - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); // The comments below assume there is a chain of layers L..R with L and P having APZC instances as // explained in the comment above. This function is called with aApzc at L, and the loop @@ -1947,7 +1947,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co already_AddRefed APZCTreeManager::GetMultitouchTarget(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2) const { - MonitorAutoLock lock(mTreeLock); + MutexAutoLock lock(mTreeLock); RefPtr apzc; // For now, we only ever want to do pinching on the root-content APZC for // a given layers id. diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 56e70ead86a..d4dffe0fc85 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -17,7 +17,7 @@ #include "mozilla/gfx/Matrix.h" // for Matrix4x4 #include "mozilla/layers/APZUtils.h" // for HitTestResult #include "mozilla/layers/TouchCounter.h"// for TouchCounter -#include "mozilla/Monitor.h" // for Monitor +#include "mozilla/Mutex.h" // for Mutex #include "mozilla/TimeStamp.h" // for mozilla::TimeStamp #include "mozilla/Vector.h" // for mozilla::Vector #include "nsAutoPtr.h" // for nsRefPtr @@ -534,7 +534,7 @@ private: * is considered part of the APZC tree management state. * Finally, the lock needs to be held when accessing mZoomConstraints. * IMPORTANT: See the note about lock ordering at the top of this file. */ - mutable mozilla::Monitor mTreeLock; + mutable mozilla::Mutex mTreeLock; RefPtr mRootNode; /* Holds the zoom constraints for scrollable layers, as determined by the * the main-thread gecko code. */ From 57ccf7668a3e2d1678c0b13ca2e51ab365afd948 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:46:46 +0100 Subject: [PATCH 047/160] Backed out changeset 70ca2c2cb7d9 --- build/clang-plugin/clang-plugin.cpp | 87 ++++++++++++++--------------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index e050b87c82a..44776c63ab4 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -5,8 +5,8 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/Version.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendPluginRegistry.h" @@ -990,8 +990,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() { // lambda, where the declaration they reference is not inside the lambda. // This excludes arguments and local variables, leaving only captured // variables. - astMatcher.addMatcher(lambdaExpr().bind("lambda"), - &refCountedInsideLambdaChecker); + astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker); // Older clang versions such as the ones used on the infra recognize these // conversions as 'operator _Bool', but newer clang versions recognize these @@ -1020,26 +1019,24 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("specialization"), &nonMemMovableChecker); - astMatcher.addMatcher(cxxConstructorDecl(isInterestingImplicitCtor(), - ofClass(allOf(isConcreteClass(), - decl().bind("class"))), - unless(isMarkedImplicit())) - .bind("ctor"), - &explicitImplicitChecker); + astMatcher.addMatcher( + cxxConstructorDecl(isInterestingImplicitCtor(), + ofClass(allOf(isConcreteClass(), decl().bind("class"))), + unless(isMarkedImplicit())) + .bind("ctor"), + &explicitImplicitChecker); astMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"), &noAutoTypeChecker); - astMatcher.addMatcher( - cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), - &noExplicitMoveConstructorChecker); + astMatcher.addMatcher(cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), + &noExplicitMoveConstructorChecker); - astMatcher.addMatcher( - cxxConstructExpr( - hasDeclaration(cxxConstructorDecl(isCompilerProvidedCopyConstructor(), - ofClass(hasRefCntMember())))) - .bind("node"), - &refCountedCopyConstructorChecker); + astMatcher.addMatcher(cxxConstructExpr(hasDeclaration( + cxxConstructorDecl( + isCompilerProvidedCopyConstructor(), + ofClass(hasRefCntMember())))).bind("node"), + &refCountedCopyConstructorChecker); } // These enum variants determine whether an allocation has occured in the code. @@ -1054,8 +1051,7 @@ enum AllocationVariety { // XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it // probably will be used at some point in the future, in order to produce better // error messages. -typedef DenseMap - AutomaticTemporaryMap; +typedef DenseMap AutomaticTemporaryMap; AutomaticTemporaryMap AutomaticTemporaries; void DiagnosticsMatcher::ScopeChecker::run( @@ -1067,11 +1063,9 @@ void DiagnosticsMatcher::ScopeChecker::run( SourceLocation Loc; QualType T; - if (const ParmVarDecl *D = - Result.Nodes.getNodeAs("parm_vardecl")) { + if (const ParmVarDecl *D = Result.Nodes.getNodeAs("parm_vardecl")) { if (const Expr *Default = D->getDefaultArg()) { - if (const MaterializeTemporaryExpr *E = - dyn_cast(Default)) { + if (const MaterializeTemporaryExpr *E = dyn_cast(Default)) { // We have just found a ParmVarDecl which has, as its default argument, // a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as // automatic, by adding it to the AutomaticTemporaryMap. @@ -1110,17 +1104,18 @@ void DiagnosticsMatcher::ScopeChecker::run( // XXX We maybe should mark these lifetimes as being due to a temporary // which has had its lifetime extended, to improve the error messages. switch (E->getStorageDuration()) { - case SD_FullExpression: { - // Check if this temporary is allocated as a default argument! - // if it is, we want to pretend that it is automatic. - AutomaticTemporaryMap::iterator AutomaticTemporary = - AutomaticTemporaries.find(E); - if (AutomaticTemporary != AutomaticTemporaries.end()) { - Variety = AV_Automatic; - } else { - Variety = AV_Temporary; + case SD_FullExpression: + { + // Check if this temporary is allocated as a default argument! + // if it is, we want to pretend that it is automatic. + AutomaticTemporaryMap::iterator AutomaticTemporary = AutomaticTemporaries.find(E); + if (AutomaticTemporary != AutomaticTemporaries.end()) { + Variety = AV_Automatic; + } else { + Variety = AV_Temporary; + } } - } break; + break; case SD_Automatic: Variety = AV_Automatic; break; @@ -1185,8 +1180,8 @@ void DiagnosticsMatcher::ScopeChecker::run( case AV_Temporary: GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID); HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID); - NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc, NonTemporaryID, - TemporaryNoteID); + NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc, + NonTemporaryID, TemporaryNoteID); break; case AV_Heap: @@ -1296,8 +1291,8 @@ void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run( QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType(); if (!Pointee.isNull() && isClassRefCounted(Pointee)) { - Diag.Report(Capture.getLocation(), errorID) << Capture.getCapturedVar() - << Pointee; + Diag.Report(Capture.getLocation(), errorID) + << Capture.getCapturedVar() << Pointee; Diag.Report(Capture.getLocation(), noteID); } } @@ -1465,7 +1460,7 @@ void DiagnosticsMatcher::NoExplicitMoveConstructorChecker::run( // Everything we needed to know was checked in the matcher - we just report // the error here const CXXConstructorDecl *D = - Result.Nodes.getNodeAs("node"); + Result.Nodes.getNodeAs("node"); Diag.Report(D->getLocation(), ErrorID); } @@ -1477,16 +1472,16 @@ void DiagnosticsMatcher::RefCountedCopyConstructorChecker::run( DiagnosticIDs::Error, "Invalid use of compiler-provided copy constructor " "on refcounted type"); unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID( - DiagnosticIDs::Note, - "The default copy constructor also copies the " - "default mRefCnt property, leading to reference " - "count imbalance issues. Please provide your own " - "copy constructor which only copies the fields which " - "need to be copied"); + DiagnosticIDs::Note, "The default copy constructor also copies the " + "default mRefCnt property, leading to reference " + "count imbalance issues. Please provide your own " + "copy constructor which only copies the fields which " + "need to be copied"); // Everything we needed to know was checked in the matcher - we just report // the error here - const CXXConstructExpr *E = Result.Nodes.getNodeAs("node"); + const CXXConstructExpr *E = + Result.Nodes.getNodeAs("node"); Diag.Report(E->getLocation(), ErrorID); Diag.Report(E->getLocation(), NoteID); From 1a14b6a4f856c78998864a51b43d0704031fbd4b Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:46:47 +0100 Subject: [PATCH 048/160] Backed out changeset ad3e81d12128 (bug 1245275) --- build/clang-plugin/clang-plugin.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 44776c63ab4..778e4e49548 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -435,8 +435,6 @@ public: bool overridden = false; for (CXXRecordDecl::method_iterator M = d->method_begin(); !overridden && M != d->method_end(); ++M) { - if (!M->getIdentifier() || !(*it)->getIdentifier()) - continue; // The way that Clang checks if a method M overrides its parent method // is if the method has the same name but would not overload. if (M->getName() == (*it)->getName() && @@ -511,8 +509,6 @@ bool classHasAddRefRelease(const CXXRecordDecl *D) { bool seenRelease = false; for (CXXRecordDecl::method_iterator method = D->method_begin(); method != D->method_end(); ++method) { - if (!method->getIdentifier()) - continue; const auto &name = method->getName(); if (name == "AddRef") { seenAddRef = true; From 17f3703246a81e2361e0a4c4523eb435e2e51be9 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 15:47:02 +0100 Subject: [PATCH 049/160] Backed out changeset b542e3e8bb79 (bug 1245269) for bustage on a CLOSED TREE --- build/clang-plugin/clang-plugin.cpp | 33 ++++++++++------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/build/clang-plugin/clang-plugin.cpp b/build/clang-plugin/clang-plugin.cpp index 778e4e49548..9d442bdfc94 100644 --- a/build/clang-plugin/clang-plugin.cpp +++ b/build/clang-plugin/clang-plugin.cpp @@ -28,17 +28,6 @@ typedef std::unique_ptr ASTConsumerPtr; typedef ASTConsumer *ASTConsumerPtr; #endif -#if CLANG_VERSION_FULL < 308 -// In clang 3.8, a number of AST matchers were renamed to better match the -// respective AST node. We use the new names, and #define them to the old -// ones for compatibility with older versions. -#define cxxConstructExpr constructExpr -#define cxxConstructorDecl constructorDecl -#define cxxMethodDecl methodDecl -#define cxxNewExpr newExpr -#define cxxRecordDecl recordDecl -#endif - namespace { using namespace clang::ast_matchers; @@ -904,7 +893,7 @@ bool isPlacementNew(const CXXNewExpr *Expr) { DiagnosticsMatcher::DiagnosticsMatcher() { astMatcher.addMatcher(varDecl().bind("node"), &scopeChecker); - astMatcher.addMatcher(cxxNewExpr().bind("node"), &scopeChecker); + astMatcher.addMatcher(newExpr().bind("node"), &scopeChecker); astMatcher.addMatcher(materializeTemporaryExpr().bind("node"), &scopeChecker); astMatcher.addMatcher( callExpr(callee(functionDecl(heapAllocator()))).bind("node"), @@ -930,7 +919,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("call"), &arithmeticArgChecker); astMatcher.addMatcher( - cxxConstructExpr( + constructExpr( allOf(hasDeclaration(noArithmeticExprInArgs()), anyOf(hasDescendant( binaryOperator( @@ -949,7 +938,7 @@ DiagnosticsMatcher::DiagnosticsMatcher() { .bind("call"), &arithmeticArgChecker); - astMatcher.addMatcher(cxxRecordDecl(hasTrivialCtorDtor()).bind("node"), + astMatcher.addMatcher(recordDecl(hasTrivialCtorDtor()).bind("node"), &trivialCtorDtorChecker); astMatcher.addMatcher( @@ -992,12 +981,12 @@ DiagnosticsMatcher::DiagnosticsMatcher() { // conversions as 'operator _Bool', but newer clang versions recognize these // as 'operator bool'. astMatcher.addMatcher( - cxxMethodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool"))) + methodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool"))) .bind("node"), &explicitOperatorBoolChecker); astMatcher.addMatcher( - cxxRecordDecl(allOf(decl().bind("decl"), hasRefCntMember())), + recordDecl(allOf(decl().bind("decl"), hasRefCntMember())), &noDuplicateRefCntMemberChecker); astMatcher.addMatcher( @@ -1016,20 +1005,20 @@ DiagnosticsMatcher::DiagnosticsMatcher() { &nonMemMovableChecker); astMatcher.addMatcher( - cxxConstructorDecl(isInterestingImplicitCtor(), - ofClass(allOf(isConcreteClass(), decl().bind("class"))), - unless(isMarkedImplicit())) + constructorDecl(isInterestingImplicitCtor(), + ofClass(allOf(isConcreteClass(), decl().bind("class"))), + unless(isMarkedImplicit())) .bind("ctor"), &explicitImplicitChecker); astMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"), &noAutoTypeChecker); - astMatcher.addMatcher(cxxConstructorDecl(isExplicitMoveConstructor()).bind("node"), + astMatcher.addMatcher(constructorDecl(isExplicitMoveConstructor()).bind("node"), &noExplicitMoveConstructorChecker); - astMatcher.addMatcher(cxxConstructExpr(hasDeclaration( - cxxConstructorDecl( + astMatcher.addMatcher(constructExpr(hasDeclaration( + constructorDecl( isCompilerProvidedCopyConstructor(), ofClass(hasRefCntMember())))).bind("node"), &refCountedCopyConstructorChecker); From 55d6875b07b6a0885e833b970560407e08d76619 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:20 +0100 Subject: [PATCH 050/160] Backed out changeset 8adcb4e83cf4 (bug 1194721) --- hal/gonk/GonkSensor.cpp | 533 +--------------------------------------- 1 file changed, 4 insertions(+), 529 deletions(-) diff --git a/hal/gonk/GonkSensor.cpp b/hal/gonk/GonkSensor.cpp index e977652d20f..9f94e9b6926 100644 --- a/hal/gonk/GonkSensor.cpp +++ b/hal/gonk/GonkSensor.cpp @@ -18,14 +18,10 @@ #include #include "mozilla/DebugOnly.h" -#include "mozilla/Saturate.h" #include "base/basictypes.h" #include "base/thread.h" -#include "GonkSensorsInterface.h" -#include "GonkSensorsPollInterface.h" -#include "GonkSensorsRegistryInterface.h" #include "Hal.h" #include "HalLog.h" #include "HalSensor.h" @@ -36,10 +32,6 @@ using namespace mozilla::hal; namespace mozilla { -// -// Internal implementation -// - // The value from SensorDevice.h (Android) #define DEFAULT_DEVICE_POLL_RATE 200000000 /*200ms*/ // ProcessOrientation.cpp needs smaller poll rate to detect delay between @@ -293,8 +285,8 @@ SetSensorState(SensorType aSensor, bool activate) } } -static void -EnableSensorNotificationsInternal(SensorType aSensor) +void +EnableSensorNotifications(SensorType aSensor) { if (!sSensorModule) { hw_get_module(SENSORS_HARDWARE_MODULE_ID, @@ -330,8 +322,8 @@ EnableSensorNotificationsInternal(SensorType aSensor) SetSensorState(aSensor, true); } -static void -DisableSensorNotificationsInternal(SensorType aSensor) +void +DisableSensorNotifications(SensorType aSensor) { if (!sSensorModule) { return; @@ -339,522 +331,5 @@ DisableSensorNotificationsInternal(SensorType aSensor) SetSensorState(aSensor, false); } -// -// Daemon -// - -typedef detail::SaturateOp SaturateOpUint32; - -/** - * The poll notification handler receives all events about sensors and - * sensor events. - */ -class SensorsPollNotificationHandler final - : public GonkSensorsPollNotificationHandler -{ -public: - SensorsPollNotificationHandler(GonkSensorsPollInterface* aPollInterface) - : mPollInterface(aPollInterface) - { - MOZ_ASSERT(mPollInterface); - - mPollInterface->SetNotificationHandler(this); - } - - void EnableSensorsByType(SensorsType aType) - { - if (SaturateOpUint32(mClasses[aType].mActivated)++) { - return; - } - - SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); - - // Old ref-count for the sensor type was 0, so we - // activate all sensors of the type. - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mType == aType && - mSensors[i].mDeliveryMode == deliveryMode) { - mPollInterface->EnableSensor(mSensors[i].mId, nullptr); - mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), - nullptr); - } - } - } - - void DisableSensorsByType(SensorsType aType) - { - if (SaturateOpUint32(mClasses[aType].mActivated)-- != 1) { - return; - } - - SensorsDeliveryMode deliveryMode = DefaultSensorsDeliveryMode(aType); - - // Old ref-count for the sensor type was 1, so we - // deactivate all sensors of the type. - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mType == aType && - mSensors[i].mDeliveryMode == deliveryMode) { - mPollInterface->DisableSensor(mSensors[i].mId, nullptr); - } - } - } - - void ClearSensorClasses() - { - for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mClasses); ++i) { - mClasses[i] = SensorsSensorClass(); - } - } - - void ClearSensors() - { - mSensors.Clear(); - } - - // Methods for SensorsPollNotificationHandler - // - - void ErrorNotification(SensorsError aError) override - { - // XXX: Bug 1206056: Try to repair some of the errors or restart cleanly. - } - - void SensorDetectedNotification(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) override - { - auto i = FindSensorIndexById(aId); - if (i == -1) { - // Add a new sensor... - i = mSensors.Length(); - mSensors.AppendElement(SensorsSensor(aId, aType, aRange, aResolution, - aPower, aMinPeriod, aMaxPeriod, - aTriggerMode, aDeliveryMode)); - } else { - // ...or update an existing one. - mSensors[i] = SensorsSensor(aId, aType, aRange, aResolution, aPower, - aMinPeriod, aMaxPeriod, aTriggerMode, - aDeliveryMode); - } - - mClasses[aType].UpdateFromSensor(mSensors[i]); - - if (mClasses[aType].mActivated && - mSensors[i].mDeliveryMode == DefaultSensorsDeliveryMode(aType)) { - // The new sensor's type is enabled, so enable sensor. - mPollInterface->EnableSensor(aId, nullptr); - mPollInterface->SetPeriod(mSensors[i].mId, DefaultSensorPeriod(aType), - nullptr); - } - } - - void SensorLostNotification(int32_t aId) override - { - auto i = FindSensorIndexById(aId); - if (i != -1) { - mSensors.RemoveElementAt(i); - } - } - - void EventNotification(int32_t aId, const SensorsEvent& aEvent) override - { - auto i = FindSensorIndexById(aId); - if (i == -1) { - HAL_ERR("Sensor %d not registered", aId); - return; - } - - SensorData sensorData; - auto rv = CreateSensorData(aEvent, mClasses[mSensors[i].mType], - sensorData); - if (NS_FAILED(rv)) { - return; - } - - NotifySensorChange(sensorData); - } - -private: - ssize_t FindSensorIndexById(int32_t aId) const - { - for (size_t i = 0; i < mSensors.Length(); ++i) { - if (mSensors[i].mId == aId) { - return i; - } - } - return -1; - } - - uint64_t DefaultSensorPeriod(SensorsType aType) const - { - return aType == SENSORS_TYPE_ACCELEROMETER ? ACCELEROMETER_POLL_RATE - : DEFAULT_DEVICE_POLL_RATE; - } - - SensorsDeliveryMode DefaultSensorsDeliveryMode(SensorsType aType) const - { - if (aType == SENSORS_TYPE_PROXIMITY || - aType == SENSORS_TYPE_SIGNIFICANT_MOTION) { - return SENSORS_DELIVERY_MODE_IMMEDIATE; - } - return SENSORS_DELIVERY_MODE_BEST_EFFORT; - } - - SensorType HardwareSensorToHalSensor(SensorsType aType) const - { - // FIXME: bug 802004, add proper support for the magnetic-field sensor. - switch (aType) { - case SENSORS_TYPE_ORIENTATION: - return SENSOR_ORIENTATION; - case SENSORS_TYPE_ACCELEROMETER: - return SENSOR_ACCELERATION; - case SENSORS_TYPE_PROXIMITY: - return SENSOR_PROXIMITY; - case SENSORS_TYPE_LIGHT: - return SENSOR_LIGHT; - case SENSORS_TYPE_GYROSCOPE: - return SENSOR_GYROSCOPE; - case SENSORS_TYPE_LINEAR_ACCELERATION: - return SENSOR_LINEAR_ACCELERATION; - case SENSORS_TYPE_ROTATION_VECTOR: - return SENSOR_ROTATION_VECTOR; - case SENSORS_TYPE_GAME_ROTATION_VECTOR: - return SENSOR_GAME_ROTATION_VECTOR; - default: - NS_NOTREACHED("Invalid sensors type"); - } - return SENSOR_UNKNOWN; - } - - SensorAccuracyType HardwareStatusToHalAccuracy(SensorsStatus aStatus) const - { - return static_cast(aStatus - 1); - } - - nsresult CreateSensorData(const SensorsEvent& aEvent, - const SensorsSensorClass& aSensorClass, - SensorData& aSensorData) const - { - nsAutoTArray sensorValues; - - auto sensor = HardwareSensorToHalSensor(aEvent.mType); - - if (sensor == SENSOR_UNKNOWN) { - return NS_ERROR_ILLEGAL_VALUE; - } - - aSensorData.sensor() = sensor; - aSensorData.accuracy() = HardwareStatusToHalAccuracy(aEvent.mStatus); - aSensorData.timestamp() = aEvent.mTimestamp; - - if (aSensorData.sensor() == SENSOR_ORIENTATION) { - // Bug 938035: transfer HAL data for orientation sensor to meet W3C spec - // ex: HAL report alpha=90 means East but alpha=90 means West in W3C spec - sensorValues.AppendElement(360.0 - radToDeg(aEvent.mData.mFloat[0])); - sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[1])); - sensorValues.AppendElement(-radToDeg(aEvent.mData.mFloat[2])); - } else if (aSensorData.sensor() == SENSOR_ACCELERATION) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - } else if (aSensorData.sensor() == SENSOR_PROXIMITY) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aSensorClass.mMinValue); - sensorValues.AppendElement(aSensorClass.mMaxValue); - } else if (aSensorData.sensor() == SENSOR_LINEAR_ACCELERATION) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - } else if (aSensorData.sensor() == SENSOR_GYROSCOPE) { - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[0])); - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[1])); - sensorValues.AppendElement(radToDeg(aEvent.mData.mFloat[2])); - } else if (aSensorData.sensor() == SENSOR_LIGHT) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - } else if (aSensorData.sensor() == SENSOR_ROTATION_VECTOR) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - sensorValues.AppendElement(aEvent.mData.mFloat[3]); - } else if (aSensorData.sensor() == SENSOR_GAME_ROTATION_VECTOR) { - sensorValues.AppendElement(aEvent.mData.mFloat[0]); - sensorValues.AppendElement(aEvent.mData.mFloat[1]); - sensorValues.AppendElement(aEvent.mData.mFloat[2]); - sensorValues.AppendElement(aEvent.mData.mFloat[3]); - } - - aSensorData.values() = sensorValues; - - return NS_OK; - } - - GonkSensorsPollInterface* mPollInterface; - nsTArray mSensors; - SensorsSensorClass mClasses[SENSORS_NUM_TYPES]; -}; - -static StaticAutoPtr sPollNotificationHandler; - -/** - * This is the notifiaction handler for the Sensors interface. If the backend - * crashes, we can restart it from here. - */ -class SensorsNotificationHandler final : public GonkSensorsNotificationHandler -{ -public: - SensorsNotificationHandler(GonkSensorsInterface* aInterface) - : mInterface(aInterface) - { - MOZ_ASSERT(mInterface); - - mInterface->SetNotificationHandler(this); - } - - void BackendErrorNotification(bool aCrashed) override - { - // XXX: Bug 1206056: restart sensorsd - } - -private: - GonkSensorsInterface* mInterface; -}; - -static StaticAutoPtr sNotificationHandler; - -/** - * |SensorsRegisterModuleResultHandler| implements the result-handler - * callback for registering the Poll service and activating the first - * sensors. If an error occures during the process, the result handler - * disconnects and closes the backend. - */ -class SensorsRegisterModuleResultHandler final - : public GonkSensorsRegistryResultHandler -{ -public: - SensorsRegisterModuleResultHandler( - uint32_t* aSensorsTypeActivated, - GonkSensorsInterface* aInterface) - : mSensorsTypeActivated(aSensorsTypeActivated) - , mInterface(aInterface) - { - MOZ_ASSERT(mSensorsTypeActivated); - MOZ_ASSERT(mInterface); - } - void OnError(SensorsError aError) override - { - GonkSensorsRegistryResultHandler::OnError(aError); // print error message - Disconnect(); // Registering failed, so close the connection completely - } - void RegisterModule(uint32_t aProtocolVersion) override - { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!sPollNotificationHandler); - - // Init, step 3: set notification handler for poll service and vice versa - auto pollInterface = mInterface->GetSensorsPollInterface(); - if (!pollInterface) { - Disconnect(); - return; - } - if (NS_FAILED(pollInterface->SetProtocolVersion(aProtocolVersion))) { - Disconnect(); - return; - } - - sPollNotificationHandler = - new SensorsPollNotificationHandler(pollInterface); - - // Init, step 4: activate sensors - for (int i = 0; i < SENSORS_NUM_TYPES; ++i) { - while (mSensorsTypeActivated[i]) { - sPollNotificationHandler->EnableSensorsByType( - static_cast(i)); - --mSensorsTypeActivated[i]; - } - } - } -public: - void Disconnect() - { - class DisconnectResultHandler final : public GonkSensorsResultHandler - { - public: - void OnError(SensorsError aError) - { - GonkSensorsResultHandler::OnError(aError); // print error message - sNotificationHandler = nullptr; - } - void Disconnect() override - { - sNotificationHandler = nullptr; - } - }; - mInterface->Disconnect(new DisconnectResultHandler()); - } -private: - uint32_t* mSensorsTypeActivated; - GonkSensorsInterface* mInterface; -}; - -/** - * |SensorsConnectResultHandler| implements the result-handler - * callback for starting the Sensors backend. - */ -class SensorsConnectResultHandler final : public GonkSensorsResultHandler -{ -public: - SensorsConnectResultHandler( - uint32_t* aSensorsTypeActivated, - GonkSensorsInterface* aInterface) - : mSensorsTypeActivated(aSensorsTypeActivated) - , mInterface(aInterface) - { - MOZ_ASSERT(mSensorsTypeActivated); - MOZ_ASSERT(mInterface); - } - void OnError(SensorsError aError) override - { - GonkSensorsResultHandler::OnError(aError); // print error message - sNotificationHandler = nullptr; - } - void Connect() override - { - MOZ_ASSERT(NS_IsMainThread()); - - // Init, step 2: register poll service - auto registryInterface = mInterface->GetSensorsRegistryInterface(); - if (!registryInterface) { - return; - } - registryInterface->RegisterModule( - GonkSensorsPollModule::SERVICE_ID, - new SensorsRegisterModuleResultHandler(mSensorsTypeActivated, - mInterface)); - } -private: - uint32_t* mSensorsTypeActivated; - GonkSensorsInterface* mInterface; -}; - -static uint32_t sSensorsTypeActivated[SENSORS_NUM_TYPES]; - -static const SensorsType sSensorsType[] = { - [SENSOR_ORIENTATION] = SENSORS_TYPE_ORIENTATION, - [SENSOR_ACCELERATION] = SENSORS_TYPE_ACCELEROMETER, - [SENSOR_PROXIMITY] = SENSORS_TYPE_PROXIMITY, - [SENSOR_LINEAR_ACCELERATION] = SENSORS_TYPE_LINEAR_ACCELERATION, - [SENSOR_GYROSCOPE] = SENSORS_TYPE_GYROSCOPE, - [SENSOR_LIGHT] = SENSORS_TYPE_LIGHT, - [SENSOR_ROTATION_VECTOR] = SENSORS_TYPE_ROTATION_VECTOR, - [SENSOR_GAME_ROTATION_VECTOR] = SENSORS_TYPE_GAME_ROTATION_VECTOR -}; - -void -EnableSensorNotificationsDaemon(SensorType aSensor) -{ - if ((aSensor < 0) || - (aSensor > static_cast(MOZ_ARRAY_LENGTH(sSensorsType)))) { - HAL_ERR("Sensor type %d not known", aSensor); - return; // Unsupported sensor type - } - - auto interface = GonkSensorsInterface::GetInstance(); - if (!interface) { - return; - } - - if (sPollNotificationHandler) { - // Everythings already up and running; enable sensor type. - sPollNotificationHandler->EnableSensorsByType(sSensorsType[aSensor]); - return; - } - - ++SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); - - if (sNotificationHandler) { - // We are in the middle of a pending start up; nothing else to do. - return; - } - - // Start up - - MOZ_ASSERT(!sPollNotificationHandler); - MOZ_ASSERT(!sNotificationHandler); - - sNotificationHandler = new SensorsNotificationHandler(interface); - - // Init, step 1: connect to Sensors backend - interface->Connect( - sNotificationHandler, - new SensorsConnectResultHandler(sSensorsTypeActivated, interface)); -} - -void -DisableSensorNotificationsDaemon(SensorType aSensor) -{ - if ((aSensor < 0) || - (aSensor > static_cast(MOZ_ARRAY_LENGTH(sSensorsType)))) { - HAL_ERR("Sensor type %d not known", aSensor); - return; // Unsupported sensor type - } - - if (sPollNotificationHandler) { - // Everthings up and running; disable sensors type - sPollNotificationHandler->DisableSensorsByType(sSensorsType[aSensor]); - return; - } - - // We might be in the middle of a startup; decrement type's ref-counter. - --SaturateOpUint32(sSensorsTypeActivated[sSensorsType[aSensor]]); - - // TODO: stop sensorsd if all sensors are disabled -} - -// -// Public interface -// - -// TODO: Remove in-Gecko sensors code. Until all devices' base -// images come with sensorsd installed, we have to support the -// in-Gecko implementation as well. So we test for the existance -// of the binary. If it's there, we use it. Otherwise we run the -// old code. -static bool -HasDaemon() -{ - static bool tested; - static bool hasDaemon; - - if (MOZ_UNLIKELY(!tested)) { - hasDaemon = !access("/system/bin/sensorsd", X_OK); - tested = true; - } - - return hasDaemon; -} - -void -EnableSensorNotifications(SensorType aSensor) -{ - if (HasDaemon()) { - EnableSensorNotificationsDaemon(aSensor); - } else { - EnableSensorNotificationsInternal(aSensor); - } -} - -void -DisableSensorNotifications(SensorType aSensor) -{ - if (HasDaemon()) { - DisableSensorNotificationsDaemon(aSensor); - } else { - DisableSensorNotificationsInternal(aSensor); - } -} - } // hal_impl } // mozilla From 1bdbdd58ec6e7f8a8e9d80c53ad79fe13c05c826 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:22 +0100 Subject: [PATCH 051/160] Backed out changeset 15a9b3c68084 (bug 1194721) --- hal/gonk/GonkSensorsInterface.cpp | 494 ------------------------------ hal/gonk/GonkSensorsInterface.h | 190 ------------ hal/moz.build | 1 - 3 files changed, 685 deletions(-) delete mode 100644 hal/gonk/GonkSensorsInterface.cpp delete mode 100644 hal/gonk/GonkSensorsInterface.h diff --git a/hal/gonk/GonkSensorsInterface.cpp b/hal/gonk/GonkSensorsInterface.cpp deleted file mode 100644 index c6c7658065b..00000000000 --- a/hal/gonk/GonkSensorsInterface.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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 "GonkSensorsInterface.h" -#include "GonkSensorsPollInterface.h" -#include "GonkSensorsRegistryInterface.h" -#include "HalLog.h" -#include -#include -#include - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsResultHandler -// - -void -GonkSensorsResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast(aError)); -} - -void -GonkSensorsResultHandler::Connect() -{ } - -void -GonkSensorsResultHandler::Disconnect() -{ } - -GonkSensorsResultHandler::~GonkSensorsResultHandler() -{ } - -// -// GonkSensorsNotificationHandler -// - -void -GonkSensorsNotificationHandler::BackendErrorNotification(bool aCrashed) -{ - if (aCrashed) { - HAL_ERR("Sensors backend crashed"); - } else { - HAL_ERR("Error in sensors backend"); - } -} - -GonkSensorsNotificationHandler::~GonkSensorsNotificationHandler() -{ } - -// -// GonkSensorsProtocol -// - -class GonkSensorsProtocol final - : public DaemonSocketIOConsumer - , public GonkSensorsRegistryModule - , public GonkSensorsPollModule -{ -public: - GonkSensorsProtocol(); - - void SetConnection(DaemonSocket* aConnection); - - already_AddRefed FetchResultHandler( - const DaemonSocketPDUHeader& aHeader); - - // Methods for |SensorsRegistryModule| and |SensorsPollModule| - // - - nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) override; - - // Methods for |DaemonSocketIOConsumer| - // - - void Handle(DaemonSocketPDU& aPDU) override; - void StoreResultHandler(const DaemonSocketPDU& aPDU) override; - -private: - void HandleRegistrySvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - void HandlePollSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - - DaemonSocket* mConnection; - nsTArray> mResultHandlerQ; -}; - -GonkSensorsProtocol::GonkSensorsProtocol() -{ } - -void -GonkSensorsProtocol::SetConnection(DaemonSocket* aConnection) -{ - mConnection = aConnection; -} - -already_AddRefed -GonkSensorsProtocol::FetchResultHandler(const DaemonSocketPDUHeader& aHeader) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - if (aHeader.mOpcode & 0x80) { - return nullptr; // Ignore notifications - } - - RefPtr res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - - return res.forget(); -} - -void -GonkSensorsProtocol::HandleRegistrySvc( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - GonkSensorsRegistryModule::HandleSvc(aHeader, aPDU, aRes); -} - -void -GonkSensorsProtocol::HandlePollSvc( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - GonkSensorsPollModule::HandleSvc(aHeader, aPDU, aRes); -} - -// |SensorsRegistryModule|, |SensorsPollModule| - -nsresult -GonkSensorsProtocol::Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) -{ - MOZ_ASSERT(mConnection); - MOZ_ASSERT(aPDU); - - aPDU->SetConsumer(this); - aPDU->SetResultHandler(aRes); - aPDU->UpdateHeader(); - - if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) { - HAL_ERR("Sensors socket is disconnected"); - return NS_ERROR_FAILURE; - } - - mConnection->SendSocketData(aPDU); // Forward PDU to data channel - - return NS_OK; -} - -// |DaemonSocketIOConsumer| - -void -GonkSensorsProtocol::Handle(DaemonSocketPDU& aPDU) -{ - static void (GonkSensorsProtocol::* const HandleSvc[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - DaemonSocketResultHandler*) = { - [GonkSensorsRegistryModule::SERVICE_ID] = - &GonkSensorsProtocol::HandleRegistrySvc, - [GonkSensorsPollModule::SERVICE_ID] = - &GonkSensorsProtocol::HandlePollSvc - }; - - DaemonSocketPDUHeader header; - - if (NS_FAILED(UnpackPDU(aPDU, header))) { - return; - } - if (!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc)) || - !HandleSvc[header.mService]) { - HAL_ERR("Sensors service %d unknown", header.mService); - return; - } - - RefPtr res = FetchResultHandler(header); - - (this->*(HandleSvc[header.mService]))(header, aPDU, res); -} - -void -GonkSensorsProtocol::StoreResultHandler(const DaemonSocketPDU& aPDU) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - mResultHandlerQ.AppendElement(aPDU.GetResultHandler()); -} - -// -// GonkSensorsInterface -// - -GonkSensorsInterface* -GonkSensorsInterface::GetInstance() -{ - static GonkSensorsInterface* sGonkSensorsInterface; - - if (sGonkSensorsInterface) { - return sGonkSensorsInterface; - } - - sGonkSensorsInterface = new GonkSensorsInterface(); - - return sGonkSensorsInterface; -} - -void -GonkSensorsInterface::SetNotificationHandler( - GonkSensorsNotificationHandler* aNotificationHandler) -{ - MOZ_ASSERT(NS_IsMainThread()); - - mNotificationHandler = aNotificationHandler; -} - -/* - * The connect procedure consists of several steps. - * - * (1) Start listening for the command channel's socket connection: We - * do this before anything else, so that we don't miss connection - * requests from the Sensors daemon. This step will create a listen - * socket. - * - * (2) Start the Sensors daemon: When the daemon starts up it will open - * a socket connection to Gecko and thus create the data channel. - * Gecko already opened the listen socket in step (1). Step (2) ends - * with the creation of the data channel. - * - * (3) Signal success to the caller. - * - * If any step fails, we roll-back the procedure and signal an error to the - * caller. - */ -void -GonkSensorsInterface::Connect(GonkSensorsNotificationHandler* aNotificationHandler, - GonkSensorsResultHandler* aRes) -{ -#define BASE_SOCKET_NAME "sensorsd" - static unsigned long POSTFIX_LENGTH = 16; - - // If we could not cleanup properly before and an old - // instance of the daemon is still running, we kill it - // here. - mozilla::hal::StopSystemService("sensorsd"); - - mNotificationHandler = aNotificationHandler; - - mResultHandlerQ.AppendElement(aRes); - - if (!mProtocol) { - mProtocol = new GonkSensorsProtocol(); - } - - if (!mListenSocket) { - mListenSocket = new ListenSocket(this, LISTEN_SOCKET); - } - - // Init, step 1: Listen for data channel... */ - - if (!mDataSocket) { - mDataSocket = new DaemonSocket(mProtocol, this, DATA_SOCKET); - } else if (mDataSocket->GetConnectionStatus() == SOCKET_CONNECTED) { - // Command channel should not be open; let's close it. - mDataSocket->Close(); - } - - // The listen socket's name is generated with a random postfix. This - // avoids naming collisions if we still have a listen socket from a - // previously failed cleanup. It also makes it hard for malicious - // external programs to capture the socket name or connect before - // the daemon can do so. If no random postfix can be generated, we - // simply use the base name as-is. - nsresult rv = DaemonSocketConnector::CreateRandomAddressString( - NS_LITERAL_CSTRING(BASE_SOCKET_NAME), POSTFIX_LENGTH, mListenSocketName); - if (NS_FAILED(rv)) { - mListenSocketName.AssignLiteral(BASE_SOCKET_NAME); - } - - rv = mListenSocket->Listen(new DaemonSocketConnector(mListenSocketName), - mDataSocket); - if (NS_FAILED(rv)) { - OnConnectError(DATA_SOCKET); - return; - } - - // The protocol implementation needs a data channel for - // sending commands to the daemon. We set it here, because - // this is the earliest time when it's available. - mProtocol->SetConnection(mDataSocket); -} - -/* - * Disconnecting is inverse to connecting. - * - * (1) Close data socket: We close the data channel and the daemon will - * will notice. Once we see the socket's disconnect, we continue with - * the cleanup. - * - * (2) Close listen socket: The listen socket is not active any longer - * and we simply close it. - * - * (3) Signal success to the caller. - * - * We don't have to stop the daemon explicitly. It will cleanup and quit - * after it noticed the closing of the data channel - * - * Rolling back half-completed cleanups is not possible. In the case of - * an error, we simply push forward and try to recover during the next - * initialization. - */ -void -GonkSensorsInterface::Disconnect(GonkSensorsResultHandler* aRes) -{ - mNotificationHandler = nullptr; - - // Cleanup, step 1: Close data channel - mDataSocket->Close(); - - mResultHandlerQ.AppendElement(aRes); -} - -GonkSensorsRegistryInterface* -GonkSensorsInterface::GetSensorsRegistryInterface() -{ - if (mRegistryInterface) { - return mRegistryInterface; - } - - mRegistryInterface = new GonkSensorsRegistryInterface(mProtocol); - - return mRegistryInterface; -} - -GonkSensorsPollInterface* -GonkSensorsInterface::GetSensorsPollInterface() -{ - if (mPollInterface) { - return mPollInterface; - } - - mPollInterface = new GonkSensorsPollInterface(mProtocol); - - return mPollInterface; -} - -GonkSensorsInterface::GonkSensorsInterface() - : mNotificationHandler(nullptr) -{ } - -GonkSensorsInterface::~GonkSensorsInterface() -{ } - -void -GonkSensorsInterface::DispatchError(GonkSensorsResultHandler* aRes, - SensorsError aError) -{ - DaemonResultRunnable1::Dispatch( - aRes, &GonkSensorsResultHandler::OnError, - ConstantInitOp1(aError)); -} - -void -GonkSensorsInterface::DispatchError( - GonkSensorsResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -// |DaemonSocketConsumer|, |ListenSocketConsumer| - -void -GonkSensorsInterface::OnConnectSuccess(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); - - switch (aIndex) { - case LISTEN_SOCKET: { - // Init, step 2: Start Sensors daemon - nsCString args("-a "); - args.Append(mListenSocketName); - mozilla::hal::StartSystemService("sensorsd", args.get()); - } - break; - case DATA_SOCKET: - if (!mResultHandlerQ.IsEmpty()) { - // Init, step 3: Signal success - RefPtr res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - res->Connect(); - } - } - break; - } -} - -void -GonkSensorsInterface::OnConnectError(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!mResultHandlerQ.IsEmpty()); - - switch (aIndex) { - case DATA_SOCKET: - // Stop daemon and close listen socket - mozilla::hal::StopSystemService("sensorsd"); - mListenSocket->Close(); - // fall through - case LISTEN_SOCKET: - if (!mResultHandlerQ.IsEmpty()) { - // Signal error to caller - RefPtr res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - DispatchError(res, SENSORS_ERROR_FAIL); - } - } - break; - } -} - -/* - * Disconnects can happend - * - * (a) during startup, - * (b) during regular service, or - * (c) during shutdown. - * - * For cases (a) and (c), |mResultHandlerQ| contains an element. For - * case (b) |mResultHandlerQ| will be empty. This distinguishes a crash in - * the daemon. The following procedure to recover from crashes consists of - * several steps for case (b). - * - * (1) Close listen socket. - * (2) Wait for all sockets to be disconnected and inform caller about - * the crash. - * (3) After all resources have been cleaned up, let the caller restart - * the daemon. - */ -void -GonkSensorsInterface::OnDisconnect(int aIndex) -{ - MOZ_ASSERT(NS_IsMainThread()); - - switch (aIndex) { - case DATA_SOCKET: - // Cleanup, step 2 (Recovery, step 1): Close listen socket - mListenSocket->Close(); - break; - case LISTEN_SOCKET: - // Cleanup, step 3: Signal success to caller - if (!mResultHandlerQ.IsEmpty()) { - RefPtr res = mResultHandlerQ.ElementAt(0); - mResultHandlerQ.RemoveElementAt(0); - if (res) { - res->Disconnect(); - } - } - break; - } - - /* For recovery make sure all sockets disconnected, in order to avoid - * the remaining disconnects interfere with the restart procedure. - */ - if (mNotificationHandler && mResultHandlerQ.IsEmpty()) { - if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED && - mDataSocket->GetConnectionStatus() == SOCKET_DISCONNECTED) { - // Recovery, step 2: Notify the caller to prepare the restart procedure. - mNotificationHandler->BackendErrorNotification(true); - mNotificationHandler = nullptr; - } - } -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsInterface.h b/hal/gonk/GonkSensorsInterface.h deleted file mode 100644 index 44126ce8762..00000000000 --- a/hal/gonk/GonkSensorsInterface.h +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- 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/. */ - -/* - * The sensors interface gives you access to the low-level sensors code - * in a platform-independent manner. The interfaces in this file allow - * for starting an stopping the sensors driver. Specific functionality - * is implemented in sub-interfaces. - */ - -#ifndef hal_gonk_GonkSensorsInterface_h -#define hal_gonk_GonkSensorsInterface_h - -#include -#include -#include -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocket; -class ListenSocket; - -} -} - -namespace mozilla { -namespace hal { - -class GonkSensorsPollInterface; -class GonkSensorsProtocol; -class GonkSensorsRegistryInterface; - -/** - * This class is the result-handler interface for the Sensors - * interface. Methods always run on the main thread. - */ -class GonkSensorsResultHandler - : public mozilla::ipc::DaemonSocketResultHandler -{ -public: - - /** - * Called if a command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsInterface::Connect|. - */ - virtual void Connect(); - - /** - * The callback method for |GonkSensorsInterface::Connect|. - */ - virtual void Disconnect(); - -protected: - virtual ~GonkSensorsResultHandler(); -}; - -/** - * This is the notification-handler interface. Implement this classes - * methods to handle event and notifications from the sensors daemon. - * All methods run on the main thread. - */ -class GonkSensorsNotificationHandler -{ -public: - - /** - * This notification is called when the backend code fails - * unexpectedly. Save state in the high-level code and restart - * the driver. - * - * @param aCrash True is the sensors driver crashed. - */ - virtual void BackendErrorNotification(bool aCrashed); - -protected: - virtual ~GonkSensorsNotificationHandler(); -}; - -/** - * This class implements the public interface to the Sensors functionality - * and driver. Use |GonkSensorsInterface::GetInstance| to retrieve an instance. - * All methods run on the main thread. - */ -class GonkSensorsInterface final - : public mozilla::ipc::DaemonSocketConsumer - , public mozilla::ipc::ListenSocketConsumer -{ -public: - /** - * Returns an instance of the Sensors backend. This code can return - * |nullptr| if no Sensors backend is available. - * - * @return An instance of |GonkSensorsInterface|. - */ - static GonkSensorsInterface* GetInstance(); - - /** - * This method sets the notification handler for sensor notifications. Call - * this method immediately after retreiving an instance of the class, or you - * won't be able able to receive notifications. You may not free the handler - * class while the Sensors backend is connected. - * - * @param aNotificationHandler An instance of a notification handler. - */ - void SetNotificationHandler( - GonkSensorsNotificationHandler* aNotificationHandler); - - /** - * This method starts the Sensors backend and establishes ad connection - * with Gecko. This is a multi-step process and errors are signalled by - * |GonkSensorsNotificationHandler::BackendErrorNotification|. If you see - * this notification before the connection has been established, it's - * certainly best to assume the Sensors backend to be not evailable. - * - * @param aRes The result handler. - */ - void Connect(GonkSensorsNotificationHandler* aNotificationHandler, - GonkSensorsResultHandler* aRes); - - /** - * This method disconnects Gecko from the Sensors backend and frees - * the backend's resources. This will invalidate all interfaces and - * state. Don't use any sensors functionality without reconnecting - * first. - * - * @param aRes The result handler. - */ - void Disconnect(GonkSensorsResultHandler* aRes); - - /** - * Returns the Registry interface for the connected Sensors backend. - * - * @return An instance of the Sensors Registry interface. - */ - GonkSensorsRegistryInterface* GetSensorsRegistryInterface(); - - /** - * Returns the Poll interface for the connected Sensors backend. - * - * @return An instance of the Sensors Poll interface. - */ - GonkSensorsPollInterface* GetSensorsPollInterface(); - -private: - enum Channel { - LISTEN_SOCKET, - DATA_SOCKET - }; - - GonkSensorsInterface(); - ~GonkSensorsInterface(); - - void DispatchError(GonkSensorsResultHandler* aRes, SensorsError aError); - void DispatchError(GonkSensorsResultHandler* aRes, nsresult aRv); - - // Methods for |DaemonSocketConsumer| and |ListenSocketConsumer| - // - - void OnConnectSuccess(int aIndex) override; - void OnConnectError(int aIndex) override; - void OnDisconnect(int aIndex) override; - - nsCString mListenSocketName; - RefPtr mListenSocket; - RefPtr mDataSocket; - nsAutoPtr mProtocol; - - nsTArray > mResultHandlerQ; - - GonkSensorsNotificationHandler* mNotificationHandler; - - nsAutoPtr mRegistryInterface; - nsAutoPtr mPollInterface; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsInterface_h diff --git a/hal/moz.build b/hal/moz.build index 195cd895228..2381b5628a1 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,7 +52,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', - 'gonk/GonkSensorsInterface.cpp', 'gonk/GonkSensorsPollInterface.cpp', 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', From e510ba930ddc7d345d31e7805eb0e72a61cd0e47 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:23 +0100 Subject: [PATCH 052/160] Backed out changeset 6a5db0961a0a (bug 1194721) --- hal/gonk/GonkSensorsPollInterface.cpp | 430 -------------------------- hal/gonk/GonkSensorsPollInterface.h | 343 -------------------- hal/moz.build | 1 - 3 files changed, 774 deletions(-) delete mode 100644 hal/gonk/GonkSensorsPollInterface.cpp delete mode 100644 hal/gonk/GonkSensorsPollInterface.h diff --git a/hal/gonk/GonkSensorsPollInterface.cpp b/hal/gonk/GonkSensorsPollInterface.cpp deleted file mode 100644 index 010deb656a7..00000000000 --- a/hal/gonk/GonkSensorsPollInterface.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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 "GonkSensorsPollInterface.h" -#include "HalLog.h" - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsPollResultHandler -// - -void -GonkSensorsPollResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast(aError)); -} - -void -GonkSensorsPollResultHandler::EnableSensor() -{ } - -void -GonkSensorsPollResultHandler::DisableSensor() -{ } - -void -GonkSensorsPollResultHandler::SetPeriod() -{ } - -GonkSensorsPollResultHandler::~GonkSensorsPollResultHandler() -{ } - -// -// GonkSensorsPollNotificationHandler -// - -void -GonkSensorsPollNotificationHandler::ErrorNotification(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast(aError)); -} - -void -GonkSensorsPollNotificationHandler::SensorDetectedNotification( - int32_t aId, - SensorsType aType, - float aRange, - float aResolution, - float aPower, - int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) -{ } - -void -GonkSensorsPollNotificationHandler::SensorLostNotification(int32_t aId) -{ } - -void -GonkSensorsPollNotificationHandler::EventNotification(int32_t aId, - const SensorsEvent& aEvent) -{ } - -GonkSensorsPollNotificationHandler::~GonkSensorsPollNotificationHandler() -{ } - -// -// GonkSensorsPollModule -// - -GonkSensorsPollModule::GonkSensorsPollModule() - : mProtocolVersion(0) -{ } - -GonkSensorsPollModule::~GonkSensorsPollModule() -{ } - -nsresult -GonkSensorsPollModule::SetProtocolVersion(unsigned long aProtocolVersion) -{ - if ((aProtocolVersion < MIN_PROTOCOL_VERSION) || - (aProtocolVersion > MAX_PROTOCOL_VERSION)) { - HAL_ERR("Sensors Poll protocol version %lu not supported", - aProtocolVersion); - return NS_ERROR_ILLEGAL_VALUE; - } - mProtocolVersion = aProtocolVersion; - return NS_OK; -} - -void -GonkSensorsPollModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const HandleOp[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - DaemonSocketResultHandler*) = { - [0] = &GonkSensorsPollModule::HandleRsp, - [1] = &GonkSensorsPollModule::HandleNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); // I/O thread - - // Negate twice to map bit to 0/1 - unsigned long isNtf = !!(aHeader.mOpcode & 0x80); - - (this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes); -} - -// Commands -// - -nsresult -GonkSensorsPollModule::EnableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu( - new DaemonSocketPDU(SERVICE_ID, OPCODE_ENABLE_SENSOR, 0)); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.forget(); - return NS_OK; -} - -nsresult -GonkSensorsPollModule::DisableSensorCmd(int32_t aId, GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu( - new DaemonSocketPDU(SERVICE_ID, OPCODE_DISABLE_SENSOR, 0)); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.forget(); - return NS_OK; -} - -nsresult -GonkSensorsPollModule::SetPeriodCmd(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu( - new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_PERIOD, 0)); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = PackPDU(aPeriod, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.forget(); - return NS_OK; -} - -// Responses -// - -void -GonkSensorsPollModule::ErrorRsp( - const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, GonkSensorsPollResultHandler* aRes) -{ - ErrorRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::OnError, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::EnableSensorRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::EnableSensor, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::DisableSensorRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::DisableSensor, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SetPeriodRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, &GonkSensorsPollResultHandler::SetPeriod, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::HandleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const sHandleRsp[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - GonkSensorsPollResultHandler*) = { - [OPCODE_ERROR] = &GonkSensorsPollModule::ErrorRsp, - [OPCODE_ENABLE_SENSOR] = &GonkSensorsPollModule::EnableSensorRsp, - [OPCODE_DISABLE_SENSOR] = &GonkSensorsPollModule::DisableSensorRsp, - [OPCODE_SET_PERIOD] = &GonkSensorsPollModule::SetPeriodRsp, - }; - - MOZ_ASSERT(!NS_IsMainThread()); // I/O thread - - if (!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(sHandleRsp)) || - !sHandleRsp[aHeader.mOpcode]) { - HAL_ERR("Sensors poll response opcode %d unknown", aHeader.mOpcode); - return; - } - - RefPtr res = - static_cast(aRes); - - if (!res) { - return; // Return early if no result handler has been set for response - } - - (this->*(sHandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); -} - -// Notifications -// - -// Returns the current notification handler to a notification runnable -class GonkSensorsPollModule::NotificationHandlerWrapper final -{ -public: - typedef GonkSensorsPollNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sNotificationHandler; - } - - static GonkSensorsPollNotificationHandler* sNotificationHandler; -}; - -GonkSensorsPollNotificationHandler* - GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler; - -void -GonkSensorsPollModule::ErrorNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - ErrorNotification::Dispatch( - &GonkSensorsPollNotificationHandler::ErrorNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SensorDetectedNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - SensorDetectedNotification::Dispatch( - &GonkSensorsPollNotificationHandler::SensorDetectedNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::SensorLostNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - SensorLostNotification::Dispatch( - &GonkSensorsPollNotificationHandler::SensorLostNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::EventNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) -{ - EventNotification::Dispatch( - &GonkSensorsPollNotificationHandler::EventNotification, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsPollModule::HandleNtf( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsPollModule::* const sHandleNtf[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { - [0] = &GonkSensorsPollModule::ErrorNtf, - [1] = &GonkSensorsPollModule::SensorDetectedNtf, - [2] = &GonkSensorsPollModule::SensorLostNtf, - [3] = &GonkSensorsPollModule::EventNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); - - uint8_t index = aHeader.mOpcode - 0x80; - - if (!(index < MOZ_ARRAY_LENGTH(sHandleNtf)) || !sHandleNtf[index]) { - HAL_ERR("Sensors poll notification opcode %d unknown", aHeader.mOpcode); - return; - } - - (this->*(sHandleNtf[index]))(aHeader, aPDU); -} - -// -// GonkSensorsPollInterface -// - -GonkSensorsPollInterface::GonkSensorsPollInterface( - GonkSensorsPollModule* aModule) - : mModule(aModule) -{ } - -GonkSensorsPollInterface::~GonkSensorsPollInterface() -{ } - -void -GonkSensorsPollInterface::SetNotificationHandler( - GonkSensorsPollNotificationHandler* aNotificationHandler) -{ - MOZ_ASSERT(NS_IsMainThread()); - - GonkSensorsPollModule::NotificationHandlerWrapper::sNotificationHandler = - aNotificationHandler; -} - -nsresult -GonkSensorsPollInterface::SetProtocolVersion(unsigned long aProtocolVersion) -{ - MOZ_ASSERT(mModule); - - return mModule->SetProtocolVersion(aProtocolVersion); -} - -void -GonkSensorsPollInterface::EnableSensor(int32_t aId, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->EnableSensorCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::DisableSensor(int32_t aId, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->DisableSensorCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::SetPeriod(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->SetPeriodCmd(aId, aPeriod, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsPollInterface::DispatchError( - GonkSensorsPollResultHandler* aRes, SensorsError aError) -{ - DaemonResultRunnable1::Dispatch( - aRes, &GonkSensorsPollResultHandler::OnError, - ConstantInitOp1(aError)); -} - -void -GonkSensorsPollInterface::DispatchError( - GonkSensorsPollResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsPollInterface.h b/hal/gonk/GonkSensorsPollInterface.h deleted file mode 100644 index d25fed4f3ea..00000000000 --- a/hal/gonk/GonkSensorsPollInterface.h +++ /dev/null @@ -1,343 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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/. */ - -/* - * The poll interface gives yo access to the Sensors daemon's Poll service, - * which handles sensors. The poll service will inform you when sensors are - * detected or removed from the system. You can activate (or deactivate) - * existing sensors and poll will deliver the sensors' events. - * - * All public methods and callback methods run on the main thread. - */ - -#ifndef hal_gonk_GonkSensorsPollInterface_h -#define hal_gonk_GonkSensorsPollInterface_h - -#include -#include -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocketPDU; -class DaemonSocketPDUHeader; - -} -} - -namespace mozilla { -namespace hal { - -class SensorsInterface; - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketResultHandler; - -/** - * This class is the result-handler interface for the Sensors - * Poll interface. Methods always run on the main thread. - */ -class GonkSensorsPollResultHandler : public DaemonSocketResultHandler -{ -public: - - /** - * Called if a poll command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsPollInterface::EnableSensor|. - */ - virtual void EnableSensor(); - - /** - * The callback method for |GonkSensorsPollInterface::DisableSensor|. - */ - virtual void DisableSensor(); - - /** - * The callback method for |GonkSensorsPollInterface::SetPeriod|. - */ - virtual void SetPeriod(); - -protected: - virtual ~GonkSensorsPollResultHandler(); -}; - -/** - * This is the notification-handler interface. Implement this classes - * methods to handle event and notifications from the sensors daemon. - */ -class GonkSensorsPollNotificationHandler -{ -public: - - /** - * The notification handler for errors. You'll receive this call if - * there's been a critical error in the daemon. Either try to handle - * the error, or restart the daemon. - * - * @param aError The error code. - */ - virtual void ErrorNotification(SensorsError aError); - - /** - * This methods gets call when a new sensor has been detected. - * - * @param aId The sensor's id. - * @param aType The sensor's type. - * @param aRange The sensor's maximum value. - * @param aResolution The minimum difference between two consecutive values. - * @param aPower The sensor's power consumption (in mA). - * @param aMinPeriod The minimum time between two events (in ns). - * @param aMaxPeriod The maximum time between two events (in ns). - * @param aTriggerMode The sensor's mode for triggering events. - * @param aDeliveryMode The sensor's urgency for event delivery. - */ - virtual void SensorDetectedNotification(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode); - - /** - * This methods gets call when an existing sensor has been removed. - * - * @param aId The sensor's id. - */ - virtual void SensorLostNotification(int32_t aId); - - /** - * This is the callback methods for sensor events. Only activated sensors - * generate events. All sensors are disabled by default. The actual data - * of the event depends on the sensor type. - * - * @param aId The sensor's id. - * @param aEvent The event's data. - */ - virtual void EventNotification(int32_t aId, const SensorsEvent& aEvent); - -protected: - virtual ~GonkSensorsPollNotificationHandler(); -}; - -/** - * This is the module class for the Sensors poll component. It handles PDU - * packing and unpacking. Methods are either executed on the main thread or - * the I/O thread. - * - * This is an internal class, use |GonkSensorsPollInterface| instead. - */ -class GonkSensorsPollModule -{ -public: - class NotificationHandlerWrapper; - - enum { - SERVICE_ID = 0x01 - }; - - enum { - OPCODE_ERROR = 0x00, - OPCODE_ENABLE_SENSOR = 0x01, - OPCODE_DISABLE_SENSOR = 0x02, - OPCODE_SET_PERIOD = 0x03 - }; - - enum { - MIN_PROTOCOL_VERSION = 1, - MAX_PROTOCOL_VERSION = 1 - }; - - virtual nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) = 0; - - nsresult SetProtocolVersion(unsigned long aProtocolVersion); - - // - // Commands - // - - nsresult EnableSensorCmd(int32_t aId, - GonkSensorsPollResultHandler* aRes); - - nsresult DisableSensorCmd(int32_t aId, - GonkSensorsPollResultHandler* aRes); - - nsresult SetPeriodCmd(int32_t aId, uint64_t aPeriod, - GonkSensorsPollResultHandler* aRes); - -protected: - GonkSensorsPollModule(); - virtual ~GonkSensorsPollModule(); - - void HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - -private: - - // - // Responses - // - - typedef mozilla::ipc::DaemonResultRunnable0< - GonkSensorsPollResultHandler, void> - ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsPollResultHandler, void, SensorsError, SensorsError> - ErrorRunnable; - - void ErrorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void EnableSensorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void DisableSensorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void SetPeriodRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsPollResultHandler* aRes); - - void HandleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - - // - // Notifications - // - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, SensorsError> - ErrorNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable9< - NotificationHandlerWrapper, void, int32_t, SensorsType, - float, float, float, int32_t, int32_t, SensorsTriggerMode, - SensorsDeliveryMode> - SensorDetectedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, int32_t> - SensorLostNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable2< - NotificationHandlerWrapper, void, int32_t, SensorsEvent, int32_t, - const SensorsEvent&> - EventNotification; - - class SensorDetectedInitOp; - class SensorLostInitOp; - class EventInitOp; - - void ErrorNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void SensorDetectedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void SensorLostNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void EventNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU); - - void HandleNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes); - -private: - unsigned long mProtocolVersion; -}; - -/** - * This class implements the public interface to the Sensors poll - * component. Use |SensorsInterface::GetPollInterface| to retrieve - * an instance. All methods run on the main thread. - */ -class GonkSensorsPollInterface final -{ -public: - friend class GonkSensorsInterface; - - /** - * This method sets the notification handler for poll notifications. Call - * this method immediately after registering the module. Otherwise you won't - * be able able to receive poll notifications. You may not free the handler - * class while the poll component is regsitered. - * - * @param aNotificationHandler An instance of a poll notification handler. - */ - void SetNotificationHandler( - GonkSensorsPollNotificationHandler* aNotificationHandler); - - /** - * This method sets the protocol version. You should set it to the - * value that has been returned from the backend when registering the - * Poll service. You cannot send or receive messages before setting - * the protocol version. - * - * @param aProtocolVersion - * @return NS_OK for supported versions, or an XPCOM error code otherwise. - */ - nsresult SetProtocolVersion(unsigned long aProtocolVersion); - - /** - * Enables an existing sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. - * - * @param aId The sensor's id. - * @param aRes The result handler. - */ - void EnableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); - - /** - * Disables an existing sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. - * - * @param aId The sensor's id. - * @param aRes The result handler. - */ - void DisableSensor(int32_t aId, GonkSensorsPollResultHandler* aRes); - - /** - * Sets the period for a sensor. The sensor id will have been delivered in - * a SensorDetectedNotification. The value for the period should be between - * the sensor's minimum and maximum period. - * - * @param aId The sensor's id. - * @param aPeriod The sensor's new period. - * @param aRes The result handler. - */ - void SetPeriod(int32_t aId, uint64_t aPeriod, GonkSensorsPollResultHandler* aRes); - - ~GonkSensorsPollInterface(); - -private: - GonkSensorsPollInterface(GonkSensorsPollModule* aModule); - - void DispatchError(GonkSensorsPollResultHandler* aRes, SensorsError aError); - void DispatchError(GonkSensorsPollResultHandler* aRes, nsresult aRv); - - GonkSensorsPollModule* mModule; -}; - -} // hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsPollInterface_h diff --git a/hal/moz.build b/hal/moz.build index 2381b5628a1..bba3f138670 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,7 +52,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', - 'gonk/GonkSensorsPollInterface.cpp', 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', From bbf73780b4f11734657a7cba73bc7df4781c26b8 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:25 +0100 Subject: [PATCH 053/160] Backed out changeset f817794c422b (bug 1194721) --- hal/gonk/GonkSensorsRegistryInterface.cpp | 212 ---------------------- hal/gonk/GonkSensorsRegistryInterface.h | 185 ------------------- hal/moz.build | 1 - 3 files changed, 398 deletions(-) delete mode 100644 hal/gonk/GonkSensorsRegistryInterface.cpp delete mode 100644 hal/gonk/GonkSensorsRegistryInterface.h diff --git a/hal/gonk/GonkSensorsRegistryInterface.cpp b/hal/gonk/GonkSensorsRegistryInterface.cpp deleted file mode 100644 index 0fc318fe2a8..00000000000 --- a/hal/gonk/GonkSensorsRegistryInterface.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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 "GonkSensorsRegistryInterface.h" -#include "GonkSensorsHelpers.h" -#include "HalLog.h" - -namespace mozilla { -namespace hal { - -using namespace mozilla::ipc; - -// -// GonkSensorsRegistryResultHandler -// - -void -GonkSensorsRegistryResultHandler::OnError(SensorsError aError) -{ - HAL_ERR("Received error code %d", static_cast(aError)); -} - -void -GonkSensorsRegistryResultHandler::RegisterModule(uint32_t aProtocolVersion) -{ } - -void -GonkSensorsRegistryResultHandler::UnregisterModule() -{ } - -GonkSensorsRegistryResultHandler::~GonkSensorsRegistryResultHandler() -{ } - -// -// GonkSensorsRegistryModule -// - -GonkSensorsRegistryModule::~GonkSensorsRegistryModule() -{ } - -void -GonkSensorsRegistryModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - DaemonSocketResultHandler* aRes) -{ - static void (GonkSensorsRegistryModule::* const HandleRsp[])( - const DaemonSocketPDUHeader&, - DaemonSocketPDU&, - GonkSensorsRegistryResultHandler*) = { - [OPCODE_ERROR] = &GonkSensorsRegistryModule::ErrorRsp, - [OPCODE_REGISTER_MODULE] = &GonkSensorsRegistryModule::RegisterModuleRsp, - [OPCODE_UNREGISTER_MODULE] = &GonkSensorsRegistryModule::UnregisterModuleRsp - }; - - if ((aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) || - !HandleRsp[aHeader.mOpcode]) { - HAL_ERR("Sensors registry response opcode %d unknown", aHeader.mOpcode); - return; - } - - RefPtr res = - static_cast(aRes); - - if (!res) { - return; // Return early if no result handler has been set - } - - (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); -} - -// Commands -// - -nsresult -GonkSensorsRegistryModule::RegisterModuleCmd( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu( - new DaemonSocketPDU(SERVICE_ID, OPCODE_REGISTER_MODULE, 0)); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.forget(); - return NS_OK; -} - -nsresult -GonkSensorsRegistryModule::UnregisterModuleCmd( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu( - new DaemonSocketPDU(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0)); - - nsresult rv = PackPDU(aId, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - Unused << pdu.forget(); - return NS_OK; -} - -// Responses -// - -void -GonkSensorsRegistryModule::ErrorRsp( - const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, GonkSensorsRegistryResultHandler* aRes) -{ - ErrorRunnable::Dispatch( - aRes, &GonkSensorsRegistryResultHandler::OnError, UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsRegistryModule::RegisterModuleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes) -{ - Uint32ResultRunnable::Dispatch( - aRes, - &GonkSensorsRegistryResultHandler::RegisterModule, - UnpackPDUInitOp(aPDU)); -} - -void -GonkSensorsRegistryModule::UnregisterModuleRsp( - const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes) -{ - ResultRunnable::Dispatch( - aRes, - &GonkSensorsRegistryResultHandler::UnregisterModule, - UnpackPDUInitOp(aPDU)); -} - -// -// GonkSensorsRegistryInterface -// - -GonkSensorsRegistryInterface::GonkSensorsRegistryInterface( - GonkSensorsRegistryModule* aModule) - : mModule(aModule) -{ } - -GonkSensorsRegistryInterface::~GonkSensorsRegistryInterface() -{ } - -void -GonkSensorsRegistryInterface::RegisterModule( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->RegisterModuleCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsRegistryInterface::UnregisterModule( - uint8_t aId, GonkSensorsRegistryResultHandler* aRes) -{ - MOZ_ASSERT(mModule); - - nsresult rv = mModule->UnregisterModuleCmd(aId, aRes); - if (NS_FAILED(rv)) { - DispatchError(aRes, rv); - } -} - -void -GonkSensorsRegistryInterface::DispatchError( - GonkSensorsRegistryResultHandler* aRes, SensorsError aError) -{ - DaemonResultRunnable1::Dispatch( - aRes, &GonkSensorsRegistryResultHandler::OnError, - ConstantInitOp1(aError)); -} - -void -GonkSensorsRegistryInterface::DispatchError( - GonkSensorsRegistryResultHandler* aRes, nsresult aRv) -{ - SensorsError error; - - if (NS_FAILED(Convert(aRv, error))) { - error = SENSORS_ERROR_FAIL; - } - DispatchError(aRes, error); -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsRegistryInterface.h b/hal/gonk/GonkSensorsRegistryInterface.h deleted file mode 100644 index e7d64cb1d81..00000000000 --- a/hal/gonk/GonkSensorsRegistryInterface.h +++ /dev/null @@ -1,185 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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/. */ - -/* - * The registry interface gives yo access to the Sensors daemon's Registry - * service. The purpose of the service is to register and setup all other - * services, and make them available. - * - * All public methods and callback methods run on the main thread. - */ - -#ifndef hal_gonk_GonkSensorsRegistryInterface_h -#define hal_gonk_GonkSensorsRegistryInterface_h - -#include -#include -#include "SensorsTypes.h" - -namespace mozilla { -namespace ipc { - -class DaemonSocketPDU; -class DaemonSocketPDUHeader; - -} -} - -namespace mozilla { -namespace hal { - -class SensorsInterface; - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketResultHandler; - -/** - * This class is the result-handler interface for the Sensors - * Registry interface. Methods always run on the main thread. - */ -class GonkSensorsRegistryResultHandler : public DaemonSocketResultHandler -{ -public: - - /** - * Called if a registry command failed. - * - * @param aError The error code. - */ - virtual void OnError(SensorsError aError); - - /** - * The callback method for |GonkSensorsRegistryInterface::RegisterModule|. - * - * @param aProtocolVersion The daemon's protocol version. Make sure it's - * compatible with Gecko's implementation. - */ - virtual void RegisterModule(uint32_t aProtocolVersion); - - /** - * The callback method for |SensorsRegsitryInterface::UnregisterModule|. - */ - virtual void UnregisterModule(); - -protected: - virtual ~GonkSensorsRegistryResultHandler(); -}; - -/** - * This is the module class for the Sensors registry component. It handles - * PDU packing and unpacking. Methods are either executed on the main thread - * or the I/O thread. - * - * This is an internal class, use |GonkSensorsRegistryInterface| instead. - */ -class GonkSensorsRegistryModule -{ -public: - enum { - SERVICE_ID = 0x00 - }; - - enum { - OPCODE_ERROR = 0x00, - OPCODE_REGISTER_MODULE = 0x01, - OPCODE_UNREGISTER_MODULE = 0x02 - }; - - virtual nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) = 0; - - // - // Commands - // - - nsresult RegisterModuleCmd(uint8_t aId, - GonkSensorsRegistryResultHandler* aRes); - - nsresult UnregisterModuleCmd(uint8_t aId, - GonkSensorsRegistryResultHandler* aRes); - -protected: - virtual ~GonkSensorsRegistryModule(); - - void HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); - - // - // Responses - // - - typedef mozilla::ipc::DaemonResultRunnable0< - GonkSensorsRegistryResultHandler, void> - ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsRegistryResultHandler, void, uint32_t, uint32_t> - Uint32ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - GonkSensorsRegistryResultHandler, void, SensorsError, SensorsError> - ErrorRunnable; - - void ErrorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); - - void RegisterModuleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); - - void UnregisterModuleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - GonkSensorsRegistryResultHandler* aRes); -}; - -/** - * This class implements the public interface to the Sensors Registry - * component. Use |SensorsInterface::GetRegistryInterface| to retrieve - * an instance. All methods run on the main thread. - */ -class GonkSensorsRegistryInterface final -{ -public: - friend class GonkSensorsInterface; - - /** - * Sends a RegisterModule command to the Sensors daemon. When the - * result handler's |RegisterModule| method gets called, the service - * has been registered successfully and can be used. - * - * @param aId The id of the service that is to be registered. - * @param aRes The result handler. - */ - void RegisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); - - /** - * Sends an UnregisterModule command to the Sensors daemon. The service - * should not be used afterwards until it has been registered again. - * - * @param aId The id of the service that is to be unregistered. - * @param aRes The result handler. - */ - void UnregisterModule(uint8_t aId, GonkSensorsRegistryResultHandler* aRes); - - ~GonkSensorsRegistryInterface(); - -private: - GonkSensorsRegistryInterface(GonkSensorsRegistryModule* aModule); - - void DispatchError(GonkSensorsRegistryResultHandler* aRes, - SensorsError aError); - void DispatchError(GonkSensorsRegistryResultHandler* aRes, - nsresult aRv); - - GonkSensorsRegistryModule* mModule; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsRegistryInterface_h diff --git a/hal/moz.build b/hal/moz.build index bba3f138670..0a0c5cd8b51 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -52,7 +52,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', - 'gonk/GonkSensorsRegistryInterface.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', 'gonk/UeventPoller.cpp', From 015290e684853ca05a799dcdf9fd621e091f8974 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:26 +0100 Subject: [PATCH 054/160] Backed out changeset 2a7dbf51f1e8 (bug 1194721) --- hal/gonk/GonkSensorsHelpers.cpp | 112 --------------- hal/gonk/GonkSensorsHelpers.h | 226 ------------------------------- hal/gonk/SensorsTypes.h | 140 ------------------- hal/moz.build | 1 - ipc/hal/DaemonSocketPDUHelpers.h | 130 ------------------ 5 files changed, 609 deletions(-) delete mode 100644 hal/gonk/GonkSensorsHelpers.cpp delete mode 100644 hal/gonk/GonkSensorsHelpers.h delete mode 100644 hal/gonk/SensorsTypes.h diff --git a/hal/gonk/GonkSensorsHelpers.cpp b/hal/gonk/GonkSensorsHelpers.cpp deleted file mode 100644 index ccc940c7c08..00000000000 --- a/hal/gonk/GonkSensorsHelpers.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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 "GonkSensorsHelpers.h" - -namespace mozilla { -namespace hal { - -// -// Unpacking -// - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut) -{ - nsresult rv = UnpackPDU(aPDU, aOut.mType); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mTimestamp); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mStatus); - if (NS_FAILED(rv)) { - return rv; - } - - size_t i = 0; - - switch (aOut.mType) { - case SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED: - case SENSORS_TYPE_GYROSCOPE_UNCALIBRATED: - /* 6 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_ROTATION_VECTOR: - case SENSORS_TYPE_GAME_ROTATION_VECTOR: - case SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR: - /* 5 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_ACCELEROMETER: - case SENSORS_TYPE_GEOMAGNETIC_FIELD: - case SENSORS_TYPE_ORIENTATION: - case SENSORS_TYPE_GYROSCOPE: - case SENSORS_TYPE_GRAVITY: - case SENSORS_TYPE_LINEAR_ACCELERATION: - /* 3 data values */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - /* fall through */ - case SENSORS_TYPE_LIGHT: - case SENSORS_TYPE_PRESSURE: - case SENSORS_TYPE_TEMPERATURE: - case SENSORS_TYPE_PROXIMITY: - case SENSORS_TYPE_RELATIVE_HUMIDITY: - case SENSORS_TYPE_AMBIENT_TEMPERATURE: - case SENSORS_TYPE_HEART_RATE: - case SENSORS_TYPE_TILT_DETECTOR: - case SENSORS_TYPE_WAKE_GESTURE: - case SENSORS_TYPE_GLANCE_GESTURE: - case SENSORS_TYPE_PICK_UP_GESTURE: - case SENSORS_TYPE_WRIST_TILT_GESTURE: - case SENSORS_TYPE_SIGNIFICANT_MOTION: - case SENSORS_TYPE_STEP_DETECTED: - /* 1 data value */ - rv = UnpackPDU(aPDU, aOut.mData.mFloat[i++]); - if (NS_FAILED(rv)) { - return rv; - } - break; - case SENSORS_TYPE_STEP_COUNTER: - /* 1 data value */ - rv = UnpackPDU(aPDU, aOut.mData.mUint[0]); - if (NS_FAILED(rv)) { - return rv; - } - break; - default: - if (MOZ_HAL_IPC_UNPACK_WARN_IF(true, SensorsEvent)) { - return NS_ERROR_ILLEGAL_VALUE; - } - } - rv = UnpackPDU(aPDU, aOut.mDeliveryMode); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; -} - -} // namespace hal -} // namespace mozilla diff --git a/hal/gonk/GonkSensorsHelpers.h b/hal/gonk/GonkSensorsHelpers.h deleted file mode 100644 index 5218af53afd..00000000000 --- a/hal/gonk/GonkSensorsHelpers.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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/. */ - -#ifndef hal_gonk_GonkSensorsHelpers_h -#define hal_gonk_GonkSensorsHelpers_h - -#include -#include -#include "SensorsTypes.h" - -namespace mozilla { -namespace hal { - -using mozilla::ipc::DaemonSocketPDU; -using mozilla::ipc::DaemonSocketPDUHeader; -using mozilla::ipc::DaemonSocketPDUHelpers::Convert; -using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU; -using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU; - -using namespace mozilla::ipc::DaemonSocketPDUHelpers; - -// -// Conversion -// -// The functions below convert the input value to the output value's -// type and perform extension tests on the validity of the result. On -// success the output value will be returned in |aOut|. The functions -// return NS_OK on success, or an XPCOM error code otherwise. -// -// See the documentation of the HAL IPC framework for more information -// on conversion functions. -// - -nsresult -Convert(int32_t aIn, SensorsStatus& aOut) -{ - static const uint8_t sStatus[] = { - [0] = SENSORS_STATUS_NO_CONTACT, // '-1' - [1] = SENSORS_STATUS_UNRELIABLE, // '0' - [2] = SENSORS_STATUS_ACCURACY_LOW, // '1' - [3] = SENSORS_STATUS_ACCURACY_MEDIUM, // '2' - [4] = SENSORS_STATUS_ACCURACY_HIGH // '3' - }; - static const int8_t sOffset = -1; // '-1' is the lower bound of the status - - if (MOZ_HAL_IPC_CONVERT_WARN_IF(aIn < sOffset, int32_t, SensorsStatus) || - MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= (static_cast(MOZ_ARRAY_LENGTH(sStatus)) + sOffset), - int32_t, SensorsStatus)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast(sStatus[aIn - sOffset]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsDeliveryMode& aOut) -{ - static const uint8_t sMode[] = { - [0x00] = SENSORS_DELIVERY_MODE_BEST_EFFORT, - [0x01] = SENSORS_DELIVERY_MODE_IMMEDIATE - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsDeliveryMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast(sMode[aIn]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsError& aOut) -{ - static const uint8_t sError[] = { - [0x00] = SENSORS_ERROR_NONE, - [0x01] = SENSORS_ERROR_FAIL, - [0x02] = SENSORS_ERROR_NOT_READY, - [0x03] = SENSORS_ERROR_NOMEM, - [0x04] = SENSORS_ERROR_BUSY, - [0x05] = SENSORS_ERROR_DONE, - [0x06] = SENSORS_ERROR_UNSUPPORTED, - [0x07] = SENSORS_ERROR_PARM_INVALID - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sError), uint8_t, SensorsError)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast(sError[aIn]); - return NS_OK; -} - -nsresult -Convert(uint8_t aIn, SensorsTriggerMode& aOut) -{ - static const uint8_t sMode[] = { - [0x00] = SENSORS_TRIGGER_MODE_CONTINUOUS, - [0x01] = SENSORS_TRIGGER_MODE_ON_CHANGE, - [0x02] = SENSORS_TRIGGER_MODE_ONE_SHOT, - [0x03] = SENSORS_TRIGGER_MODE_SPECIAL - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sMode), uint8_t, SensorsTriggerMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast(sMode[aIn]); - return NS_OK; -} - -nsresult -Convert(uint32_t aIn, SensorsType& aOut) -{ - static const uint8_t sType[] = { - [0x00] = 0, // invalid, required by gcc - [0x01] = SENSORS_TYPE_ACCELEROMETER, - [0x02] = SENSORS_TYPE_GEOMAGNETIC_FIELD, - [0x03] = SENSORS_TYPE_ORIENTATION, - [0x04] = SENSORS_TYPE_GYROSCOPE, - [0x05] = SENSORS_TYPE_LIGHT, - [0x06] = SENSORS_TYPE_PRESSURE, - [0x07] = SENSORS_TYPE_TEMPERATURE, - [0x08] = SENSORS_TYPE_PROXIMITY, - [0x09] = SENSORS_TYPE_GRAVITY, - [0x0a] = SENSORS_TYPE_LINEAR_ACCELERATION, - [0x0b] = SENSORS_TYPE_ROTATION_VECTOR, - [0x0c] = SENSORS_TYPE_RELATIVE_HUMIDITY, - [0x0d] = SENSORS_TYPE_AMBIENT_TEMPERATURE, - [0x0e] = SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, - [0x0f] = SENSORS_TYPE_GAME_ROTATION_VECTOR, - [0x10] = SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, - [0x11] = SENSORS_TYPE_SIGNIFICANT_MOTION, - [0x12] = SENSORS_TYPE_STEP_DETECTED, - [0x13] = SENSORS_TYPE_STEP_COUNTER, - [0x14] = SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, - [0x15] = SENSORS_TYPE_HEART_RATE, - [0x16] = SENSORS_TYPE_TILT_DETECTOR, - [0x17] = SENSORS_TYPE_WAKE_GESTURE, - [0x18] = SENSORS_TYPE_GLANCE_GESTURE, - [0x19] = SENSORS_TYPE_PICK_UP_GESTURE, - [0x1a] = SENSORS_TYPE_WRIST_TILT_GESTURE - }; - if (MOZ_HAL_IPC_CONVERT_WARN_IF( - !aIn, uint32_t, SensorsType) || - MOZ_HAL_IPC_CONVERT_WARN_IF( - aIn >= MOZ_ARRAY_LENGTH(sType), uint32_t, SensorsType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = static_cast(sType[aIn]); - return NS_OK; -} - -nsresult -Convert(nsresult aIn, SensorsError& aOut) -{ - if (NS_SUCCEEDED(aIn)) { - aOut = SENSORS_ERROR_NONE; - } else if (aIn == NS_ERROR_OUT_OF_MEMORY) { - aOut = SENSORS_ERROR_NOMEM; - } else if (aIn == NS_ERROR_ILLEGAL_VALUE) { - aOut = SENSORS_ERROR_PARM_INVALID; - } else { - aOut = SENSORS_ERROR_FAIL; - } - return NS_OK; -} - -// -// Packing -// -// Pack functions store a value in PDU. See the documentation of the -// HAL IPC framework for more information. -// -// There are currently no sensor-specific pack functions necessary. If -// you add one, put it below. -// - -// -// Unpacking -// -// Unpack function retrieve a value from a PDU. The functions return -// NS_OK on success, or an XPCOM error code otherwise. On sucess, the -// returned value is stored in the second argument |aOut|. -// -// See the documentation of the HAL IPC framework for more information -// on unpack functions. -// - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsDeliveryMode& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsError& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsEvent& aOut); - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsStatus& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsTriggerMode& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion(aOut)); -} - -nsresult -UnpackPDU(DaemonSocketPDU& aPDU, SensorsType& aOut) -{ - return UnpackPDU(aPDU, UnpackConversion(aOut)); -} - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_GonkSensorsHelpers_h diff --git a/hal/gonk/SensorsTypes.h b/hal/gonk/SensorsTypes.h deleted file mode 100644 index 35c852f5a80..00000000000 --- a/hal/gonk/SensorsTypes.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 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/. */ - -#ifndef hal_gonk_SensorsTypes_h -#define hal_gonk_SensorsTypes_h - -namespace mozilla { -namespace hal { - -enum SensorsDeliveryMode { - SENSORS_DELIVERY_MODE_BEST_EFFORT, - SENSORS_DELIVERY_MODE_IMMEDIATE -}; - -enum SensorsError { - SENSORS_ERROR_NONE, - SENSORS_ERROR_FAIL, - SENSORS_ERROR_NOT_READY, - SENSORS_ERROR_NOMEM, - SENSORS_ERROR_BUSY, - SENSORS_ERROR_DONE, - SENSORS_ERROR_UNSUPPORTED, - SENSORS_ERROR_PARM_INVALID -}; - -enum SensorsStatus { - SENSORS_STATUS_NO_CONTACT, - SENSORS_STATUS_UNRELIABLE, - SENSORS_STATUS_ACCURACY_LOW, - SENSORS_STATUS_ACCURACY_MEDIUM, - SENSORS_STATUS_ACCURACY_HIGH -}; - -enum SensorsTriggerMode { - SENSORS_TRIGGER_MODE_CONTINUOUS, - SENSORS_TRIGGER_MODE_ON_CHANGE, - SENSORS_TRIGGER_MODE_ONE_SHOT, - SENSORS_TRIGGER_MODE_SPECIAL -}; - -enum SensorsType { - SENSORS_TYPE_ACCELEROMETER, - SENSORS_TYPE_GEOMAGNETIC_FIELD, - SENSORS_TYPE_ORIENTATION, - SENSORS_TYPE_GYROSCOPE, - SENSORS_TYPE_LIGHT, - SENSORS_TYPE_PRESSURE, - SENSORS_TYPE_TEMPERATURE, - SENSORS_TYPE_PROXIMITY, - SENSORS_TYPE_GRAVITY, - SENSORS_TYPE_LINEAR_ACCELERATION, - SENSORS_TYPE_ROTATION_VECTOR, - SENSORS_TYPE_RELATIVE_HUMIDITY, - SENSORS_TYPE_AMBIENT_TEMPERATURE, - SENSORS_TYPE_MAGNETIC_FIELD_UNCALIBRATED, - SENSORS_TYPE_GAME_ROTATION_VECTOR, - SENSORS_TYPE_GYROSCOPE_UNCALIBRATED, - SENSORS_TYPE_SIGNIFICANT_MOTION, - SENSORS_TYPE_STEP_DETECTED, - SENSORS_TYPE_STEP_COUNTER, - SENSORS_TYPE_GEOMAGNETIC_ROTATION_VECTOR, - SENSORS_TYPE_HEART_RATE, - SENSORS_TYPE_TILT_DETECTOR, - SENSORS_TYPE_WAKE_GESTURE, - SENSORS_TYPE_GLANCE_GESTURE, - SENSORS_TYPE_PICK_UP_GESTURE, - SENSORS_TYPE_WRIST_TILT_GESTURE, - SENSORS_NUM_TYPES -}; - -struct SensorsEvent { - SensorsType mType; - SensorsStatus mStatus; - SensorsDeliveryMode mDeliveryMode; - int64_t mTimestamp; - union { - float mFloat[6]; - uint64_t mUint[1]; - } mData; -}; - -/** - * |SensorsSensor| represents a device sensor; either single or composite. - */ -struct SensorsSensor { - SensorsSensor(int32_t aId, SensorsType aType, - float aRange, float aResolution, - float aPower, int32_t aMinPeriod, - int32_t aMaxPeriod, - SensorsTriggerMode aTriggerMode, - SensorsDeliveryMode aDeliveryMode) - : mId(aId) - , mType(aType) - , mRange(aRange) - , mResolution(aResolution) - , mPower(aPower) - , mMinPeriod(aMinPeriod) - , mMaxPeriod(aMaxPeriod) - , mTriggerMode(aTriggerMode) - , mDeliveryMode(aDeliveryMode) - { } - - int32_t mId; - SensorsType mType; - float mRange; - float mResolution; - float mPower; - int32_t mMinPeriod; - int32_t mMaxPeriod; - SensorsTriggerMode mTriggerMode; - SensorsDeliveryMode mDeliveryMode; -}; - -/** - * |SensorClass| represents the status of a specific sensor type. - */ -struct SensorsSensorClass { - SensorsSensorClass() - : mActivated(0) - , mMinValue(0) - , mMaxValue(0) - { } - - void UpdateFromSensor(const SensorsSensor& aSensor) - { - mMaxValue = std::max(aSensor.mRange, mMaxValue); - } - - uint32_t mActivated; - float mMinValue; - float mMaxValue; -}; - -} // namespace hal -} // namespace mozilla - -#endif // hal_gonk_SensorsTypes_h diff --git a/hal/moz.build b/hal/moz.build index 0a0c5cd8b51..e0328816851 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -51,7 +51,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkDiskSpaceWatcher.cpp', 'gonk/GonkFMRadio.cpp', 'gonk/GonkSensor.cpp', - 'gonk/GonkSensorsHelpers.cpp', 'gonk/GonkSwitch.cpp', 'gonk/SystemService.cpp', 'gonk/UeventPoller.cpp', diff --git a/ipc/hal/DaemonSocketPDUHelpers.h b/ipc/hal/DaemonSocketPDUHelpers.h index 02f672f0ed5..219a0ce0198 100644 --- a/ipc/hal/DaemonSocketPDUHelpers.h +++ b/ipc/hal/DaemonSocketPDUHelpers.h @@ -1142,136 +1142,6 @@ public: WarnAboutTrailingData(); return NS_OK; } - - template - nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, - T5& aArg5, T6& aArg6, T7& aArg7) const - { - DaemonSocketPDU& pdu = GetPDU(); - - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg2); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg4); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg5); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg6); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg7); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - - template - nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, - T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8) const - { - DaemonSocketPDU& pdu = GetPDU(); - - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg2); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg4); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg5); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg6); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg7); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg8); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - - template - nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4, - T5& aArg5, T6& aArg6, T7& aArg7, T8& aArg8, - T9& aArg9) const - { - DaemonSocketPDU& pdu = GetPDU(); - - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg2); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg4); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg5); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg6); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg7); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg8); - if (NS_FAILED(rv)) { - return rv; - } - rv = UnpackPDU(pdu, aArg9); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } }; } // namespace DaemonSocketPDUHelpers From f920cffa2baf1edde6dec42a34eb9905ed6f3928 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:28 +0100 Subject: [PATCH 055/160] Backed out changeset 2a5cf57e8b67 (bug 1194721) --- ipc/hal/DaemonSocketPDUHelpers.h | 48 -------------------------------- ipc/unixsocket/SocketBase.h | 40 -------------------------- 2 files changed, 88 deletions(-) diff --git a/ipc/hal/DaemonSocketPDUHelpers.h b/ipc/hal/DaemonSocketPDUHelpers.h index 219a0ce0198..3c9fb775e87 100644 --- a/ipc/hal/DaemonSocketPDUHelpers.h +++ b/ipc/hal/DaemonSocketPDUHelpers.h @@ -188,30 +188,6 @@ PackPDU(uint32_t aIn, DaemonSocketPDU& aPDU) return aPDU.Write(aIn); } -inline nsresult -PackPDU(int64_t aIn, DaemonSocketPDU& aPDU) -{ - return aPDU.Write(aIn); -} - -inline nsresult -PackPDU(uint64_t aIn, DaemonSocketPDU& aPDU) -{ - return aPDU.Write(aIn); -} - -inline nsresult -PackPDU(float aIn, DaemonSocketPDU& aPDU) -{ - return aPDU.Write(aIn); -} - -inline nsresult -PackPDU(double aIn, DaemonSocketPDU& aPDU) -{ - return aPDU.Write(aIn); -} - nsresult PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU); @@ -670,30 +646,6 @@ UnpackPDU(DaemonSocketPDU& aPDU, uint32_t& aOut) return aPDU.Read(aOut); } -inline nsresult -UnpackPDU(DaemonSocketPDU& aPDU, int64_t& aOut) -{ - return aPDU.Read(aOut); -} - -inline nsresult -UnpackPDU(DaemonSocketPDU& aPDU, uint64_t& aOut) -{ - return aPDU.Read(aOut); -} - -inline nsresult -UnpackPDU(DaemonSocketPDU& aPDU, float& aOut) -{ - return aPDU.Read(aOut); -} - -inline nsresult -UnpackPDU(DaemonSocketPDU& aPDU, double& aOut) -{ - return aPDU.Read(aOut); -} - inline nsresult UnpackPDU(DaemonSocketPDU& aPDU, DaemonSocketPDUHeader& aOut) { diff --git a/ipc/unixsocket/SocketBase.h b/ipc/unixsocket/SocketBase.h index 65d912cefd7..e59d4dea14f 100644 --- a/ipc/unixsocket/SocketBase.h +++ b/ipc/unixsocket/SocketBase.h @@ -73,26 +73,6 @@ public: return Read(&aValue, sizeof(aValue)); } - nsresult Read(int64_t& aValue) - { - return Read(&aValue, sizeof(aValue)); - } - - nsresult Read(uint64_t& aValue) - { - return Read(&aValue, sizeof(aValue)); - } - - nsresult Read(float& aValue) - { - return Read(&aValue, sizeof(aValue)); - } - - nsresult Read(double& aValue) - { - return Read(&aValue, sizeof(aValue)); - } - uint8_t* Append(size_t aLen); nsresult Write(const void* aValue, size_t aLen); @@ -127,26 +107,6 @@ public: return Write(&aValue, sizeof(aValue)); } - nsresult Write(int64_t aValue) - { - return Write(&aValue, sizeof(aValue)); - } - - nsresult Write(uint64_t aValue) - { - return Write(&aValue, sizeof(aValue)); - } - - nsresult Write(float aValue) - { - return Write(&aValue, sizeof(aValue)); - } - - nsresult Write(double aValue) - { - return Write(&aValue, sizeof(aValue)); - } - protected: UnixSocketBuffer(); From 4fe2cc7c907a6dd8e8a97a792e0406870218c1bf Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:24:29 +0100 Subject: [PATCH 056/160] Backed out changeset e7a5a6174748 (bug 1194721) --- ipc/hal/DaemonRunnables.h | 88 --------------------------------------- 1 file changed, 88 deletions(-) diff --git a/ipc/hal/DaemonRunnables.h b/ipc/hal/DaemonRunnables.h index e067dd14119..03d6fa01a3b 100644 --- a/ipc/hal/DaemonRunnables.h +++ b/ipc/hal/DaemonRunnables.h @@ -713,94 +713,6 @@ private: Tin6 mArg6; }; -template -class DaemonNotificationRunnable8 final : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef DaemonNotificationRunnable8 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)( - Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), - const InitOp& aInitOp) - { - RefPtr runnable(new SelfType(aMethod)); - if (NS_FAILED(runnable->Init(aInitOp))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch( - Res (ObjectType::*aMethod)( - Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), - const InitOp& aInitOp) - { - RefPtr runnable = Create(aMethod, aInitOp); - if (!runnable) { - return; - } - Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(runnable))); - } - - NS_IMETHODIMP Run() override - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - if (!obj) { - NS_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, - mArg5, mArg6, mArg7, mArg8); - } - return NS_OK; - } - -private: - DaemonNotificationRunnable8( - Res (ObjectType::*aMethod)( - Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult Init(const InitOp& aInitOp) - { - nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, - mArg5, mArg6, mArg7, mArg8); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)( - Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); - Tin1 mArg1; - Tin2 mArg2; - Tin3 mArg3; - Tin4 mArg4; - Tin5 mArg5; - Tin6 mArg6; - Tin7 mArg7; - Tin8 mArg8; -}; - template Date: Wed, 3 Feb 2016 16:24:31 +0100 Subject: [PATCH 057/160] Backed out changeset bbadd0a1367d (bug 1194721) --- ipc/hal/DaemonSocket.cpp | 2 +- ipc/hal/DaemonSocketPDU.cpp | 26 +++++++++++++------------- ipc/hal/DaemonSocketPDU.h | 12 ++++++------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ipc/hal/DaemonSocket.cpp b/ipc/hal/DaemonSocket.cpp index 6ba49c8c889..41765acc2c0 100644 --- a/ipc/hal/DaemonSocket.cpp +++ b/ipc/hal/DaemonSocket.cpp @@ -103,7 +103,7 @@ DaemonSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) if (!mPDU) { /* There's only one PDU for receiving. We reuse it every time. */ - mPDU = new DaemonSocketPDU(DaemonSocketPDU::PDU_MAX_PAYLOAD_LENGTH); + mPDU = new DaemonSocketPDU(DaemonSocketPDU::MAX_PAYLOAD_LENGTH); } *aBuffer = mPDU.get(); diff --git a/ipc/hal/DaemonSocketPDU.cpp b/ipc/hal/DaemonSocketPDU.cpp index 08184f872c2..d8cb3070c9a 100644 --- a/ipc/hal/DaemonSocketPDU.cpp +++ b/ipc/hal/DaemonSocketPDU.cpp @@ -35,17 +35,17 @@ DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); // Allocate memory - size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize; + size_t availableSpace = HEADER_SIZE + aPayloadSize; ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); // Reserve PDU header - uint8_t* data = Append(PDU_HEADER_SIZE); + uint8_t* data = Append(HEADER_SIZE); MOZ_ASSERT(data); // Setup PDU header - data[PDU_OFF_SERVICE] = aService; - data[PDU_OFF_OPCODE] = aOpcode; - memcpy(data + PDU_OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); + data[OFF_SERVICE] = aService; + data[OFF_OPCODE] = aOpcode; + memcpy(data + OFF_LENGTH, &aPayloadSize, sizeof(aPayloadSize)); } DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize) @@ -53,7 +53,7 @@ DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize) { MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer); - size_t availableSpace = PDU_HEADER_SIZE + aPayloadSize; + size_t availableSpace = HEADER_SIZE + aPayloadSize; ResetBuffer(new uint8_t[availableSpace], 0, 0, availableSpace); } @@ -69,9 +69,9 @@ void DaemonSocketPDU::GetHeader(uint8_t& aService, uint8_t& aOpcode, uint16_t& aPayloadSize) { - memcpy(&aService, GetData(PDU_OFF_SERVICE), sizeof(aService)); - memcpy(&aOpcode, GetData(PDU_OFF_OPCODE), sizeof(aOpcode)); - memcpy(&aPayloadSize, GetData(PDU_OFF_LENGTH), sizeof(aPayloadSize)); + memcpy(&aService, GetData(OFF_SERVICE), sizeof(aService)); + memcpy(&aOpcode, GetData(OFF_OPCODE), sizeof(aOpcode)); + memcpy(&aPayloadSize, GetData(OFF_LENGTH), sizeof(aPayloadSize)); } ssize_t @@ -164,12 +164,12 @@ nsresult DaemonSocketPDU::UpdateHeader() { size_t len = GetPayloadSize(); - if (len >= PDU_MAX_PAYLOAD_LENGTH) { + if (len >= MAX_PAYLOAD_LENGTH) { return NS_ERROR_ILLEGAL_VALUE; } uint16_t len16 = static_cast(len); - memcpy(GetData(PDU_OFF_LENGTH), &len16, sizeof(len16)); + memcpy(GetData(OFF_LENGTH), &len16, sizeof(len16)); return NS_OK; } @@ -177,9 +177,9 @@ DaemonSocketPDU::UpdateHeader() size_t DaemonSocketPDU::GetPayloadSize() const { - MOZ_ASSERT(GetSize() >= PDU_HEADER_SIZE); + MOZ_ASSERT(GetSize() >= HEADER_SIZE); - return GetSize() - PDU_HEADER_SIZE; + return GetSize() - HEADER_SIZE; } void diff --git a/ipc/hal/DaemonSocketPDU.h b/ipc/hal/DaemonSocketPDU.h index 006b3ac3a2c..2f0c9b152cc 100644 --- a/ipc/hal/DaemonSocketPDU.h +++ b/ipc/hal/DaemonSocketPDU.h @@ -39,12 +39,12 @@ class DaemonSocketPDU final : public UnixSocketIOBuffer { public: enum { - PDU_OFF_SERVICE = 0, - PDU_OFF_OPCODE = 1, - PDU_OFF_LENGTH = 2, - PDU_OFF_PAYLOAD = 4, - PDU_HEADER_SIZE = PDU_OFF_PAYLOAD, - PDU_MAX_PAYLOAD_LENGTH = 1 << 16 + OFF_SERVICE = 0, + OFF_OPCODE = 1, + OFF_LENGTH = 2, + OFF_PAYLOAD = 4, + HEADER_SIZE = OFF_PAYLOAD, + MAX_PAYLOAD_LENGTH = 1 << 16 }; DaemonSocketPDU(uint8_t aService, uint8_t aOpcode, uint16_t aPayloadSize); From 0d206890d6b23bb310fcd8e3a294cb7aafd54d9e Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Wed, 3 Feb 2016 16:25:00 +0100 Subject: [PATCH 058/160] Backed out changeset 8d6c228ef008 (bug 1194721) on developers request --- mfbt/Saturate.h | 287 ------------------------------------ mfbt/moz.build | 1 - mfbt/tests/TestSaturate.cpp | 215 --------------------------- mfbt/tests/moz.build | 1 - testing/cppunittest.ini | 1 - 5 files changed, 505 deletions(-) delete mode 100644 mfbt/Saturate.h delete mode 100644 mfbt/tests/TestSaturate.cpp diff --git a/mfbt/Saturate.h b/mfbt/Saturate.h deleted file mode 100644 index 5d3315e17be..00000000000 --- a/mfbt/Saturate.h +++ /dev/null @@ -1,287 +0,0 @@ -/* -*- 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/. */ - -/* Provides saturation arithmetics for scalar types. */ - -#ifndef mozilla_Saturate_h -#define mozilla_Saturate_h - -#include "mozilla/Attributes.h" -#include "mozilla/Move.h" -#include "mozilla/NumericLimits.h" -#include "mozilla/TypeTraits.h" - -namespace mozilla { -namespace detail { - -/** - * |SaturateOp| wraps scalar values for saturation arithmetics. Usage: - * - * uint32_t value = 1; - * - * ++SaturateOp(value); // value is 2 - * --SaturateOp(value); // value is 1 - * --SaturateOp(value); // value is 0 - * --SaturateOp(value); // value is still 0 - * - * Please add new operators when required. - * - * |SaturateOp| will saturate at the minimum and maximum values of - * type T. If you need other bounds, implement a clamped-type class and - * specialize the type traits accordingly. - */ -template -class SaturateOp -{ -public: - explicit SaturateOp(T& aValue) - : mValue(aValue) - { - // We should actually check for |std::is_scalar::value| to be - // true, but this type trait is not available everywhere. Relax - // this assertion if you want to use floating point values as well. - static_assert(IsIntegral::value, - "Integral type required in instantiation"); - } - - // Add and subtract operators - - T operator+(const T& aRhs) const - { - return T(mValue) += aRhs; - } - - T operator-(const T& aRhs) const - { - return T(mValue) -= aRhs; - } - - // Compound operators - - const T& operator+=(const T& aRhs) const - { - const T min = NumericLimits::min(); - const T max = NumericLimits::max(); - - if (aRhs > static_cast(0)) { - mValue = (max - aRhs) < mValue ? max : mValue + aRhs; - } else { - mValue = (min - aRhs) > mValue ? min : mValue + aRhs; - } - return mValue; - } - - const T& operator-=(const T& aRhs) const - { - const T min = NumericLimits::min(); - const T max = NumericLimits::max(); - - if (aRhs > static_cast(0)) { - mValue = (min + aRhs) > mValue ? min : mValue - aRhs; - } else { - mValue = (max + aRhs) < mValue ? max : mValue - aRhs; - } - return mValue; - } - - // Increment and decrement operators - - const T& operator++() const // prefix - { - return operator+=(static_cast(1)); - } - - T operator++(int) const // postfix - { - const T value(mValue); - operator++(); - return value; - } - - const T& operator--() const // prefix - { - return operator-=(static_cast(1)); - } - - T operator--(int) const // postfix - { - const T value(mValue); - operator--(); - return value; - } - -private: - SaturateOp(const SaturateOp&) = delete; - SaturateOp(SaturateOp&&) = delete; - SaturateOp& operator=(const SaturateOp&) = delete; - SaturateOp& operator=(SaturateOp&&) = delete; - - T& mValue; -}; - -/** - * |Saturate| is a value type for saturation arithmetics. It's - * build on top of |SaturateOp|. - */ -template -class Saturate -{ -public: - Saturate() = default; - MOZ_IMPLICIT Saturate(const Saturate&) = default; - - MOZ_IMPLICIT Saturate(Saturate&& aValue) - { - mValue = Move(aValue.mValue); - } - - explicit Saturate(const T& aValue) - : mValue(aValue) - { } - - const T& value() const - { - return mValue; - } - - // Compare operators - - bool operator==(const Saturate& aRhs) const - { - return mValue == aRhs.mValue; - } - - bool operator!=(const Saturate& aRhs) const - { - return !operator==(aRhs); - } - - bool operator==(const T& aRhs) const - { - return mValue == aRhs; - } - - bool operator!=(const T& aRhs) const - { - return !operator==(aRhs); - } - - // Assignment operators - - Saturate& operator=(const Saturate&) = default; - - Saturate& operator=(Saturate&& aRhs) - { - mValue = Move(aRhs.mValue); - return *this; - } - - // Add and subtract operators - - Saturate operator+(const Saturate& aRhs) const - { - Saturate lhs(mValue); - return lhs += aRhs.mValue; - } - - Saturate operator+(const T& aRhs) const - { - Saturate lhs(mValue); - return lhs += aRhs; - } - - Saturate operator-(const Saturate& aRhs) const - { - Saturate lhs(mValue); - return lhs -= aRhs.mValue; - } - - Saturate operator-(const T& aRhs) const - { - Saturate lhs(mValue); - return lhs -= aRhs; - } - - // Compound operators - - Saturate& operator+=(const Saturate& aRhs) - { - SaturateOp(mValue) += aRhs.mValue; - return *this; - } - - Saturate& operator+=(const T& aRhs) - { - SaturateOp(mValue) += aRhs; - return *this; - } - - Saturate& operator-=(const Saturate& aRhs) - { - SaturateOp(mValue) -= aRhs.mValue; - return *this; - } - - Saturate& operator-=(const T& aRhs) - { - SaturateOp(mValue) -= aRhs; - return *this; - } - - // Increment and decrement operators - - Saturate& operator++() // prefix - { - ++SaturateOp(mValue); - return *this; - } - - Saturate operator++(int) // postfix - { - return Saturate(SaturateOp(mValue)++); - } - - Saturate& operator--() // prefix - { - --SaturateOp(mValue); - return *this; - } - - Saturate operator--(int) // postfix - { - return Saturate(SaturateOp(mValue)--); - } - -private: - T mValue; -}; - -} // namespace detail - -typedef detail::Saturate SaturateInt8; -typedef detail::Saturate SaturateInt16; -typedef detail::Saturate SaturateInt32; -typedef detail::Saturate SaturateUint8; -typedef detail::Saturate SaturateUint16; -typedef detail::Saturate SaturateUint32; - -} // namespace mozilla - -template -bool -operator==(LhsT aLhs, const mozilla::detail::Saturate& aRhs) -{ - return aRhs.operator==(static_cast(aLhs)); -} - -template -bool -operator!=(LhsT aLhs, const mozilla::detail::Saturate& aRhs) -{ - return !(aLhs == aRhs); -} - -#endif // mozilla_Saturate_h diff --git a/mfbt/moz.build b/mfbt/moz.build index 38d424dd2ed..f6acbe8d5c5 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -73,7 +73,6 @@ EXPORTS.mozilla = [ 'RefPtr.h', 'ReverseIterator.h', 'RollingMean.h', - 'Saturate.h', 'Scoped.h', 'ScopeExit.h', 'SegmentedVector.h', diff --git a/mfbt/tests/TestSaturate.cpp b/mfbt/tests/TestSaturate.cpp deleted file mode 100644 index cd1208ff8f3..00000000000 --- a/mfbt/tests/TestSaturate.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- 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 - -#include -#include - -using mozilla::detail::Saturate; -using mozilla::NumericLimits; - -#define A(a) MOZ_RELEASE_ASSERT(a, "Test \'" #a "\' failed.") - -static const unsigned long sNumOps = 32; - -template -static T -StartValue() -{ - // Specialize |StartValue| for the given type. - A(false); -} - -template<> -int8_t -StartValue() -{ - return 0; -} - -template<> -int16_t -StartValue() -{ - return 0; -} - -template<> -int32_t -StartValue() -{ - return 0; -} - -template<> -uint8_t -StartValue() -{ - // Picking a value near middle of uint8_t's range. - return static_cast(NumericLimits::max()); -} - -template<> -uint16_t -StartValue() -{ - // Picking a value near middle of uint16_t's range. - return static_cast(NumericLimits::max()); -} - -template<> -uint32_t -StartValue() -{ - // Picking a value near middle of uint32_t's range. - return static_cast(NumericLimits::max()); -} - -// Add -// - -template -static void -TestPrefixIncr() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A(++value == ++satValue); - } -} - -template -static void -TestPostfixIncr() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A(value++ == satValue++); - } -} - -template -static void -TestAdd() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A((value + i) == (satValue + i)); - } -} - -// Subtract -// - -template -static void -TestPrefixDecr() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A(--value == --satValue); - } -} - -template -static void -TestPostfixDecr() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A(value-- == satValue--); - } -} - -template -static void -TestSub() -{ - T value = StartValue(); - Saturate satValue(value); - - for (T i = 0; i < static_cast(sNumOps); ++i) { - A((value - i) == (satValue - i)); - } -} - -// Corner cases near bounds -// - -template -static void -TestUpperBound() -{ - Saturate satValue(NumericLimits::max()); - - A(--satValue == (NumericLimits::max() - 1)); - A(++satValue == (NumericLimits::max())); - A(++satValue == (NumericLimits::max())); // don't overflow here - A(++satValue == (NumericLimits::max())); // don't overflow here - A(--satValue == (NumericLimits::max() - 1)); // back at (max - 1) - A(--satValue == (NumericLimits::max() - 2)); -} - -template -static void -TestLowerBound() -{ - Saturate satValue(NumericLimits::min()); - - A(++satValue == (NumericLimits::min() + 1)); - A(--satValue == (NumericLimits::min())); - A(--satValue == (NumericLimits::min())); // don't overflow here - A(--satValue == (NumericLimits::min())); // don't overflow here - A(++satValue == (NumericLimits::min() + 1)); // back at (max + 1) - A(++satValue == (NumericLimits::min() + 2)); -} - -// Framework -// - -template -static void -TestAll() -{ - // Assert that we don't accidently hit type's range limits in tests. - const T value = StartValue(); - A(NumericLimits::min() + static_cast(sNumOps) <= value); - A(NumericLimits::max() - static_cast(sNumOps) >= value); - - TestPrefixIncr(); - TestPostfixIncr(); - TestAdd(); - - TestPrefixDecr(); - TestPostfixDecr(); - TestSub(); - - TestUpperBound(); - TestLowerBound(); -} - -int -main() -{ - TestAll(); - TestAll(); - TestAll(); - TestAll(); - TestAll(); - TestAll(); - return 0; -} diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index 499cd730de4..c75ee8eec15 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -31,7 +31,6 @@ CppUnitTests([ 'TestPair', 'TestRefPtr', 'TestRollingMean', - 'TestSaturate', 'TestScopeExit', 'TestSegmentedVector', 'TestSHA1', diff --git a/testing/cppunittest.ini b/testing/cppunittest.ini index a3e5da5d317..05899358c4b 100644 --- a/testing/cppunittest.ini +++ b/testing/cppunittest.ini @@ -67,7 +67,6 @@ skip-if = os == 'android' # Bug 1147630 [TestRollingMean] [TestSHA1] [TestSTSParser] -[TestSaturate] [TestSplayTree] [TestStartupCache] skip-if = os == 'b2g' || os == 'android' # Bug 929655 From c0c49b2bd1d23904a97e3454f8e521bb89ff5153 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 10:26:10 -0500 Subject: [PATCH 059/160] Bug 1245164 - Ensure the metrics are still clamped properly when the surface shifts. r=rbarker --- .../java/org/mozilla/gecko/gfx/NativePanZoomController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java b/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java index f4042e7fac2..120887b770b 100644 --- a/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java +++ b/mobile/android/base/java/org/mozilla/gecko/gfx/NativePanZoomController.java @@ -190,7 +190,7 @@ class NativePanZoomController extends JNIObject implements PanZoomController { @Override // PanZoomController public ImmutableViewportMetrics adjustScrollForSurfaceShift(ImmutableViewportMetrics aMetrics, PointF aShift) { adjustScrollForSurfaceShift(aShift.x, aShift.y); - return aMetrics; + return aMetrics.offsetViewportByAndClamp(aShift.x, aShift.y); } @WrapForJNI(allowMultithread = true) From 95b561f204301ce1c8cb34d84b1870b251768a8d Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 07:28:27 -0800 Subject: [PATCH 060/160] Bug 1242119 - Remove early exit in WinXP debug content processes. r=froydnj This was disabled because it was causing intermittent failures in a test, but that failure seems to have stopped. This will cause us to start doing leak checking in content processes on Windows XP. --- xpcom/build/XPCOMInit.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index 7d6647d39ea..35e9561e295 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -968,18 +968,6 @@ ShutdownXPCOM(nsIServiceManager* aServMgr) NS_ShutdownNativeCharsetUtils(); #endif -#if defined(XP_WIN) - // This exit(0) call is intended to be temporary, to get shutdown leak - // checking working on Linux. - // On Windows XP debug, there are intermittent failures in - // dom/media/tests/mochitest/test_peerConnection_basicH264Video.html - // if we don't exit early in a child process. See bug 1073310. - if (XRE_IsContentProcess() && !IsVistaOrLater()) { - NS_WARNING("Exiting child process early!"); - exit(0); - } -#endif - // Shutdown xpcom. This will release all loaders and cause others holding // a refcount to the component manager to release it. if (nsComponentManagerImpl::gComponentManager) { From 22bb795314c4e4124bb069af28db35d306d8f410 Mon Sep 17 00:00:00 2001 From: Paul Bignier Date: Tue, 2 Feb 2016 07:38:00 +0100 Subject: [PATCH 061/160] Bug 1245113 - Fixed uninitialized variables warnings. r=ehsan --- editor/libeditor/nsEditor.cpp | 2 +- editor/libeditor/nsHTMLEditor.cpp | 2 +- editor/txtsvc/nsTextServicesDocument.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/editor/libeditor/nsEditor.cpp b/editor/libeditor/nsEditor.cpp index bc604c141df..ba0c1fa9913 100644 --- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -1480,7 +1480,7 @@ nsEditor::JoinNodes(nsINode& aLeftNode, nsINode& aRightNode) parent->AsDOMNode()); } - nsresult result; + nsresult result = NS_OK; RefPtr txn = CreateTxnForJoinNode(aLeftNode, aRightNode); if (txn) { result = DoTransaction(txn); diff --git a/editor/libeditor/nsHTMLEditor.cpp b/editor/libeditor/nsHTMLEditor.cpp index f635c16d8b2..ca5684a5aad 100644 --- a/editor/libeditor/nsHTMLEditor.cpp +++ b/editor/libeditor/nsHTMLEditor.cpp @@ -547,7 +547,7 @@ nsHTMLEditor::BeginningOfDocument() // Find first editable thingy bool done = false; nsCOMPtr curNode = rootElement.get(), selNode; - int32_t curOffset = 0, selOffset; + int32_t curOffset = 0, selOffset = 0; while (!done) { nsWSRunObject wsObj(this, curNode, curOffset); int32_t visOffset = 0; diff --git a/editor/txtsvc/nsTextServicesDocument.cpp b/editor/txtsvc/nsTextServicesDocument.cpp index 587b4ad9f9e..46a6eedf0ec 100644 --- a/editor/txtsvc/nsTextServicesDocument.cpp +++ b/editor/txtsvc/nsTextServicesDocument.cpp @@ -2754,7 +2754,7 @@ nsTextServicesDocument::GetUncollapsedSelection(nsITextServicesDocument::TSDBloc nsCOMPtr startParent, endParent; int32_t startOffset, endOffset; int32_t rangeCount, tableCount, i; - int32_t e1s1, e1s2, e2s1, e2s2; + int32_t e1s1 = 0, e1s2 = 0, e2s1 = 0, e2s2 = 0; OffsetEntry *eStart, *eEnd; int32_t eStartOffset, eEndOffset; From c8e4165734b2112a61667c2b1d5885696bc53511 Mon Sep 17 00:00:00 2001 From: Bogdan Postelnicu Date: Wed, 3 Feb 2016 13:53:11 +0200 Subject: [PATCH 062/160] Bug 1245464 - initialize with 0 mSupportedIfaces in xpcAccessibleGeneric in order to avoid corrupted result after bit-wise operation. r=surkov --- accessible/xpcom/xpcAccessibleGeneric.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessible/xpcom/xpcAccessibleGeneric.h b/accessible/xpcom/xpcAccessibleGeneric.h index 1b7c6c40270..8f6d9878746 100644 --- a/accessible/xpcom/xpcAccessibleGeneric.h +++ b/accessible/xpcom/xpcAccessibleGeneric.h @@ -39,7 +39,7 @@ public: } xpcAccessibleGeneric(ProxyAccessible* aProxy, uint32_t aInterfaces) : - mIntl(aProxy) + mIntl(aProxy), mSupportedIfaces(0) { if (aInterfaces & Interfaces::SELECTION) { mSupportedIfaces |= eSelectable; From 5b883e889a2ebb7c456729fe1a92fbb0c33da035 Mon Sep 17 00:00:00 2001 From: Juan Gomez Date: Thu, 7 Jan 2016 08:05:00 +0100 Subject: [PATCH 063/160] Bug 1235990 - Correct array type checking. r=shu --- b2g/components/PersistentDataBlock.jsm | 2 +- b2g/components/test/unit/file_persistentdatablock.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/components/PersistentDataBlock.jsm b/b2g/components/PersistentDataBlock.jsm index 72085a9b568..a26efe56d82 100644 --- a/b2g/components/PersistentDataBlock.jsm +++ b/b2g/components/PersistentDataBlock.jsm @@ -66,7 +66,7 @@ function toHexString(data) { let hexString = ""; if (typeof data === "string") { hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join(""); - } else if (typeof data === "array") { + } else if (data instanceof Array) { hexString = data.map(toHexChar).join(""); } return hexString; diff --git a/b2g/components/test/unit/file_persistentdatablock.js b/b2g/components/test/unit/file_persistentdatablock.js index 691cead2ae6..6ce3072ac3a 100644 --- a/b2g/components/test/unit/file_persistentdatablock.js +++ b/b2g/components/test/unit/file_persistentdatablock.js @@ -33,7 +33,7 @@ function toHexString(data) { let hexString = ""; if (typeof data === "string") { hexString = Array.from(data, (c, i) => toHexChar(data.charCodeAt(i))).join(""); - } else if (typeof data === "array") { + } else if (data instanceof Array) { hexString = data.map(toHexChar).join(""); } return hexString; From d9c52b88f5a2071f47b73cdb2e0ff017dd729177 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Wed, 3 Feb 2016 18:21:27 +0200 Subject: [PATCH 064/160] Bug 1242907 - Fix broken about:crashes due to typo in ContentCrashHandlers.jsm. r=mconley --- browser/base/content/test/general/browser.ini | 2 + .../browser_aboutTabCrashed_withoutDump.js | 44 +++++++++++++++++++ browser/modules/ContentCrashHandlers.jsm | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 4633a631b9d..4b632ffd65b 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -543,3 +543,5 @@ skip-if = !e10s || !crashreporter skip-if = !e10s || !crashreporter [browser_aboutTabCrashed_showForm.js] skip-if = !e10s || !crashreporter +[browser_aboutTabCrashed_withoutDump.js] +skip-if = !e10s diff --git a/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js b/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js new file mode 100644 index 00000000000..4a41b16d4d2 --- /dev/null +++ b/browser/base/content/test/general/browser_aboutTabCrashed_withoutDump.js @@ -0,0 +1,44 @@ +"use strict"; + +const PAGE = "data:text/html,A%20regular,%20everyday,%20normal%20page."; + +/** + * Monkey patches TabCrashHandler.getDumpID to return null in order to test + * about:tabcrashed when a dump is not available. + */ +add_task(function* setup() { + let originalGetDumpID = TabCrashHandler.getDumpID; + TabCrashHandler.getDumpID = function(browser) { return null; }; + registerCleanupFunction(() => { + TabCrashHandler.getDumpID = originalGetDumpID; + }); +}); + +/** + * Tests tab crash page when a dump is not available. + */ +add_task(function* test_without_dump() { + return BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, function*(browser) { + let tab = gBrowser.getTabForBrowser(browser); + yield BrowserTestUtils.crashBrowser(browser); + + let tabRemovedPromise = BrowserTestUtils.removeTab(tab, { dontRemove: true }); + + yield ContentTask.spawn(browser, null, function*() { + let doc = content.document; + ok(!doc.documentElement.classList.contains("crashDumpAvailable"), + "doesn't have crash dump"); + + let container = doc.getElementById("crash-reporter-container"); + ok(container, "has crash-reporter-container"); + ok(container.hidden, "crash-reporter-container is hidden"); + + doc.getElementById("closeTab").click(); + }); + + yield tabRemovedPromise; + }); +}); diff --git a/browser/modules/ContentCrashHandlers.jsm b/browser/modules/ContentCrashHandlers.jsm index 336dc8ff2c4..4ebef698e5b 100644 --- a/browser/modules/ContentCrashHandlers.jsm +++ b/browser/modules/ContentCrashHandlers.jsm @@ -228,7 +228,7 @@ this.TabCrashHandler = { let dumpID = this.getDumpID(browser); if (!dumpID) { - message.target.sendAsyncMessge("SetCrashReportAvailable", { + message.target.sendAsyncMessage("SetCrashReportAvailable", { hasReport: false, }); return; From 960f959f7d0740b64eb220e74e3095a0306f0fa0 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Wed, 3 Feb 2016 18:21:31 +0200 Subject: [PATCH 065/160] Bug 1233702 - Remove dom.permissions.enabled pref. r=baku --- dom/permission/tests/test_permissions_api.html | 11 +---------- dom/webidl/Navigator.webidl | 2 +- dom/webidl/PermissionStatus.webidl | 3 +-- dom/webidl/Permissions.webidl | 3 +-- modules/libpref/init/all.js | 3 --- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/dom/permission/tests/test_permissions_api.html b/dom/permission/tests/test_permissions_api.html index c936b46e91a..5cced3597af 100644 --- a/dom/permission/tests/test_permissions_api.html +++ b/dom/permission/tests/test_permissions_api.html @@ -31,14 +31,6 @@ const UNSUPPORTED_PERMISSIONS = [ 'midi' ]; -function setup() { - return new Promise((resolve, reject) => { - SpecialPowers.pushPrefEnv({'set': [ - ['dom.permissions.enabled', true], - ]}, resolve); - }); -} - function setPermissions(action) { let permissions = PERMISSIONS.map(x => { return { 'type': x.perm, 'allow': action, 'context': document }; @@ -111,8 +103,7 @@ function testInvalidQuery() { } function runTests() { - setup() - .then(checkUnsupportedPermissions) + checkUnsupportedPermissions() .then(checkUserVisiblePushPermission) .then(() => setPermissions(UNKNOWN_ACTION)) .then(() => checkPermissions('prompt')) diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index cb08be68149..74ee74909e5 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -100,7 +100,7 @@ interface NavigatorFeatures { }; partial interface Navigator { - [Throws, Pref="dom.permissions.enabled"] + [Throws] readonly attribute Permissions permissions; }; diff --git a/dom/webidl/PermissionStatus.webidl b/dom/webidl/PermissionStatus.webidl index 27ae490c391..3abfd66f407 100644 --- a/dom/webidl/PermissionStatus.webidl +++ b/dom/webidl/PermissionStatus.webidl @@ -13,8 +13,7 @@ enum PermissionState { "prompt" }; -[Exposed=(Window), - Pref="dom.permissions.enabled"] +[Exposed=(Window)] interface PermissionStatus : EventTarget { readonly attribute PermissionState state; attribute EventHandler onchange; diff --git a/dom/webidl/Permissions.webidl b/dom/webidl/Permissions.webidl index 776a22ff843..17574c75e59 100644 --- a/dom/webidl/Permissions.webidl +++ b/dom/webidl/Permissions.webidl @@ -22,8 +22,7 @@ dictionary PushPermissionDescriptor : PermissionDescriptor { boolean userVisible = false; }; -[Exposed=(Window), - Pref="dom.permissions.enabled"] +[Exposed=(Window)] interface Permissions { [Throws] Promise query(object permission); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index e09bbb2e223..d513194bff5 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -129,9 +129,6 @@ pref("dom.indexedDB.logging.profiler-marks", false); // Whether or not File Handle is enabled. pref("dom.fileHandle.enabled", true); -// Whether or not the Permissions API is enabled. -pref("dom.permissions.enabled", true); - // Whether or not selection events are enabled #ifdef NIGHTLY_BUILD pref("dom.select_events.enabled", true); From 2646f6a420068a8a2ca907b6f2c1967afec15262 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 08:30:14 -0800 Subject: [PATCH 066/160] Bug 1183754, part 1 - Get rid of aligned spacing for XPCWrappedNative fields. r=bholley --- js/xpconnect/src/xpcprivate.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 00646467b0b..b9c15e6067d 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -2268,12 +2268,12 @@ public: private: union { - XPCWrappedNativeScope* mMaybeScope; - XPCWrappedNativeProto* mMaybeProto; + XPCWrappedNativeScope* mMaybeScope; + XPCWrappedNativeProto* mMaybeProto; }; - XPCNativeSet* mSet; - JS::TenuredHeap mFlatJSObject; - XPCNativeScriptableInfo* mScriptableInfo; + XPCNativeSet* mSet; + JS::TenuredHeap mFlatJSObject; + XPCNativeScriptableInfo* mScriptableInfo; XPCWrappedNativeTearOffChunk mFirstChunk; }; From 8ac50e0323b4bed03dec56af6e127d09aa34ddca Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 08:30:14 -0800 Subject: [PATCH 067/160] Bug 1183754, part 2 - Remove clearing of the next chunk. r=bholley The list of chunks will already be destroyed by the dtor. --- js/xpconnect/src/XPCWrappedNative.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 9a3aae5b7d9..82ce20e6e86 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -971,7 +971,7 @@ XPCWrappedNative::SystemIsBeingShutDown() // We leak mIdentity (see above). - // short circuit future finalization + // Short circuit future finalization. JS_SetPrivate(mFlatJSObject, nullptr); mFlatJSObject = nullptr; mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID); @@ -987,8 +987,7 @@ XPCWrappedNative::SystemIsBeingShutDown() delete mScriptableInfo; } - // cleanup the tearoffs... - + // Cleanup the tearoffs. XPCWrappedNativeTearOffChunk* chunk; for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { XPCWrappedNativeTearOff* to = &chunk->mTearOff; @@ -1001,11 +1000,6 @@ XPCWrappedNative::SystemIsBeingShutDown() Unused << to->TakeNative().take(); to->SetInterface(nullptr); } - - if (mFirstChunk.mNextChunk) { - delete mFirstChunk.mNextChunk; - mFirstChunk.mNextChunk = nullptr; - } } /***************************************************************************/ From b74455c3aaadaa4342e2cb3078eb95d6776adbd5 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 08:30:14 -0800 Subject: [PATCH 068/160] Bug 1183754, part 3 - Use a UniquePtr for XPCWrappedNativeChunk::mNextChunk. r=bholley --- js/xpconnect/src/XPCInlines.h | 2 +- js/xpconnect/src/XPCWrappedNative.cpp | 13 ++++++------- js/xpconnect/src/xpcprivate.h | 9 +++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h index b33eba5146a..d43167d291e 100644 --- a/js/xpconnect/src/XPCInlines.h +++ b/js/xpconnect/src/XPCInlines.h @@ -538,7 +538,7 @@ inline void XPCWrappedNative::SweepTearOffs() { XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { + for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { XPCWrappedNativeTearOff* to = &chunk->mTearOff; bool marked = to->IsMarked(); to->Unmark(); diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index 82ce20e6e86..b3f9dfbe2da 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -114,7 +114,7 @@ XPCWrappedNative::NoteTearoffs(nsCycleCollectionTraversalCallback& cb) // then the tearoff is only reachable through the XPCWrappedNative, so we // record an edge here. XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { + for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { XPCWrappedNativeTearOff* to = &chunk->mTearOff; JSObject* jso = to->GetJSObjectPreserveColor(); if (!jso) { @@ -899,7 +899,7 @@ XPCWrappedNative::FlatJSObjectFinalized() // JSObjects are about to be finalized too. XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { + for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { XPCWrappedNativeTearOff* to = &chunk->mTearOff; JSObject* jso = to->GetJSObjectPreserveColor(); if (jso) { @@ -989,7 +989,7 @@ XPCWrappedNative::SystemIsBeingShutDown() // Cleanup the tearoffs. XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk) { + for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { XPCWrappedNativeTearOff* to = &chunk->mTearOff; if (JSObject* jso = to->GetJSObjectPreserveColor()) { JS_SetPrivate(jso, nullptr); @@ -1056,7 +1056,7 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface, XPCWrappedNativeTearOffChunk* chunk; for (lastChunk = chunk = &mFirstChunk; chunk; - lastChunk = chunk, chunk = chunk->mNextChunk) { + lastChunk = chunk, chunk = chunk->mNextChunk.get()) { to = &chunk->mTearOff; if (to->GetInterface() == aInterface) { if (needJSObject && !to->GetJSObjectPreserveColor()) { @@ -1083,9 +1083,8 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface, to = firstAvailable; if (!to) { - auto newChunk = new XPCWrappedNativeTearOffChunk(); - lastChunk->mNextChunk = newChunk; - to = &newChunk->mTearOff; + lastChunk->mNextChunk = MakeUnique(); + to = &lastChunk->mNextChunk->mTearOff; } { diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index b9c15e6067d..cfbccf5d782 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -85,6 +85,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Preferences.h" #include "mozilla/TimeStamp.h" +#include "mozilla/UniquePtr.h" #include "mozilla/dom/ScriptSettings.h" @@ -1992,13 +1993,13 @@ private: class XPCWrappedNativeTearOffChunk { friend class XPCWrappedNative; -private: - XPCWrappedNativeTearOffChunk() : mNextChunk(nullptr) {} - ~XPCWrappedNativeTearOffChunk() {delete mNextChunk;} +public: + XPCWrappedNativeTearOffChunk() {} + ~XPCWrappedNativeTearOffChunk() {} private: XPCWrappedNativeTearOff mTearOff; - XPCWrappedNativeTearOffChunk* mNextChunk; + mozilla::UniquePtr mNextChunk; }; /***************************************************************************/ From bcfc38f7a57a18db8d59f5e009690c36bfeee976 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 08:30:15 -0800 Subject: [PATCH 069/160] Bug 1183754, part 4 - Eliminate XPCWrappedNativeTearOffChunk. r=bholley --- js/xpconnect/src/XPCInlines.h | 4 +--- js/xpconnect/src/XPCWrappedNative.cpp | 25 ++++++++--------------- js/xpconnect/src/xpcprivate.h | 29 ++++++++++----------------- 3 files changed, 20 insertions(+), 38 deletions(-) diff --git a/js/xpconnect/src/XPCInlines.h b/js/xpconnect/src/XPCInlines.h index d43167d291e..9ad7d7ac468 100644 --- a/js/xpconnect/src/XPCInlines.h +++ b/js/xpconnect/src/XPCInlines.h @@ -537,9 +537,7 @@ XPCWrappedNative::HasInterfaceNoQI(const nsIID& iid) inline void XPCWrappedNative::SweepTearOffs() { - XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { - XPCWrappedNativeTearOff* to = &chunk->mTearOff; + for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { bool marked = to->IsMarked(); to->Unmark(); if (marked) diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index b3f9dfbe2da..5d0ba354295 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -113,9 +113,7 @@ XPCWrappedNative::NoteTearoffs(nsCycleCollectionTraversalCallback& cb) // (see nsXPConnect::Traverse), but if their JS object has been finalized // then the tearoff is only reachable through the XPCWrappedNative, so we // record an edge here. - XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { - XPCWrappedNativeTearOff* to = &chunk->mTearOff; + for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { JSObject* jso = to->GetJSObjectPreserveColor(); if (!jso) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "tearoff's mNative"); @@ -898,9 +896,7 @@ XPCWrappedNative::FlatJSObjectFinalized() // dying tearoff object. We can safely assume that those remaining // JSObjects are about to be finalized too. - XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { - XPCWrappedNativeTearOff* to = &chunk->mTearOff; + for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { JSObject* jso = to->GetJSObjectPreserveColor(); if (jso) { JS_SetPrivate(jso, nullptr); @@ -988,9 +984,7 @@ XPCWrappedNative::SystemIsBeingShutDown() } // Cleanup the tearoffs. - XPCWrappedNativeTearOffChunk* chunk; - for (chunk = &mFirstChunk; chunk; chunk = chunk->mNextChunk.get()) { - XPCWrappedNativeTearOff* to = &chunk->mTearOff; + for (XPCWrappedNativeTearOff* to = &mFirstTearOff; to; to = to->GetNextTearOff()) { if (JSObject* jso = to->GetJSObjectPreserveColor()) { JS_SetPrivate(jso, nullptr); to->SetJSObject(nullptr); @@ -1052,12 +1046,10 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface, XPCWrappedNativeTearOff* to; XPCWrappedNativeTearOff* firstAvailable = nullptr; - XPCWrappedNativeTearOffChunk* lastChunk; - XPCWrappedNativeTearOffChunk* chunk; - for (lastChunk = chunk = &mFirstChunk; - chunk; - lastChunk = chunk, chunk = chunk->mNextChunk.get()) { - to = &chunk->mTearOff; + XPCWrappedNativeTearOff* lastTearOff; + for (lastTearOff = to = &mFirstTearOff; + to; + lastTearOff = to, to = to->GetNextTearOff()) { if (to->GetInterface() == aInterface) { if (needJSObject && !to->GetJSObjectPreserveColor()) { AutoMarkingWrappedNativeTearOffPtr tearoff(cx, to); @@ -1083,8 +1075,7 @@ XPCWrappedNative::FindTearOff(XPCNativeInterface* aInterface, to = firstAvailable; if (!to) { - lastChunk->mNextChunk = MakeUnique(); - to = &lastChunk->mNextChunk->mTearOff; + to = lastTearOff->AddTearOff(); } { diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index cfbccf5d782..b3a844180d6 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -1972,6 +1972,15 @@ public: void Unmark() {mJSObject.unsetFlags(1);} bool IsMarked() const {return mJSObject.hasFlag(1);} + XPCWrappedNativeTearOff* AddTearOff() + { + MOZ_ASSERT(!mNextTearOff); + mNextTearOff = mozilla::MakeUnique(); + return mNextTearOff.get(); + } + + XPCWrappedNativeTearOff* GetNextTearOff() {return mNextTearOff.get();} + private: XPCWrappedNativeTearOff(const XPCWrappedNativeTearOff& r) = delete; XPCWrappedNativeTearOff& operator= (const XPCWrappedNativeTearOff& r) = delete; @@ -1982,25 +1991,9 @@ private: // nsISupports pointer. RefPtr mNative; JS::TenuredHeap mJSObject; + mozilla::UniquePtr mNextTearOff; }; -/***********************************************/ -// XPCWrappedNativeTearOffChunk is a linked list of XPCWrappedNativeTearOff -// objects. It lets us allocate a set of XPCWrappedNativeTearOff objects and -// link the sets - rather than only having the option of linking single -// XPCWrappedNativeTearOff objects. - -class XPCWrappedNativeTearOffChunk -{ -friend class XPCWrappedNative; -public: - XPCWrappedNativeTearOffChunk() {} - ~XPCWrappedNativeTearOffChunk() {} - -private: - XPCWrappedNativeTearOff mTearOff; - mozilla::UniquePtr mNextChunk; -}; /***************************************************************************/ // XPCWrappedNative the wrapper around one instance of a native xpcom object @@ -2275,7 +2268,7 @@ private: XPCNativeSet* mSet; JS::TenuredHeap mFlatJSObject; XPCNativeScriptableInfo* mScriptableInfo; - XPCWrappedNativeTearOffChunk mFirstChunk; + XPCWrappedNativeTearOff mFirstTearOff; }; /*************************************************************************** From f144d8e7c4761d0d042935487d3613bf32212247 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 08:30:15 -0800 Subject: [PATCH 070/160] Bug 1063569 - Enable devicestorage test_dirs.html. r=dhylands --- dom/devicestorage/test/mochitest.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/dom/devicestorage/test/mochitest.ini b/dom/devicestorage/test/mochitest.ini index cee91b441da..a2367739f9c 100644 --- a/dom/devicestorage/test/mochitest.ini +++ b/dom/devicestorage/test/mochitest.ini @@ -10,7 +10,6 @@ support-files = devicestorage_common.js [test_available.html] [test_basic.html] [test_dirs.html] -skip-if = e10s # Bug 1063569. # [test_diskSpace.html] # Possible race between the time we write a file, and the # time it takes to be reflected by statfs(). Bug # 791287 From aa9e0839184a72833c433a708c83393c0e8128fc Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 3 Feb 2016 16:39:18 +0000 Subject: [PATCH 071/160] Bug 1245533 - nsXHTMLContentSerializer::CheckElementEnd - small compilation issue, r=smaug --- dom/base/nsXHTMLContentSerializer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/base/nsXHTMLContentSerializer.cpp b/dom/base/nsXHTMLContentSerializer.cpp index 12e14d3b692..ed3bb84f76c 100644 --- a/dom/base/nsXHTMLContentSerializer.cpp +++ b/dom/base/nsXHTMLContentSerializer.cpp @@ -511,7 +511,7 @@ nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent, } bool -nsXHTMLContentSerializer::CheckElementEnd(Element* aElement, +nsXHTMLContentSerializer::CheckElementEnd(mozilla::dom::Element* aElement, bool& aForceFormat, nsAString& aStr) { From 55737a549108eb7b266a1d1a71d13146d4e8d02e Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Wed, 3 Feb 2016 18:43:05 +0100 Subject: [PATCH 072/160] Bug 1229348 - Add a "valgrind-plain" suite to all_mochitest_suites. r=cmanchester. --- testing/mochitest/mochitest_options.py | 13 +++++++++++++ testing/mochitest/moz.build | 3 +++ .../configs/unittests/linux_unittest.py | 15 +++++++++++++++ testing/mozharness/mach_commands.py | 5 +++++ .../mozharness/mozilla/testing/errors.py | 7 +------ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/testing/mochitest/mochitest_options.py b/testing/mochitest/mochitest_options.py index 26ffd76dce9..5435bccdd1f 100644 --- a/testing/mochitest/mochitest_options.py +++ b/testing/mochitest/mochitest_options.py @@ -33,6 +33,19 @@ except ImportError: def get_default_valgrind_suppression_files(): # We are trying to locate files in the source tree. So if we # don't know where the source tree is, we must give up. + # + # When this is being run by |mach mochitest --valgrind ...|, it is + # expected that |build_obj| is not None, and so the logic below will + # select the correct suppression files. + # + # When this is run from mozharness, |build_obj| is None, and we expect + # that testing/mozharness/configs/unittests/linux_unittests.py will + # select the correct suppression files (and paths to them) and + # will specify them using the --valgrind-supp-files= flag. Hence this + # function will not get called when running from mozharness. + # + # Note: keep these Valgrind .sup file names consistent with those + # in testing/mozharness/configs/unittests/linux_unittest.py. if build_obj is None or build_obj.topsrcdir is None: return [] diff --git a/testing/mochitest/moz.build b/testing/mochitest/moz.build index ea1a8bb0da9..a65aa717a9a 100644 --- a/testing/mochitest/moz.build +++ b/testing/mochitest/moz.build @@ -29,6 +29,9 @@ TEST_HARNESS_FILES.testing.mochitest += [ '/build/mobile/remoteautomation.py', '/build/pgo/server-locations.txt', '/build/sanitizers/lsan_suppressions.txt', + '/build/valgrind/cross-architecture.sup', + '/build/valgrind/i386-redhat-linux-gnu.sup', + '/build/valgrind/x86_64-redhat-linux-gnu.sup', '/netwerk/test/httpserver/httpd.js', '/testing/mozbase/mozdevice/mozdevice/devicemanager.py', '/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py', diff --git a/testing/mozharness/configs/unittests/linux_unittest.py b/testing/mozharness/configs/unittests/linux_unittest.py index ade9385acea..6ab0aeb1960 100644 --- a/testing/mozharness/configs/unittests/linux_unittest.py +++ b/testing/mozharness/configs/unittests/linux_unittest.py @@ -9,12 +9,24 @@ XPCSHELL_NAME = "xpcshell" EXE_SUFFIX = "" DISABLE_SCREEN_SAVER = True ADJUST_MOUSE_AND_SCREEN = False + +# Note: keep these Valgrind .sup file names consistent with those +# in testing/mochitest/mochitest_options.py. +VALGRIND_SUPP_DIR = os.path.join(os.getcwd(), "build/tests/mochitest") +VALGRIND_SUPP_CROSS_ARCH = os.path.join(VALGRIND_SUPP_DIR, + "cross-architecture.sup") +VALGRIND_SUPP_ARCH = None + if platform.architecture()[0] == "64bit": TOOLTOOL_MANIFEST_PATH = "config/tooltool-manifests/linux64/releng.manifest" MINIDUMP_STACKWALK_PATH = "linux64-minidump_stackwalk" + VALGRIND_SUPP_ARCH = os.path.join(VALGRIND_SUPP_DIR, + "x86_64-redhat-linux-gnu.sup") else: TOOLTOOL_MANIFEST_PATH = "config/tooltool-manifests/linux32/releng.manifest" MINIDUMP_STACKWALK_PATH = "linux32-minidump_stackwalk" + VALGRIND_SUPP_ARCH = os.path.join(VALGRIND_SUPP_DIR, + "i386-redhat-linux-gnu.sup") ##### config = { @@ -188,6 +200,9 @@ config = { }, # local mochi suites "all_mochitest_suites": { + "valgrind-plain": ["--valgrind=/usr/bin/valgrind", + "--valgrind-supp-files=" + VALGRIND_SUPP_ARCH + + "," + VALGRIND_SUPP_CROSS_ARCH], "plain": [], "plain-chunked": ["--chunk-by-dir=4"], "mochitest-push": ["--subsuite=push"], diff --git a/testing/mozharness/mach_commands.py b/testing/mozharness/mach_commands.py index 1115cb96949..91388480c50 100644 --- a/testing/mozharness/mach_commands.py +++ b/testing/mozharness/mach_commands.py @@ -53,6 +53,11 @@ class MozharnessRunner(MozbuildObject): "--test-packages-url", self.test_packages_url] }, + "mochitest-valgrind": { + "script": "desktop_unittest.py", + "config": desktop_unittest_config + [ + "--mochitest-suite", "valgrind-plain"] + }, "mochitest": { "script": "desktop_unittest.py", "config": desktop_unittest_config + [ diff --git a/testing/mozharness/mozharness/mozilla/testing/errors.py b/testing/mozharness/mozharness/mozilla/testing/errors.py index 09e1353b6ed..d0acd29ad53 100644 --- a/testing/mozharness/mozharness/mozilla/testing/errors.py +++ b/testing/mozharness/mozharness/mozilla/testing/errors.py @@ -88,14 +88,9 @@ TinderBoxPrintRe = { "harness_error": { 'full_regex': re.compile(r"(?:TEST-UNEXPECTED-FAIL|PROCESS-CRASH) \| .* \| (application crashed|missing output line for total leaks!|negative leaks caught!|\d+ bytes leaked)"), - 'minimum_regex': re.compile(r'''(TEST-UNEXPECTED|PROCESS-CRASH)'''), + 'minimum_regex': re.compile(r'''(TEST-UNEXPECTED|PROCESS-CRASH|TEST-VALGRIND-ERROR)'''), 'retry_regex': re.compile(r'''FAIL-SHOULD-RETRY''') }, - "valgrind_error": { - 'substr': 'TEST-VALGRIND-ERROR', - 'level': ERROR, - 'explanation': 'Valgrind detected memory errors during the run' - }, } TestPassed = [ From 56f6791f9b3e394bcceb3d3fc573c7a55ee1c80a Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Wed, 3 Feb 2016 10:00:11 -0800 Subject: [PATCH 073/160] Bug 1245513 - Use _exit(0) to exit in B2G debug content processes. r=froydnj This skips destructors, so hopefully it avoids some odd behaviors. --- xpcom/build/XPCOMInit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index 35e9561e295..08d9583020a 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -1042,13 +1042,13 @@ ShutdownXPCOM(nsIServiceManager* aServMgr) NS_LogTerm(); #if defined(MOZ_WIDGET_GONK) - // This exit(0) call is intended to be temporary, to get shutdown leak - // checking working on Linux. + // This _exit(0) call is intended to be temporary, to get shutdown leak + // checking working on non-B2G platforms. // On debug B2G, the child process crashes very late. Instead, just // give up so at least we exit cleanly. See bug 1071866. if (XRE_IsContentProcess()) { NS_WARNING("Exiting child process early!"); - exit(0); + _exit(0); } #endif From 5282989f60ecf5fc608a1878032bfafaa6e86a0d Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 2 Feb 2016 14:05:23 -0800 Subject: [PATCH 074/160] Bug 1242173 - Typing in input fields does not visually update r= --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 51ae4c49be8..7e639c0008d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2887,6 +2887,7 @@ AsyncPanZoomController::RequestContentRepaint(const FrameMetrics& aFrameMetrics, aFrameMetrics.GetScrollOffset().x) < EPSILON && fabsf(mLastPaintRequestMetrics.GetScrollOffset().y - aFrameMetrics.GetScrollOffset().y) < EPSILON && + aFrameMetrics.GetPresShellResolution() == mLastPaintRequestMetrics.GetPresShellResolution() && aFrameMetrics.GetZoom() == mLastPaintRequestMetrics.GetZoom() && fabsf(aFrameMetrics.GetViewport().width - mLastPaintRequestMetrics.GetViewport().width) < EPSILON && @@ -3315,6 +3316,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri / mFrameMetrics.GetCumulativeResolution(); float presShellResolutionChange = aLayerMetrics.GetPresShellResolution() / mFrameMetrics.GetPresShellResolution(); + if (presShellResolutionChange != 1.0f) { + needContentRepaint = true; + } mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange); } else { // Take the new zoom as either device scale or composition width or From 156fd2f43b0123675fee6c9b1dbc2869f94e6598 Mon Sep 17 00:00:00 2001 From: Geoff Brown Date: Wed, 3 Feb 2016 11:13:50 -0700 Subject: [PATCH 075/160] Bug 1233220 - Add README for test_awsy_lite data; r=me DONTBUILD NPOTB --- mobile/android/tests/browser/chrome/tp5/README | 1 + 1 file changed, 1 insertion(+) create mode 100644 mobile/android/tests/browser/chrome/tp5/README diff --git a/mobile/android/tests/browser/chrome/tp5/README b/mobile/android/tests/browser/chrome/tp5/README new file mode 100644 index 00000000000..c733fb4c031 --- /dev/null +++ b/mobile/android/tests/browser/chrome/tp5/README @@ -0,0 +1 @@ +This directory contains pages and other resources downloaded from the web for the purpose of testing against pages from the real world. Pages are copied from the Talos tp5 data -- see https://wiki.mozilla.org/Buildbot/Talos/Tests#tp5. These files are not made available under an open source license. From bfe12e3b5a9627441d2ba75f2c81f7caebfdadd3 Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Wed, 3 Feb 2016 19:44:41 +0100 Subject: [PATCH 076/160] Bug 1245525: Fix some compiler errors in Moz2D type classes. r=jrmuizel --- gfx/2d/BaseMargin.h | 8 ++++---- gfx/2d/Matrix.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gfx/2d/BaseMargin.h b/gfx/2d/BaseMargin.h index 28bc648c5de..a4ef5fe2424 100644 --- a/gfx/2d/BaseMargin.h +++ b/gfx/2d/BaseMargin.h @@ -21,10 +21,10 @@ struct Sides final { mBits = aSideBits; } bool IsEmpty() const { return mBits == 0; } - bool Top() const { return mBits & eSideBitsTop; } - bool Right() const { return mBits & eSideBitsRight; } - bool Bottom() const { return mBits & eSideBitsBottom; } - bool Left() const { return mBits & eSideBitsLeft; } + bool Top() const { return (mBits & eSideBitsTop) != 0; } + bool Right() const { return (mBits & eSideBitsRight) != 0; } + bool Bottom() const { return (mBits & eSideBitsBottom) != 0; } + bool Left() const { return (mBits & eSideBitsLeft) != 0; } bool Contains(SideBits aSideBits) const { MOZ_ASSERT((aSideBits & ~eSideBitsAll) == 0, "illegal side bits"); diff --git a/gfx/2d/Matrix.h b/gfx/2d/Matrix.h index 53203477b70..1bd826bedcc 100644 --- a/gfx/2d/Matrix.h +++ b/gfx/2d/Matrix.h @@ -298,8 +298,8 @@ public: */ bool HasNonIntegerTranslation() const { return HasNonTranslation() || - !FuzzyEqual(_31, floor(_31 + 0.5)) || - !FuzzyEqual(_32, floor(_32 + 0.5)); + !FuzzyEqual(_31, floor(_31 + Float(0.5))) || + !FuzzyEqual(_32, floor(_32 + Float(0.5))); } /** From 65ab2dc8d1f0d116cd28a933e7e228038f638ac2 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 3 Feb 2016 11:01:06 -0800 Subject: [PATCH 077/160] Bug 1232229 - Add some instrumentation and more fencing to ArenaLists; r=ehoogeveen --- js/src/jsgc.cpp | 1 + js/src/jsgc.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 25fa074500a..19add8094e3 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3410,6 +3410,7 @@ GCRuntime::sweepBackgroundThings(ZoneList& zones, LifoAlloc& freeBlocks, ThreadT for (unsigned index = 0 ; index < BackgroundFinalizePhases[phase].length ; ++index) { AllocKind kind = BackgroundFinalizePhases[phase].kinds[index]; ArenaHeader* arenas = zone->arenas.arenaListsToSweep[kind]; + MOZ_RELEASE_ASSERT(uintptr_t(arenas) != uintptr_t(-1)); if (arenas) ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 2ceaa7bbdd4..54ce98097d8 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -594,7 +594,7 @@ class ArenaLists enum BackgroundFinalizeStateEnum { BFS_DONE, BFS_RUN }; - typedef mozilla::Atomic + typedef mozilla::Atomic BackgroundFinalizeState; /* The current background finalization state, accessed atomically. */ From b1524cf4f7dc8e591e663a05968584391ba0e89f Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Tue, 26 Jan 2016 15:54:25 -0500 Subject: [PATCH 078/160] bug 277813 - autogenerated expires needs max r=mayhemer --- netwerk/protocol/http/nsHttpResponseHead.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp index 1fb68c3371a..61ae865848f 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.cpp +++ b/netwerk/protocol/http/nsHttpResponseHead.cpp @@ -415,7 +415,7 @@ nsHttpResponseHead::ComputeCurrentAge(uint32_t now, // // freshnessLifetime = expires_value - date_value // -// freshnessLifetime = (date_value - last_modified_value) * 0.10 +// freshnessLifetime = min(one-week,(date_value - last_modified_value) * 0.10) // // freshnessLifetime = 0 // @@ -463,6 +463,8 @@ nsHttpResponseHead::ComputeFreshnessLifetime(uint32_t *result) const if (date2 <= date) { // this only makes sense if last-modified is actually in the past *result = (date - date2) / 10; + const uint32_t kOneWeek = 60 * 60 * 24 * 7; + *result = std::min(kOneWeek, *result); return NS_OK; } } From 36b26b66da791e603a0769300816f2fa635296e0 Mon Sep 17 00:00:00 2001 From: Andrew Sutherland Date: Thu, 28 Jan 2016 14:25:46 -0500 Subject: [PATCH 079/160] Bug 345580 - Problem decoding quoted-printable question mark in subject r=biesi --- netwerk/mime/nsMIMEHeaderParamImpl.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/netwerk/mime/nsMIMEHeaderParamImpl.cpp b/netwerk/mime/nsMIMEHeaderParamImpl.cpp index 2c42afa487b..362ff1f6abf 100644 --- a/netwerk/mime/nsMIMEHeaderParamImpl.cpp +++ b/netwerk/mime/nsMIMEHeaderParamImpl.cpp @@ -1238,13 +1238,14 @@ nsresult DecodeRFC2047Str(const char *aHeader, const char *aDefaultCharset, if (q[1] != '?') goto badsyntax; - r = q; - for (r = q + 2; *r != '?'; r++) { + // loop-wise, keep going until we hit "?=". the inner check handles the + // nul terminator should the string terminate before we hit the right + // marker. (And the r[1] will never reach beyond the end of the string + // because *r != '?' is true if r is the nul character.) + for (r = q + 2; *r != '?' || r[1] != '='; r++) { if (*r < ' ') goto badsyntax; } - if (r[1] != '=') - goto badsyntax; - else if (r == q + 2) { + if (r == q + 2) { // it's empty, skip begin = r + 2; isLastEncodedWord = 1; From ae96657c3db1db9ce92eacccbdd69835a5cdd118 Mon Sep 17 00:00:00 2001 From: "sayre@gmail.com" Date: Wed, 3 Feb 2016 13:47:20 -0500 Subject: [PATCH 080/160] Bug 407537 - Dont normalize a nonexistant file r=biesi --- netwerk/base/nsFileStreams.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/netwerk/base/nsFileStreams.cpp b/netwerk/base/nsFileStreams.cpp index 31f1cca1d29..e15bd94f6a2 100644 --- a/netwerk/base/nsFileStreams.cpp +++ b/netwerk/base/nsFileStreams.cpp @@ -929,7 +929,9 @@ nsAtomicFileOutputStream::DoOpen() tempResult->SetFollowLinks(true); // XP_UNIX ignores SetFollowLinks(), so we have to normalize. - tempResult->Normalize(); + if (mTargetFileExists) { + tempResult->Normalize(); + } } if (NS_SUCCEEDED(rv) && mTargetFileExists) { From aecd8938e47b08413cf77659f06f8eb2ecdbeec2 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 14:07:33 -0500 Subject: [PATCH 081/160] Bug 1245245 - Fix typo in error string URL. r=botond --- dom/base/nsDocument.cpp | 2 +- dom/locales/en-US/chrome/layout/layout_errors.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index fc8826eefc3..d4a88f29718 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -13413,5 +13413,5 @@ nsIDocument::ReportHasScrollLinkedEffect() nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Async Pan/Zoom"), this, nsContentUtils::eLAYOUT_PROPERTIES, - "ScrollLinkedEffectFound"); + "ScrollLinkedEffectFound2"); } diff --git a/dom/locales/en-US/chrome/layout/layout_errors.properties b/dom/locales/en-US/chrome/layout/layout_errors.properties index b276ea27a7f..11acea9ebbb 100644 --- a/dom/locales/en-US/chrome/layout/layout_errors.properties +++ b/dom/locales/en-US/chrome/layout/layout_errors.properties @@ -9,4 +9,4 @@ ImageMapPolyWrongNumberOfCoords=The "coords" attribute of the tag is missing the last "y" coordinate (the correct format is "x1,y1,x2,y2 …"). TablePartRelPosWarning=Relative positioning of table rows and row groups is now supported. This site may need to be updated because it may depend on this feature having no effect. -ScrollLinkedEffectFound=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developers.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features! +ScrollLinkedEffectFound2=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features! From 77edd9ba6a13c7f7054126900619a3fb39e3162e Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 14:07:45 -0500 Subject: [PATCH 082/160] Bug 1236046 - Don't use a stupidly small time delta to compute a velocity. r=botond --- gfx/layers/apz/src/Axis.cpp | 32 +++++++++++++++++++++++--------- gfx/layers/apz/src/Axis.h | 9 ++++++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index 8b9a0cd1110..7e2e54df639 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -30,6 +30,13 @@ namespace mozilla { namespace layers { +// When we compute the velocity we do so by taking two input events and +// dividing the distance delta over the time delta. In some cases the time +// delta can be really small, which can make the velocity computation very +// volatile. To avoid this we impose a minimum time delta below which we do +// not recompute the velocity. +const uint32_t MIN_VELOCITY_SAMPLE_TIME_MS = 5; + bool FuzzyEqualsCoordinate(float aValue1, float aValue2) { return FuzzyEqualsAdditive(aValue1, aValue2, COORDINATE_EPSILON) @@ -40,7 +47,8 @@ extern StaticAutoPtr gVelocityCurveFunction; Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController) : mPos(0), - mPosTimeMs(0), + mVelocitySampleTimeMs(0), + mVelocitySamplePos(0), mVelocity(0.0f), mAxisLocked(false), mAsyncPanZoomController(aAsyncPanZoomController), @@ -67,16 +75,20 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord // mVelocityQueue is controller-thread only APZThreadUtils::AssertOnControllerThread(); - if (aTimestampMs == mPosTimeMs) { - // This could be a duplicate event, or it could be a legitimate event - // on some platforms that generate events really fast. As a compromise - // update mPos so we don't run into problems like bug 1042734, even though - // that means the velocity will be stale. Better than doing a divide-by-zero. + if (aTimestampMs <= mVelocitySampleTimeMs + MIN_VELOCITY_SAMPLE_TIME_MS) { + // See also the comment on MIN_VELOCITY_SAMPLE_TIME_MS. + // We still update mPos so that the positioning is correct (and we don't run + // into problems like bug 1042734) but the velocity will remain where it was. + // In particular we don't update either mVelocitySampleTimeMs or + // mVelocitySamplePos so that eventually when we do get an event with the + // required time delta we use the corresponding distance delta as well. + AXIS_LOG("%p|%s skipping velocity computation for small time delta %dms\n", + mAsyncPanZoomController, Name(), (aTimestampMs - mVelocitySampleTimeMs)); mPos = aPos; return; } - float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs); + float newVelocity = mAxisLocked ? 0.0f : (float)(mVelocitySamplePos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mVelocitySampleTimeMs); if (gfxPrefs::APZMaxVelocity() > 0.0f) { bool velocityIsNegative = (newVelocity < 0); newVelocity = fabs(newVelocity); @@ -107,7 +119,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord mAsyncPanZoomController, Name(), newVelocity); mVelocity = newVelocity; mPos = aPos; - mPosTimeMs = aTimestampMs; + mVelocitySampleTimeMs = aTimestampMs; + mVelocitySamplePos = aPos; // Limit queue size pased on pref mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, mVelocity)); @@ -119,7 +132,8 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) { mStartPos = aPos; mPos = aPos; - mPosTimeMs = aTimestampMs; + mVelocitySampleTimeMs = aTimestampMs; + mVelocitySamplePos = aPos; mAxisLocked = false; } diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index 1da9dcf3e42..3771d45c210 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -251,7 +251,14 @@ public: protected: ParentLayerCoord mPos; - uint32_t mPosTimeMs; + + // mVelocitySampleTimeMs and mVelocitySamplePos are the time and position + // used in the last velocity sampling. They get updated when a new sample is + // taken (which may not happen on every input event, if the time delta is too + // small). + uint32_t mVelocitySampleTimeMs; + ParentLayerCoord mVelocitySamplePos; + ParentLayerCoord mStartPos; float mVelocity; // Units: ParentLayerCoords per millisecond bool mAxisLocked; // Whether movement on this axis is locked. From d2142aaa0bbc958c8f11fd6dd466b9945462d559 Mon Sep 17 00:00:00 2001 From: Morgan Phillips Date: Wed, 3 Feb 2016 10:46:27 -0600 Subject: [PATCH 083/160] Bug 1243851 - Treat enter as shift+enter if input is valid but incomplete; r=fitzgen, bgrins --- devtools/client/preferences/devtools.js | 4 ++ devtools/client/webconsole/test/browser.ini | 1 + ...webconsole_bug_585991_autocomplete_keys.js | 5 ++ .../browser_webconsole_multiline_input.js | 70 +++++++++++++++++++ devtools/client/webconsole/webconsole.js | 14 ++-- js/src/doc/Debugger/Debugger.md | 10 +++ .../tests/debug/Debugger-isCompilableUnit.js | 50 +++++++++++++ js/src/vm/Debugger.cpp | 58 ++++++++++++++- js/src/vm/Debugger.h | 2 + 9 files changed, 206 insertions(+), 8 deletions(-) create mode 100644 devtools/client/webconsole/test/browser_webconsole_multiline_input.js create mode 100644 js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js diff --git a/devtools/client/preferences/devtools.js b/devtools/client/preferences/devtools.js index a3079a1cc43..efb6dbd670d 100644 --- a/devtools/client/preferences/devtools.js +++ b/devtools/client/preferences/devtools.js @@ -291,6 +291,10 @@ pref("devtools.webconsole.persistlog", false); // any timestamps. pref("devtools.webconsole.timestampMessages", false); +// Web Console automatic multiline mode: |true| if you want incomplete statements +// to automatically trigger multiline editing (equivalent to shift + enter). +pref("devtools.webconsole.autoMultiline", true); + // The number of lines that are displayed in the web console for the Net, // CSS, JS and Web Developer categories. These defaults should be kept in sync // with DEFAULT_LOG_LIMIT in the webconsole frontend. diff --git a/devtools/client/webconsole/test/browser.ini b/devtools/client/webconsole/test/browser.ini index 2f0d875f8af..ccef9fd6f7e 100644 --- a/devtools/client/webconsole/test/browser.ini +++ b/devtools/client/webconsole/test/browser.ini @@ -329,6 +329,7 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout) [browser_webconsole_live_filtering_of_message_types.js] [browser_webconsole_live_filtering_on_search_strings.js] [browser_webconsole_message_node_id.js] +[browser_webconsole_multiline_input.js] [browser_webconsole_netlogging.js] [browser_webconsole_netlogging_basic.js] [browser_webconsole_netlogging_panel.js] diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js index f790d188ef6..38ce77c6cfc 100644 --- a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js +++ b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js @@ -7,9 +7,13 @@ const TEST_URI = "data:text/html;charset=utf-8,

    bug 585991 - autocomplete " + "popup keyboard usage test"; + +// We should turn off auto-multiline editing during these tests +const PREF_AUTO_MULTILINE = "devtools.webconsole.autoMultiline"; var HUD, popup, jsterm, inputNode, completeNode; add_task(function*() { + Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, false); yield loadTab(TEST_URI); let hud = yield openConsole(); @@ -23,6 +27,7 @@ add_task(function*() { yield popupHideAfterCompletionInText(); HUD = popup = jsterm = inputNode = completeNode = null; + Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, true); }); var consoleOpened = Task.async(function*(aHud) { diff --git a/devtools/client/webconsole/test/browser_webconsole_multiline_input.js b/devtools/client/webconsole/test/browser_webconsole_multiline_input.js new file mode 100644 index 00000000000..f3164590e63 --- /dev/null +++ b/devtools/client/webconsole/test/browser_webconsole_multiline_input.js @@ -0,0 +1,70 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* 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/. */ + +// Tests that the console waits for more input instead of evaluating +// when valid, but incomplete, statements are present upon pressing enter +// -or- when the user ends a line with shift + enter. + +"use strict"; + +const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" + + "test/test-console.html"; + +let SHOULD_ENTER_MULTILINE = [ + {input: "function foo() {" }, + {input: "var a = 1," }, + {input: "var a = 1;", shiftKey: true }, + {input: "function foo() { }", shiftKey: true }, + {input: "function" }, + {input: "(x) =>" }, + {input: "let b = {" }, + {input: "let a = [" }, + {input: "{" }, + {input: "{ bob: 3343," }, + {input: "function x(y=" }, + {input: "Array.from(" }, + // shift + enter creates a new line despite parse errors + {input: "{2,}", shiftKey: true }, +]; +let SHOULD_EXECUTE = [ + {input: "function foo() { }" }, + {input: "var a = 1;" }, + {input: "function foo() { var a = 1; }" }, + {input: '"asdf"' }, + {input: '99 + 3' }, + {input: '1, 2, 3' }, + // errors + {input: 'function f(x) { let y = 1, }' }, + {input: 'function f(x=,) {' }, + {input: '{2,}' }, +]; + +add_task(function* () { + let { tab, browser } = yield loadTab(TEST_URI); + let hud = yield openConsole(); + let inputNode = hud.jsterm.inputNode; + + for (let test of SHOULD_ENTER_MULTILINE) { + hud.jsterm.setInputValue(test.input); + EventUtils.synthesizeKey("VK_RETURN", { shiftKey: test.shiftKey }); + let inputValue = hud.jsterm.getInputValue(); + is(inputNode.selectionStart, inputNode.selectionEnd, + "selection is collapsed"); + is(inputNode.selectionStart, inputValue.length, + "caret at end of multiline input"); + let inputWithNewline = test.input + "\n"; + is(inputValue, inputWithNewline, "Input value is correct"); + } + + for (let test of SHOULD_EXECUTE) { + hud.jsterm.setInputValue(test.input); + EventUtils.synthesizeKey("VK_RETURN", { shiftKey: test.shiftKey }); + let inputValue = hud.jsterm.getInputValue(); + is(inputNode.selectionStart, 0, "selection starts/ends at 0"); + is(inputNode.selectionEnd, 0, "selection starts/ends at 0"); + is(inputValue, "", "Input value is cleared"); + } + +}); diff --git a/devtools/client/webconsole/webconsole.js b/devtools/client/webconsole/webconsole.js index b071787fb0b..c025fb63008 100644 --- a/devtools/client/webconsole/webconsole.js +++ b/devtools/client/webconsole/webconsole.js @@ -10,6 +10,7 @@ const {Cc, Ci, Cu} = require("chrome"); const {Utils: WebConsoleUtils, CONSOLE_WORKER_IDS} = require("devtools/shared/webconsole/utils"); const promise = require("promise"); +const Debugger = require("Debugger"); loader.lazyServiceGetter(this, "clipboardHelper", "@mozilla.org/widget/clipboardhelper;1", @@ -183,6 +184,7 @@ const MIN_FONT_SIZE = 10; const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout"; const PREF_PERSISTLOG = "devtools.webconsole.persistlog"; const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages"; +const PREF_AUTO_MULTILINE = "devtools.webconsole.autoMultiline"; const PREF_INPUT_HISTORY_COUNT = "devtools.webconsole.inputHistoryCount"; /** @@ -3847,11 +3849,13 @@ JSTerm.prototype = { break; } return; - } else if (event.shiftKey && - event.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) { - // shift return - // TODO: expand the inputNode height by one line - return; + } else if (event.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RETURN) { + let autoMultiline = Services.prefs.getBoolPref(PREF_AUTO_MULTILINE); + if (event.shiftKey || + (!Debugger.isCompilableUnit(inputNode.value) && autoMultiline)) { + // shift return or incomplete statement + return; + } } switch (event.keyCode) { diff --git a/js/src/doc/Debugger/Debugger.md b/js/src/doc/Debugger/Debugger.md index 8048fcd8fd7..df275002fcd 100644 --- a/js/src/doc/Debugger/Debugger.md +++ b/js/src/doc/Debugger/Debugger.md @@ -536,3 +536,13 @@ other kinds of objects. `TypeError`. Determine which global is designated by global using the same rules as [`Debugger.prototype.addDebuggee`][add]. +## Static methods of the Debugger Object + +The functions described below are not called with a `this` value. + +isCompilableUnit(source) +: Given a string of source code, designated by source, return false if + the string might become a valid JavaScript statement with the addition of + more lines. Otherwise return true. The intent is to support interactive + compilation - accumulate lines in a buffer until isCompilableUnit is true, + then pass it to the compiler. diff --git a/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js b/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js new file mode 100644 index 00000000000..d872541c191 --- /dev/null +++ b/js/src/jit-test/tests/debug/Debugger-isCompilableUnit.js @@ -0,0 +1,50 @@ +load(libdir + "asserts.js"); + +const bad_types = [ + 2112, + {geddy: "lee"}, + () => 1, + [], + Array +] + +// We only accept strings around here! +for (var badType of bad_types) { + assertThrowsInstanceOf(() => { + Debugger.isCompilableUnit(badType); + }, TypeError); +} + +const compilable_units = [ + "wubba-lubba-dub-dub", + "'Get Schwifty!'", + "1 + 2", + "function f(x) {}", + "function x(f,) {", // statements with bad syntax are always compilable + "let x = 100", + ";;;;;;;;", + "", + " ", + "\n", + "let x", +] + +const non_compilable_units = [ + "function f(x) {", + "(...d) =>", + "{geddy:", + "{", + "[1, 2", + "[", + "1 +", + "let x =", + "3 ==", +] + +for (var code of compilable_units) { + assertEq(Debugger.isCompilableUnit(code), true); +} + +for (var code of non_compilable_units) { + assertEq(Debugger.isCompilableUnit(code), false); +} diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index cd5d41996f0..f9f832e5ac3 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -19,6 +19,7 @@ #include "jswrapper.h" #include "frontend/BytecodeCompiler.h" +#include "frontend/Parser.h" #include "gc/Marking.h" #include "jit/BaselineDebugModeOSR.h" #include "jit/BaselineJIT.h" @@ -4522,6 +4523,53 @@ Debugger::endTraceLogger(JSContext* cx, unsigned argc, Value* vp) return true; } +bool +Debugger::isCompilableUnit(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (!args[0].isString()) { + JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, + JSMSG_NOT_EXPECTED_TYPE, "Debugger.isCompilableUnit", + "string", InformalValueTypeName(args[0])); + return false; + } + + JSString* str = args[0].toString(); + size_t length = GetStringLength(str); + + AutoStableStringChars chars(cx); + if (!chars.initTwoByte(cx, str)) + return false; + + bool result = true; + + CompileOptions options(cx); + frontend::Parser parser(cx, &cx->tempLifoAlloc(), + options, chars.twoByteChars(), + length, /* foldConstants = */ true, + nullptr, nullptr); + JSErrorReporter older = JS_SetErrorReporter(cx->runtime(), nullptr); + if (!parser.checkOptions() || !parser.parse()) { + // We ran into an error. If it was because we ran out of memory we report + // it in the usual way. + if (cx->isThrowingOutOfMemory()) { + JS_SetErrorReporter(cx->runtime(), older); + return false; + } + + // If it was because we ran out of source, we return false so our caller + // knows to try to collect more [source]. + if (parser.isUnexpectedEOF()) + result = false; + + cx->clearPendingException(); + } + JS_SetErrorReporter(cx->runtime(), older); + args.rval().setBoolean(result); + return true; +} + bool Debugger::drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp) { @@ -4643,7 +4691,11 @@ const JSFunctionSpec Debugger::methods[] = { JS_FS_END }; - +const JSFunctionSpec Debugger::static_methods[] { + JS_FN("isCompilableUnit", Debugger::isCompilableUnit, 1, 0), + JS_FS_END +}; + /*** Debugger.Script *****************************************************************************/ static inline JSScript* @@ -8415,8 +8467,8 @@ JS_DefineDebuggerObject(JSContext* cx, HandleObject obj) return false; debugProto = InitClass(cx, obj, objProto, &Debugger::jsclass, Debugger::construct, - 1, Debugger::properties, Debugger::methods, nullptr, nullptr, - debugCtor.address()); + 1, Debugger::properties, Debugger::methods, nullptr, + Debugger::static_methods, debugCtor.address()); if (!debugProto) return false; diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 1acd3e1ec69..bee5e81741f 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -564,6 +564,7 @@ class Debugger : private mozilla::LinkedListElement static bool drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp); static bool startTraceLogger(JSContext* cx, unsigned argc, Value* vp); static bool endTraceLogger(JSContext* cx, unsigned argc, Value* vp); + static bool isCompilableUnit(JSContext* cx, unsigned argc, Value* vp); #ifdef NIGHTLY_BUILD static bool setupTraceLogger(JSContext* cx, unsigned argc, Value* vp); static bool drainTraceLogger(JSContext* cx, unsigned argc, Value* vp); @@ -571,6 +572,7 @@ class Debugger : private mozilla::LinkedListElement static bool construct(JSContext* cx, unsigned argc, Value* vp); static const JSPropertySpec properties[]; static const JSFunctionSpec methods[]; + static const JSFunctionSpec static_methods[]; static void removeFromFrameMapsAndClearBreakpointsIn(JSContext* cx, AbstractFramePtr frame); static bool updateExecutionObservabilityOfFrames(JSContext* cx, const ExecutionObservableSet& obs, From 2b932ae233c88e76d648d4c1cca58a32ea02ee90 Mon Sep 17 00:00:00 2001 From: Masatoshi Kimura Date: Thu, 4 Feb 2016 04:13:13 +0900 Subject: [PATCH 084/160] Bug 1243507 - Reimplement non-Unicode clipboard formats as bug 943294 broke drag and drop between some Unicode-unaware apps. r=jimm --- widget/windows/nsClipboard.cpp | 92 +++++++++++++++++++++++++++++++--- widget/windows/nsDataObj.cpp | 22 +++++++- 2 files changed, 107 insertions(+), 7 deletions(-) diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp index 67cdee82ea8..a98f384ba82 100644 --- a/widget/windows/nsClipboard.cpp +++ b/widget/windows/nsClipboard.cpp @@ -92,8 +92,9 @@ UINT nsClipboard::GetFormat(const char* aMimeStr) { UINT format; - if (strcmp(aMimeStr, kTextMime) == 0 || - strcmp(aMimeStr, kUnicodeMime) == 0) + if (strcmp(aMimeStr, kTextMime) == 0) + format = CF_TEXT; + else if (strcmp(aMimeStr, kUnicodeMime) == 0) format = CF_UNICODETEXT; else if (strcmp(aMimeStr, kRTFMime) == 0) format = ::RegisterClipboardFormat(L"Rich Text Format"); @@ -179,7 +180,14 @@ nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDa // Do various things internal to the implementation, like map one // flavor to another or add additional flavors based on what's required // for the win32 impl. - if ( strcmp(flavorStr, kHTMLMime) == 0 ) { + if ( strcmp(flavorStr, kUnicodeMime) == 0 ) { + // if we find text/unicode, also advertise text/plain (which we will convert + // on our own in nsDataObj::GetText(). + FORMATETC textFE; + SET_FORMATETC(textFE, CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL); + dObj->AddDataFlavor(kTextMime, &textFE); + } + else if ( strcmp(flavorStr, kHTMLMime) == 0 ) { // if we find text/html, also advertise win32's html flavor (which we will convert // on our own in nsDataObj::GetText(). FORMATETC htmlFE; @@ -191,10 +199,14 @@ nsresult nsClipboard::SetupNativeDataObject(nsITransferable * aTransferable, IDa // the "file" flavors so that the win32 shell knows to create an internet // shortcut when it sees one of these beasts. FORMATETC shortcutFE; + SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) + dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_FILECONTENTS), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); + SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLA), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) + dObj->AddDataFlavor(kURLMime, &shortcutFE); SET_FORMATETC(shortcutFE, ::RegisterClipboardFormat(CFSTR_INETURLW), 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL) dObj->AddDataFlavor(kURLMime, &shortcutFE); } @@ -607,9 +619,11 @@ nsresult nsClipboard::GetDataFromDataObject(IDataObject * aDataObject, // when directly asking for the flavor. Let's try digging around in other // flavors to help satisfy our craving for data. if ( !dataFound ) { - if ( strcmp(flavorStr, kURLMime) == 0 ) { + if ( strcmp(flavorStr, kUnicodeMime) == 0 ) + dataFound = FindUnicodeFromPlainText ( aDataObject, anIndex, &data, &dataLen ); + else if ( strcmp(flavorStr, kURLMime) == 0 ) { // drags from other windows apps expose the native - // CFSTR_INETURLW flavor + // CFSTR_INETURL{A,W} flavor dataFound = FindURLFromNativeURL ( aDataObject, anIndex, &data, &dataLen ); if ( !dataFound ) dataFound = FindURLFromLocalFile ( aDataObject, anIndex, &data, &dataLen ); @@ -759,6 +773,39 @@ nsClipboard :: FindPlatformHTML ( IDataObject* inDataObject, UINT inIndex, } +// +// FindUnicodeFromPlainText +// +// we are looking for text/unicode and we failed to find it on the clipboard first, +// try again with text/plain. If that is present, convert it to unicode. +// +bool +nsClipboard :: FindUnicodeFromPlainText ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) +{ + // we are looking for text/unicode and we failed to find it on the clipboard first, + // try again with text/plain. If that is present, convert it to unicode. + nsresult rv = GetNativeDataOffClipboard(inDataObject, inIndex, GetFormat(kTextMime), nullptr, outData, outDataLen); + if (NS_FAILED(rv) || !*outData) { + return false; + } + + const char* castedText = static_cast(*outData); + nsAutoString tmp; + rv = NS_CopyNativeToUnicode(nsDependentCSubstring(castedText, *outDataLen), tmp); + if (NS_FAILED(rv)) { + return false; + } + + // out with the old, in with the new + free(*outData); + *outData = ToNewUnicode(tmp); + *outDataLen = tmp.Length() * sizeof(char16_t); + + return true; + +} // FindUnicodeFromPlainText + + // // FindURLFromLocalFile // @@ -825,7 +872,7 @@ nsClipboard :: FindURLFromLocalFile ( IDataObject* inDataObject, UINT inIndex, v // // we are looking for a URL and couldn't find it using our internal // URL flavor, so look for it using the native URL flavor, -// CF_INETURLSTRW +// CF_INETURLSTRW (We don't handle CF_INETURLSTRA currently) // bool nsClipboard :: FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, void** outData, uint32_t* outDataLen ) @@ -846,6 +893,29 @@ nsClipboard :: FindURLFromNativeURL ( IDataObject* inDataObject, UINT inIndex, v free(tempOutData); dataFound = true; } + else { + loadResult = GetNativeDataOffClipboard(inDataObject, inIndex, ::RegisterClipboardFormat(CFSTR_INETURLA), nullptr, &tempOutData, &tempDataLen); + if ( NS_SUCCEEDED(loadResult) && tempOutData ) { + // CFSTR_INETURLA is (currently) equal to CFSTR_SHELLURL which is equal to CF_TEXT + // which is by definition ANSI encoded. + nsCString urlUnescapedA; + bool unescaped = NS_UnescapeURL(static_cast(tempOutData), tempDataLen, esc_OnlyNonASCII | esc_SkipControl, urlUnescapedA); + + nsString urlString; + if (unescaped) + NS_CopyNativeToUnicode(urlUnescapedA, urlString); + else + NS_CopyNativeToUnicode(nsDependentCString(static_cast(tempOutData), tempDataLen), urlString); + + // the internal mozilla URL format, text/x-moz-url, contains + // URL\ntitle. Since we don't actually have a title here, + // just repeat the URL to fake it. + *outData = ToNewUnicode(urlString + NS_LITERAL_STRING("\n") + urlString); + *outDataLen = NS_strlen(static_cast(*outData)) * sizeof(char16_t); + free(tempOutData); + dataFound = true; + } + } return dataFound; } // FindURLFromNativeURL @@ -942,6 +1012,16 @@ NS_IMETHODIMP nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, *_retval = true; break; } + else { + // We haven't found the exact flavor the client asked for, but maybe we can + // still find it from something else that's on the clipboard... + if (strcmp(aFlavorList[i], kUnicodeMime) == 0) { + // client asked for unicode and it wasn't present, check if we have CF_TEXT. + // We'll handle the actual data substitution in the data object. + if (IsClipboardFormatAvailable(GetFormat(kTextMime))) + *_retval = true; + } + } } return NS_OK; diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index fcdae453df2..f62da18eb05 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -1290,7 +1290,27 @@ HRESULT nsDataObj::GetText(const nsACString & aDataFlavor, FORMATETC& aFE, STGME // by the appropriate size to account for the null (one char for CF_TEXT, one char16_t for // CF_UNICODETEXT). DWORD allocLen = (DWORD)len; - if ( aFE.cfFormat == nsClipboard::CF_HTML ) { + if ( aFE.cfFormat == CF_TEXT ) { + // Someone is asking for text/plain; convert the unicode (assuming it's present) + // to text with the correct platform encoding. + size_t bufferSize = sizeof(char)*(len + 2); + char* plainTextData = static_cast(moz_xmalloc(bufferSize)); + char16_t* castedUnicode = reinterpret_cast(data); + int32_t plainTextLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)castedUnicode, len / 2 + 1, plainTextData, bufferSize, NULL, NULL); + // replace the unicode data with our plaintext data. Recall that |plainTextLen| doesn't include + // the null in the length. + free(data); + if ( plainTextLen ) { + data = plainTextData; + allocLen = plainTextLen; + } + else { + free(plainTextData); + NS_WARNING ( "Oh no, couldn't convert unicode to plain text" ); + return S_OK; + } + } + else if ( aFE.cfFormat == nsClipboard::CF_HTML ) { // Someone is asking for win32's HTML flavor. Convert our html fragment // from unicode to UTF-8 then put it into a format specified by msft. NS_ConvertUTF16toUTF8 converter ( reinterpret_cast(data) ); From c7ab6b684471f7bde24635f556a4171031c59111 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 3 Feb 2016 11:21:30 -0800 Subject: [PATCH 085/160] Backed 8c41c8315eea (bug 1232229) for breaking all the things on a CLOSED TREE. --- js/src/jsgc.cpp | 1 - js/src/jsgc.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 19add8094e3..25fa074500a 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3410,7 +3410,6 @@ GCRuntime::sweepBackgroundThings(ZoneList& zones, LifoAlloc& freeBlocks, ThreadT for (unsigned index = 0 ; index < BackgroundFinalizePhases[phase].length ; ++index) { AllocKind kind = BackgroundFinalizePhases[phase].kinds[index]; ArenaHeader* arenas = zone->arenas.arenaListsToSweep[kind]; - MOZ_RELEASE_ASSERT(uintptr_t(arenas) != uintptr_t(-1)); if (arenas) ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 54ce98097d8..2ceaa7bbdd4 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -594,7 +594,7 @@ class ArenaLists enum BackgroundFinalizeStateEnum { BFS_DONE, BFS_RUN }; - typedef mozilla::Atomic + typedef mozilla::Atomic BackgroundFinalizeState; /* The current background finalization state, accessed atomically. */ From e34f9237c6c152c8fa832421e854c45527ef8dd7 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 26 Jan 2016 15:03:37 -0600 Subject: [PATCH 086/160] Bug 1243072 - Make GfxTexturesReporter work again r=nical,jgilbert --- gfx/gl/GLTextureImage.cpp | 23 ++++++++- gfx/gl/GLTextureImage.h | 7 ++- gfx/gl/GLUploadHelpers.cpp | 62 +++++++++++++++++++++++-- gfx/gl/GLUploadHelpers.h | 3 ++ gfx/gl/GfxTexturesReporter.cpp | 85 +++------------------------------- gfx/gl/GfxTexturesReporter.h | 13 +++--- gfx/gl/TextureImageEGL.cpp | 5 ++ 7 files changed, 107 insertions(+), 91 deletions(-) diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index 6973231126e..5663fb3dcdb 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -12,6 +12,7 @@ #include "mozilla/gfx/2D.h" #include "ScopedGLHelpers.h" #include "GLUploadHelpers.h" +#include "GfxTexturesReporter.h" #include "TextureImageEGL.h" #ifdef XP_MACOSX @@ -95,6 +96,16 @@ gfx::IntRect TextureImage::GetSrcTileRect() { return GetTileRect(); } +void +TextureImage::UpdateUploadSize(size_t amount) +{ + if (mUploadSize > 0) { + GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryFreed, mUploadSize); + } + mUploadSize = amount; + GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryAllocated, mUploadSize); +} + BasicTextureImage::~BasicTextureImage() { GLContext *ctx = mGLContext; @@ -162,16 +173,20 @@ BasicTextureImage::EndUpdate() RefPtr updateData = updateSnapshot->GetDataSurface(); bool relative = FinishedSurfaceUpdate(); - + size_t uploadSize; mTextureFormat = UploadSurfaceToTexture(mGLContext, updateData, mUpdateRegion, mTexture, + &uploadSize, mTextureState == Created, mUpdateOffset, relative); FinishedSurfaceUpload(); + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); + } mUpdateDrawTarget = nullptr; mTextureState = Valid; @@ -214,14 +229,19 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion region = aRegion; } + size_t uploadSize; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, + &uploadSize, mTextureState == Created, bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y), false); + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); + } mTextureState = Valid; return true; } @@ -273,6 +293,7 @@ TextureImage::TextureImage(const gfx::IntSize& aSize, , mTextureFormat(gfx::SurfaceFormat::UNKNOWN) , mFilter(Filter::GOOD) , mFlags(aFlags) + , mUploadSize(0) {} BasicTextureImage::BasicTextureImage(GLuint aTexture, diff --git a/gfx/gl/GLTextureImage.h b/gfx/gl/GLTextureImage.h index 231f6b6d182..958d6ae5067 100644 --- a/gfx/gl/GLTextureImage.h +++ b/gfx/gl/GLTextureImage.h @@ -203,6 +203,8 @@ public: protected: friend class GLContext; + void UpdateUploadSize(size_t amount); + /** * After the ctor, the TextureImage is invalid. Implementations * must allocate resources successfully before returning the new @@ -214,7 +216,9 @@ protected: Flags aFlags = NoFlags); // Protected destructor, to discourage deletion outside of Release(): - virtual ~TextureImage() {} + virtual ~TextureImage() { + UpdateUploadSize(0); + } virtual gfx::IntRect GetSrcTileRect(); @@ -224,6 +228,7 @@ protected: gfx::SurfaceFormat mTextureFormat; gfx::Filter mFilter; Flags mFlags; + size_t mUploadSize; }; /** diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp index b92c47a61d9..fa37dd0b8d6 100644 --- a/gfx/gl/GLUploadHelpers.cpp +++ b/gfx/gl/GLUploadHelpers.cpp @@ -9,6 +9,7 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Tools.h" // For BytesPerPixel #include "nsRegion.h" +#include "GfxTexturesReporter.h" namespace mozilla { @@ -379,6 +380,50 @@ TexImage2DHelper(GLContext *gl, } } +static uint32_t +GetBytesPerTexel(GLenum format, GLenum type) +{ + // If there is no defined format or type, we're not taking up any memory + if (!format || !type) { + return 0; + } + + if (format == LOCAL_GL_DEPTH_COMPONENT) { + if (type == LOCAL_GL_UNSIGNED_SHORT) + return 2; + else if (type == LOCAL_GL_UNSIGNED_INT) + return 4; + } else if (format == LOCAL_GL_DEPTH_STENCIL) { + if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) + return 4; + } + + if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) { + uint32_t multiplier = type == LOCAL_GL_FLOAT ? 4 : 1; + switch (format) { + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + return 1 * multiplier; + case LOCAL_GL_LUMINANCE_ALPHA: + return 2 * multiplier; + case LOCAL_GL_RGB: + return 3 * multiplier; + case LOCAL_GL_RGBA: + return 4 * multiplier; + default: + break; + } + } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 || + type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 || + type == LOCAL_GL_UNSIGNED_SHORT_5_6_5) + { + return 2; + } + + MOZ_RELEASE_ASSERT(false, "Unknown type and/or format"); + return 0; +} + SurfaceFormat UploadImageDataToTexture(GLContext* gl, unsigned char* aData, @@ -386,6 +431,7 @@ UploadImageDataToTexture(GLContext* gl, SurfaceFormat aFormat, const nsIntRegion& aDstRegion, GLuint& aTexture, + size_t* aOutUploadSize, bool aOverwrite, bool aPixelBuffer, GLenum aTextureUnit, @@ -505,6 +551,10 @@ UploadImageDataToTexture(GLContext* gl, // Top left point of the region's bounding rectangle. IntPoint topLeft = paintRegion.GetBounds().TopLeft(); + if (aOutUploadSize) { + *aOutUploadSize = 0; + } + for (auto iter = paintRegion.RectIter(); !iter.Done(); iter.Next()) { const IntRect& rect = iter.Get(); // The inital data pointer is at the top left point of the region's @@ -544,6 +594,11 @@ UploadImageDataToTexture(GLContext* gl, rectData); } + if (aOutUploadSize && !textureInited) { + uint32_t texelSize = GetBytesPerTexel(internalFormat, type); + size_t numTexels = size_t(rect.width) * size_t(rect.height); + *aOutUploadSize += texelSize * numTexels; + } } return surfaceFormat; @@ -551,9 +606,10 @@ UploadImageDataToTexture(GLContext* gl, SurfaceFormat UploadSurfaceToTexture(GLContext* gl, - DataSourceSurface *aSurface, + DataSourceSurface* aSurface, const nsIntRegion& aDstRegion, GLuint& aTexture, + size_t* aOutUploadSize, bool aOverwrite, const gfx::IntPoint& aSrcPoint, bool aPixelBuffer, @@ -565,8 +621,8 @@ UploadSurfaceToTexture(GLContext* gl, SurfaceFormat format = aSurface->GetFormat(); data += DataOffset(aSrcPoint, stride, format); return UploadImageDataToTexture(gl, data, stride, format, - aDstRegion, aTexture, aOverwrite, - aPixelBuffer, aTextureUnit, + aDstRegion, aTexture, aOutUploadSize, + aOverwrite, aPixelBuffer, aTextureUnit, aTextureTarget); } diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h index 46db6fe0681..25a3348855a 100644 --- a/gfx/gl/GLUploadHelpers.h +++ b/gfx/gl/GLUploadHelpers.h @@ -40,6 +40,7 @@ class GLContext; * \param aData Image data to upload. * \param aDstRegion Region of texture to upload to. * \param aTexture Texture to use, or 0 to have one created for you. + * \param aOutUploadSize if set, the number of bytes the texture requires will be returned here * \param aOverwrite Over an existing texture with a new one. * \param aSrcPoint Offset into aSrc where the region's bound's * TopLeft() sits. @@ -59,6 +60,7 @@ UploadImageDataToTexture(GLContext* gl, gfx::SurfaceFormat aFormat, const nsIntRegion& aDstRegion, GLuint& aTexture, + size_t* aOutUploadSize = nullptr, bool aOverwrite = false, bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, @@ -72,6 +74,7 @@ UploadSurfaceToTexture(GLContext* gl, gfx::DataSourceSurface *aSurface, const nsIntRegion& aDstRegion, GLuint& aTexture, + size_t* aOutUploadSize = nullptr, bool aOverwrite = false, const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0), bool aPixelBuffer = false, diff --git a/gfx/gl/GfxTexturesReporter.cpp b/gfx/gl/GfxTexturesReporter.cpp index c4d97e9ad66..416349c0b2c 100644 --- a/gfx/gl/GfxTexturesReporter.cpp +++ b/gfx/gl/GfxTexturesReporter.cpp @@ -5,95 +5,22 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GfxTexturesReporter.h" -#include "GLDefs.h" using namespace mozilla; using namespace mozilla::gl; NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter) -Atomic GfxTexturesReporter::sAmount(0); -Atomic GfxTexturesReporter::sTileWasteAmount(0); - -static uint32_t -GetBitsPerTexel(GLenum format, GLenum type) -{ - // If there is no defined format or type, we're not taking up any memory - if (!format || !type) { - return 0; - } - - if (format == LOCAL_GL_DEPTH_COMPONENT) { - if (type == LOCAL_GL_UNSIGNED_SHORT) - return 2*8; - else if (type == LOCAL_GL_UNSIGNED_INT) - return 4*8; - } else if (format == LOCAL_GL_DEPTH_STENCIL) { - if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) - return 4*8; - } - - if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) { - uint32_t multiplier = type == LOCAL_GL_FLOAT ? 32 : 8; - switch (format) { - case LOCAL_GL_ALPHA: - case LOCAL_GL_LUMINANCE: - return 1 * multiplier; - case LOCAL_GL_LUMINANCE_ALPHA: - return 2 * multiplier; - case LOCAL_GL_RGB: - return 3 * multiplier; - case LOCAL_GL_RGBA: - return 4 * multiplier; - case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1: - case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1: - return 2; - case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case LOCAL_GL_ATC_RGB: - case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1: - case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1: - case LOCAL_GL_ETC1_RGB8_OES: - case LOCAL_GL_COMPRESSED_RGB8_ETC2: - case LOCAL_GL_COMPRESSED_SRGB8_ETC2: - case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: - case LOCAL_GL_COMPRESSED_R11_EAC: - case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC: - return 4; - case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA: - case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA: - case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC: - case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: - case LOCAL_GL_COMPRESSED_RG11_EAC: - case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC: - return 8; - default: - break; - } - } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 || - type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 || - type == LOCAL_GL_UNSIGNED_SHORT_5_6_5) - { - return 2*8; - } - - MOZ_ASSERT(false); - return 0; -} +Atomic GfxTexturesReporter::sAmount(0); +Atomic GfxTexturesReporter::sTileWasteAmount(0); /* static */ void -GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format, - GLenum type, int32_t tileWidth, - int32_t tileHeight) +GfxTexturesReporter::UpdateAmount(MemoryUse action, size_t amount) { - int64_t bitsPerTexel = GetBitsPerTexel(format, type); - int64_t bytes = int64_t(tileWidth) * int64_t(tileHeight) * bitsPerTexel/8; if (action == MemoryFreed) { - sAmount -= bytes; + MOZ_RELEASE_ASSERT(amount <= sAmount); + sAmount -= amount; } else { - sAmount += bytes; + sAmount += amount; } } diff --git a/gfx/gl/GfxTexturesReporter.h b/gfx/gl/GfxTexturesReporter.h index 89f9c4d151d..7553853f144 100644 --- a/gfx/gl/GfxTexturesReporter.h +++ b/gfx/gl/GfxTexturesReporter.h @@ -41,10 +41,9 @@ public: // When memory is used/freed for tile textures, call this method to update // the value reported by this memory reporter. - static void UpdateAmount(MemoryUse action, GLenum format, GLenum type, - int32_t tileWidth, int32_t tileHeight); + static void UpdateAmount(MemoryUse action, size_t amount); - static void UpdateWasteAmount(int32_t delta) { + static void UpdateWasteAmount(size_t delta) { sTileWasteAmount += delta; } @@ -52,17 +51,17 @@ public: nsISupports* aData, bool aAnonymize) override { MOZ_COLLECT_REPORT("gfx-tiles-waste", KIND_OTHER, UNITS_BYTES, - sTileWasteAmount, + int64_t(sTileWasteAmount), "Memory lost due to tiles extending past content boundaries"); return MOZ_COLLECT_REPORT( - "gfx-textures", KIND_OTHER, UNITS_BYTES, sAmount, + "gfx-textures", KIND_OTHER, UNITS_BYTES, int64_t(sAmount), "Memory used for storing GL textures."); } private: - static Atomic sAmount; + static Atomic sAmount; // Count the amount of memory lost to tile waste - static Atomic sTileWasteAmount; + static Atomic sTileWasteAmount; }; class GfxTextureWasteTracker { diff --git a/gfx/gl/TextureImageEGL.cpp b/gfx/gl/TextureImageEGL.cpp index 1f4323b60e6..31150f08b7e 100644 --- a/gfx/gl/TextureImageEGL.cpp +++ b/gfx/gl/TextureImageEGL.cpp @@ -207,14 +207,19 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region = aRegion; } + size_t uploadSize = 0; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, + &uploadSize, mTextureState == Created, bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y), false); + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); + } mTextureState = Valid; return true; From d89e169a11d4bc16a0900494b8daef21351daac2 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 27 Jan 2016 10:09:01 -0600 Subject: [PATCH 087/160] Bug 1243418 - Fix up incorrect 'aOverwrite' usage and impl in GLUploadHelpers r=jgilbert --- gfx/gl/GLTextureImage.cpp | 6 ++++-- gfx/gl/GLUploadHelpers.cpp | 8 ++++---- gfx/gl/GLUploadHelpers.h | 4 ++-- gfx/gl/TextureImageEGL.cpp | 3 ++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index 5663fb3dcdb..b3dd425974c 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -173,6 +173,7 @@ BasicTextureImage::EndUpdate() RefPtr updateData = updateSnapshot->GetDataSurface(); bool relative = FinishedSurfaceUpdate(); + bool needInit = mTextureState == Created; size_t uploadSize; mTextureFormat = UploadSurfaceToTexture(mGLContext, @@ -180,7 +181,7 @@ BasicTextureImage::EndUpdate() mUpdateRegion, mTexture, &uploadSize, - mTextureState == Created, + needInit, mUpdateOffset, relative); FinishedSurfaceUpload(); @@ -230,13 +231,14 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion } size_t uploadSize; + bool needInit = mTextureState == Created; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, &uploadSize, - mTextureState == Created, + needInit, bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y), false); if (uploadSize > 0) { diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp index fa37dd0b8d6..cf673ba497e 100644 --- a/gfx/gl/GLUploadHelpers.cpp +++ b/gfx/gl/GLUploadHelpers.cpp @@ -432,12 +432,12 @@ UploadImageDataToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize, - bool aOverwrite, + bool aNeedInit, bool aPixelBuffer, GLenum aTextureUnit, GLenum aTextureTarget) { - bool textureInited = aOverwrite ? false : true; + bool textureInited = aNeedInit ? false : true; gl->MakeCurrent(); gl->fActiveTexture(aTextureUnit); @@ -610,7 +610,7 @@ UploadSurfaceToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize, - bool aOverwrite, + bool aNeedInit, const gfx::IntPoint& aSrcPoint, bool aPixelBuffer, GLenum aTextureUnit, @@ -622,7 +622,7 @@ UploadSurfaceToTexture(GLContext* gl, data += DataOffset(aSrcPoint, stride, format); return UploadImageDataToTexture(gl, data, stride, format, aDstRegion, aTexture, aOutUploadSize, - aOverwrite, aPixelBuffer, aTextureUnit, + aNeedInit, aPixelBuffer, aTextureUnit, aTextureTarget); } diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h index 25a3348855a..a641b453722 100644 --- a/gfx/gl/GLUploadHelpers.h +++ b/gfx/gl/GLUploadHelpers.h @@ -61,7 +61,7 @@ UploadImageDataToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize = nullptr, - bool aOverwrite = false, + bool aNeedInit = false, bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D); @@ -75,7 +75,7 @@ UploadSurfaceToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize = nullptr, - bool aOverwrite = false, + bool aNeedInit = false, const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0), bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, diff --git a/gfx/gl/TextureImageEGL.cpp b/gfx/gl/TextureImageEGL.cpp index 31150f08b7e..9e3da7765ea 100644 --- a/gfx/gl/TextureImageEGL.cpp +++ b/gfx/gl/TextureImageEGL.cpp @@ -207,6 +207,7 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region = aRegion; } + bool needInit = mTextureState == Created; size_t uploadSize = 0; mTextureFormat = UploadSurfaceToTexture(mGLContext, @@ -214,7 +215,7 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region, mTexture, &uploadSize, - mTextureState == Created, + needInit, bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y), false); if (uploadSize > 0) { From c578d80d2f0b76f9aec978aa4a0db134bb49b3e0 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Wed, 3 Feb 2016 12:27:50 -0800 Subject: [PATCH 088/160] Bug 1233046 - Fix OES_texture_float on Mac and add tests for extensions. - r=jrmuizel --- dom/canvas/WebGLContext.cpp | 5 +- dom/canvas/WebGLContext.h | 3 +- dom/canvas/WebGLContextGL.cpp | 4 + dom/canvas/WebGLContextState.cpp | 138 +++++++++++++++--- dom/canvas/WebGLExtensionTextureFloat.cpp | 27 ++-- dom/canvas/WebGLExtensionTextureHalfFloat.cpp | 27 ++-- dom/canvas/moz.build | 2 +- dom/canvas/test/webgl-mochitest.ini | 41 ++++++ .../webgl-mochitest/ensure-exts/ensure-ext.js | 32 ++++ .../test_ANGLE_instanced_arrays.html | 17 +++ .../ensure-exts/test_EXT_blend_minmax.html | 17 +++ .../test_EXT_color_buffer_half_float.html | 17 +++ .../test_EXT_disjoint_timer_query.html | 17 +++ .../ensure-exts/test_EXT_frag_depth.html | 17 +++ .../ensure-exts/test_EXT_sRGB.html | 17 +++ .../test_EXT_shader_texture_lod.html | 17 +++ .../test_EXT_texture_filter_anisotropic.html | 17 +++ .../test_OES_standard_derivatives.html | 17 +++ .../test_WEBGL_color_buffer_float.html | 17 +++ .../test_WEBGL_compressed_texture_atc.html | 17 +++ .../test_WEBGL_compressed_texture_es3.html | 17 +++ .../test_WEBGL_compressed_texture_etc1.html | 17 +++ .../test_WEBGL_compressed_texture_pvrtc.html | 17 +++ .../test_WEBGL_compressed_texture_s3tc.html | 17 +++ .../ensure-exts/test_WEBGL_depth_texture.html | 17 +++ .../ensure-exts/test_WEBGL_draw_buffers.html | 17 +++ .../ensure-exts/test_common.html | 75 ++++++++++ .../test/webgl-mochitest/mochi-to-testcase.py | 7 +- 28 files changed, 600 insertions(+), 50 deletions(-) create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 2d1989def2d..5bb46165e19 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -1304,8 +1304,7 @@ WebGLContext::ClearScreen() const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK); if (changeDrawBuffers) { - const GLenum back = LOCAL_GL_BACK; - gl->fDrawBuffers(1, &back); + gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK); } GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT; @@ -1317,7 +1316,7 @@ WebGLContext::ClearScreen() ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha); if (changeDrawBuffers) { - gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0); + gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0); } } diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index a7eeba956f2..dafbe702306 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -827,7 +827,8 @@ protected: public: void Disable(GLenum cap); void Enable(GLenum cap); - bool GetStencilBits(GLint* out_stencilBits); + bool GetStencilBits(GLint* const out_stencilBits); + bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val); virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv); void GetParameter(JSContext* cx, GLenum pname, diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index ef3716142ae..34543116fea 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -994,6 +994,10 @@ WebGLContext::Hint(GLenum target, GLenum mode) switch (target) { case LOCAL_GL_GENERATE_MIPMAP_HINT: + // Deprecated and removed in desktop GL Core profiles. + if (gl->IsCoreProfile()) + return; + isValid = true; break; diff --git a/dom/canvas/WebGLContextState.cpp b/dom/canvas/WebGLContextState.cpp index 8f3563a0dcf..ea818e4004f 100644 --- a/dom/canvas/WebGLContextState.cpp +++ b/dom/canvas/WebGLContextState.cpp @@ -73,7 +73,7 @@ StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv) } bool -WebGLContext::GetStencilBits(GLint* out_stencilBits) +WebGLContext::GetStencilBits(GLint* const out_stencilBits) { *out_stencilBits = 0; if (mBoundDrawFramebuffer) { @@ -97,9 +97,107 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits) return true; } +bool +WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val) +{ + if (mBoundDrawFramebuffer) { + if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName)) + return false; + } + + if (!mBoundDrawFramebuffer) { + switch (pname) { + case LOCAL_GL_RED_BITS: + case LOCAL_GL_GREEN_BITS: + case LOCAL_GL_BLUE_BITS: + *out_val = 8; + break; + + case LOCAL_GL_ALPHA_BITS: + *out_val = (mOptions.alpha ? 8 : 0); + break; + + case LOCAL_GL_DEPTH_BITS: + if (mOptions.depth) { + const auto& glFormats = gl->GetGLFormats(); + + GLenum depthFormat = glFormats.depth; + if (mOptions.stencil && glFormats.depthStencil) { + depthFormat = glFormats.depthStencil; + } + + if (depthFormat == LOCAL_GL_DEPTH_COMPONENT16) { + *out_val = 16; + } else { + *out_val = 24; + } + } else { + *out_val = 0; + } + break; + + case LOCAL_GL_STENCIL_BITS: + *out_val = (mOptions.stencil ? 8 : 0); + break; + + default: + MOZ_CRASH("bad pname"); + } + return true; + } + + if (!gl->IsCoreProfile()) { + gl->fGetIntegerv(pname, out_val); + return true; + } + + GLenum fbAttachment = 0; + GLenum fbPName = 0; + switch (pname) { + case LOCAL_GL_RED_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE; + break; + + case LOCAL_GL_GREEN_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE; + break; + + case LOCAL_GL_BLUE_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE; + break; + + case LOCAL_GL_ALPHA_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE; + break; + + case LOCAL_GL_DEPTH_BITS: + fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE; + break; + + case LOCAL_GL_STENCIL_BITS: + fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE; + break; + + default: + MOZ_CRASH("bad pname"); + } + + gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment, + fbPName, out_val); + return true; +} + JS::Value WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) { + const char funcName[] = "getParameter"; + if (IsContextLost()) return JS::NullValue(); @@ -356,11 +454,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) return JS::Int32Value(refValue & stencilMask); } - case LOCAL_GL_STENCIL_BITS: { - GLint stencilBits = 0; - GetStencilBits(&stencilBits); - return JS::Int32Value(stencilBits); - } + case LOCAL_GL_STENCIL_CLEAR_VALUE: case LOCAL_GL_UNPACK_ALIGNMENT: case LOCAL_GL_PACK_ALIGNMENT: @@ -370,28 +464,26 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) case LOCAL_GL_MAX_VERTEX_ATTRIBS: case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: - case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: - case LOCAL_GL_RED_BITS: - case LOCAL_GL_GREEN_BITS: - case LOCAL_GL_BLUE_BITS: { + case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: { GLint i = 0; gl->fGetIntegerv(pname, &i); return JS::Int32Value(i); } - case LOCAL_GL_DEPTH_BITS: { - GLint i = 0; - if (!mNeedsFakeNoDepth) { - gl->fGetIntegerv(pname, &i); - } - return JS::Int32Value(i); - } - case LOCAL_GL_ALPHA_BITS: { - GLint i = 0; - if (!mNeedsFakeNoAlpha) { - gl->fGetIntegerv(pname, &i); - } - return JS::Int32Value(i); + + case LOCAL_GL_RED_BITS: + case LOCAL_GL_GREEN_BITS: + case LOCAL_GL_BLUE_BITS: + case LOCAL_GL_ALPHA_BITS: + case LOCAL_GL_DEPTH_BITS: + case LOCAL_GL_STENCIL_BITS: { + // Deprecated and removed in GL Core profiles, so special handling required. + GLint val; + if (!GetChannelBits(funcName, pname, &val)) + return JS::NullValue(); + + return JS::Int32Value(val); } + case LOCAL_GL_MAX_TEXTURE_SIZE: return JS::Int32Value(mImplMaxTextureSize); diff --git a/dom/canvas/WebGLExtensionTextureFloat.cpp b/dom/canvas/WebGLExtensionTextureFloat.cpp index a7a58939ad1..4568e994ee9 100644 --- a/dom/canvas/WebGLExtensionTextureFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureFloat.cpp @@ -32,15 +32,17 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) fua->AllowUnsizedTexFormat(pi, usage); }; - const bool needSizedInternal = !gl->IsGLES(); - MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle)); + const bool needsSwizzle = gl->IsCoreProfile(); + MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle)); + + const bool needsSizedFormat = !gl->IsGLES(); //////////////// pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGBA32F; } fnAdd(webgl::EffectiveFormat::RGBA32F); @@ -50,7 +52,7 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGB32F; } fnAdd(webgl::EffectiveFormat::RGB32F); @@ -60,9 +62,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance32F); @@ -71,9 +75,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_ALPHA32F_ARB; } fnAdd(webgl::EffectiveFormat::Alpha32F); @@ -82,9 +88,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F); } @@ -101,10 +109,9 @@ WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl) if (!gl->IsSupported(gl::GLFeature::texture_float)) return false; - const bool needSizedInternal = !gl->IsGLES(); + const bool needsSwizzle = gl->IsCoreProfile(); const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle); - - if (needSizedInternal && !hasSwizzle) + if (needsSwizzle && !hasSwizzle) return false; return true; diff --git a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp index a5770999d67..e59f9b232ee 100644 --- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp @@ -30,8 +30,10 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web fua->AllowUnsizedTexFormat(pi, usage); }; - const bool needSizedInternal = !gl->IsGLES(); - MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle)); + const bool needsSwizzle = gl->IsCoreProfile(); + MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle)); + + const bool needsSizedFormat = !gl->IsGLES(); GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT; if (!gl->IsSupported(gl::GLFeature::texture_half_float)) { @@ -44,7 +46,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGBA16F; } fnAdd(webgl::EffectiveFormat::RGBA16F); @@ -54,7 +56,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGB16F; } fnAdd(webgl::EffectiveFormat::RGB16F); @@ -64,9 +66,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance16F); @@ -75,9 +79,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_ALPHA16F_ARB; } fnAdd(webgl::EffectiveFormat::Alpha16F); @@ -86,9 +92,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F); } @@ -108,10 +116,9 @@ WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl) return false; } - const bool needSizedInternal = !gl->IsGLES(); + const bool needsSwizzle = gl->IsCoreProfile(); const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle); - - if (needSizedInternal && !hasSwizzle) + if (needsSwizzle && !hasSwizzle) return false; return true; diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index ffa942025ce..3bb34681752 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -7,7 +7,7 @@ TEST_DIRS += ['compiledtest'] # Number changes to this file to avoid bug 1081323 (clobber after changing a manifest): -# 3 +# 4 MOCHITEST_MANIFESTS += [ 'test/crossorigin/mochitest.ini', diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index d6cd17dd6b4..2fe2009587c 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -3,10 +3,51 @@ subsuite = webgl skip-if = ((os == 'linux') && (buildapp == 'b2g')) support-files = + webgl-mochitest/ensure-exts/ensure-ext.js webgl-mochitest/driver-info.js webgl-mochitest/es3-data.js webgl-mochitest/webgl-util.js +[webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html] +fail-if = (os == 'android') || (os == 'mac') +[webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_sRGB.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') +[webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html] +fail-if = (os == 'android') || (os == 'linux') +[webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html] +# Win7 is 6.1 +fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && os_version == '6.1') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html] +fail-if = (os == 'android') || (os == 'linux') +[webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html] +fail-if = (os == 'mac') +[webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html] +# Win7 is 6.1 +fail-if = (os == 'android') || (os == 'win' && os_version == '6.1') + +[webgl-mochitest/ensure-exts/test_common.html] + + [webgl-mochitest/test_backbuffer_channels.html] fail-if = (os == 'b2g') [webgl-mochitest/test_depth_readpixels.html] diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js new file mode 100644 index 00000000000..798067d5e42 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js @@ -0,0 +1,32 @@ +'use strict'; + +function EnsureExt(name, shouldBe = true) { + var c = document.createElement('canvas'); + var gl = c.getContext('experimental-webgl'); + + if (shouldBe) { + ok(gl.getExtension(name), 'Should have extension ' + name + '.'); + } else { + ok(!gl.getExtension(name), 'Should not have extension ' + name + '.'); + } +} + +function EnsureDraftExt(name, shouldBe = true) { + SimpleTest.waitForExplicitFinish(); + + var fnEnsure = function() { + EnsureExt(name, shouldBe); + SimpleTest.finish(); + }; + + if ('SpecialPowers' in window) { + var prefStateList = [ + ['webgl.enable-draft-extensions', true], + ]; + var prefEnv = {'set': prefStateList}; + SpecialPowers.pushPrefEnv(prefEnv, fnEnsure); + } else { + console.log('Couldn\'t use SpecialPowers to enable draft extensions.'); + fnEnsure(); + } +} diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html new file mode 100644 index 00000000000..04b24d90c10 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html new file mode 100644 index 00000000000..903269e6b66 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html new file mode 100644 index 00000000000..3ac21299c68 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html new file mode 100644 index 00000000000..e0b90adbbb5 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html new file mode 100644 index 00000000000..3c7f3867917 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html new file mode 100644 index 00000000000..da5aa0a3fbf --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html new file mode 100644 index 00000000000..e64ff94848c --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html new file mode 100644 index 00000000000..877c4440bf3 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html new file mode 100644 index 00000000000..3e7b7a39622 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html new file mode 100644 index 00000000000..aeb8f271ea0 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html new file mode 100644 index 00000000000..6d68f0b4e2b --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html new file mode 100644 index 00000000000..21c824ad854 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html new file mode 100644 index 00000000000..327625c0184 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html new file mode 100644 index 00000000000..c9548139842 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html new file mode 100644 index 00000000000..6ad80011064 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html new file mode 100644 index 00000000000..957171c160e --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html new file mode 100644 index 00000000000..18774d0d68a --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html new file mode 100644 index 00000000000..3b5907a8a88 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html @@ -0,0 +1,75 @@ + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py index bac482c3d73..919ba232804 100644 --- a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py +++ b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py @@ -28,7 +28,8 @@ def ReadLocalFile(include): return data -kSimpleTestReplacement = '''\n +kSimpleTestReplacement = ''' +

    -\n''' + +''' fin = open(mochiPath, 'rb') fout = open(testPath, 'wb') From 9b9bd81f4163178489572bde3d9bb2788de8d3f5 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 3 Feb 2016 14:33:07 -0600 Subject: [PATCH 089/160] Back out bug 1243418 for build bustage on mac --- gfx/gl/GLTextureImage.cpp | 6 ++---- gfx/gl/GLUploadHelpers.cpp | 8 ++++---- gfx/gl/GLUploadHelpers.h | 4 ++-- gfx/gl/TextureImageEGL.cpp | 3 +-- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index b3dd425974c..5663fb3dcdb 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -173,7 +173,6 @@ BasicTextureImage::EndUpdate() RefPtr updateData = updateSnapshot->GetDataSurface(); bool relative = FinishedSurfaceUpdate(); - bool needInit = mTextureState == Created; size_t uploadSize; mTextureFormat = UploadSurfaceToTexture(mGLContext, @@ -181,7 +180,7 @@ BasicTextureImage::EndUpdate() mUpdateRegion, mTexture, &uploadSize, - needInit, + mTextureState == Created, mUpdateOffset, relative); FinishedSurfaceUpload(); @@ -231,14 +230,13 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion } size_t uploadSize; - bool needInit = mTextureState == Created; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, &uploadSize, - needInit, + mTextureState == Created, bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y), false); if (uploadSize > 0) { diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp index cf673ba497e..fa37dd0b8d6 100644 --- a/gfx/gl/GLUploadHelpers.cpp +++ b/gfx/gl/GLUploadHelpers.cpp @@ -432,12 +432,12 @@ UploadImageDataToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize, - bool aNeedInit, + bool aOverwrite, bool aPixelBuffer, GLenum aTextureUnit, GLenum aTextureTarget) { - bool textureInited = aNeedInit ? false : true; + bool textureInited = aOverwrite ? false : true; gl->MakeCurrent(); gl->fActiveTexture(aTextureUnit); @@ -610,7 +610,7 @@ UploadSurfaceToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize, - bool aNeedInit, + bool aOverwrite, const gfx::IntPoint& aSrcPoint, bool aPixelBuffer, GLenum aTextureUnit, @@ -622,7 +622,7 @@ UploadSurfaceToTexture(GLContext* gl, data += DataOffset(aSrcPoint, stride, format); return UploadImageDataToTexture(gl, data, stride, format, aDstRegion, aTexture, aOutUploadSize, - aNeedInit, aPixelBuffer, aTextureUnit, + aOverwrite, aPixelBuffer, aTextureUnit, aTextureTarget); } diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h index a641b453722..25a3348855a 100644 --- a/gfx/gl/GLUploadHelpers.h +++ b/gfx/gl/GLUploadHelpers.h @@ -61,7 +61,7 @@ UploadImageDataToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize = nullptr, - bool aNeedInit = false, + bool aOverwrite = false, bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D); @@ -75,7 +75,7 @@ UploadSurfaceToTexture(GLContext* gl, const nsIntRegion& aDstRegion, GLuint& aTexture, size_t* aOutUploadSize = nullptr, - bool aNeedInit = false, + bool aOverwrite = false, const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0), bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, diff --git a/gfx/gl/TextureImageEGL.cpp b/gfx/gl/TextureImageEGL.cpp index 9e3da7765ea..31150f08b7e 100644 --- a/gfx/gl/TextureImageEGL.cpp +++ b/gfx/gl/TextureImageEGL.cpp @@ -207,7 +207,6 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region = aRegion; } - bool needInit = mTextureState == Created; size_t uploadSize = 0; mTextureFormat = UploadSurfaceToTexture(mGLContext, @@ -215,7 +214,7 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region, mTexture, &uploadSize, - needInit, + mTextureState == Created, bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y), false); if (uploadSize > 0) { From 55d3ffe02eb772be82b918f33e60f4928e85739d Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 1 Feb 2016 12:06:58 -0500 Subject: [PATCH 090/160] Bug 1244742. Use the default copy constructor and assignment operators. --- gfx/src/nsFont.cpp | 49 ++------------------------------------------ gfx/src/nsRegion.cpp | 5 ----- 2 files changed, 2 insertions(+), 52 deletions(-) diff --git a/gfx/src/nsFont.cpp b/gfx/src/nsFont.cpp index 99693ccb186..777a320228d 100644 --- a/gfx/src/nsFont.cpp +++ b/gfx/src/nsFont.cpp @@ -52,29 +52,7 @@ nsFont::Init() variantPosition = NS_FONT_VARIANT_POSITION_NORMAL; } -nsFont::nsFont(const nsFont& aOther) - : fontlist(aOther.fontlist) -{ - style = aOther.style; - systemFont = aOther.systemFont; - weight = aOther.weight; - stretch = aOther.stretch; - smoothing = aOther.smoothing; - size = aOther.size; - sizeAdjust = aOther.sizeAdjust; - kerning = aOther.kerning; - synthesis = aOther.synthesis; - fontFeatureSettings = aOther.fontFeatureSettings; - languageOverride = aOther.languageOverride; - variantAlternates = aOther.variantAlternates; - variantCaps = aOther.variantCaps; - variantEastAsian = aOther.variantEastAsian; - variantLigatures = aOther.variantLigatures; - variantNumeric = aOther.variantNumeric; - variantPosition = aOther.variantPosition; - alternateValues = aOther.alternateValues; - featureValueLookup = aOther.featureValueLookup; -} +nsFont::nsFont(const nsFont& aOther) = default; nsFont::nsFont() { @@ -111,30 +89,7 @@ bool nsFont::Equals(const nsFont& aOther) const return false; } -nsFont& nsFont::operator=(const nsFont& aOther) -{ - fontlist = aOther.fontlist; - style = aOther.style; - systemFont = aOther.systemFont; - weight = aOther.weight; - stretch = aOther.stretch; - smoothing = aOther.smoothing; - size = aOther.size; - sizeAdjust = aOther.sizeAdjust; - kerning = aOther.kerning; - synthesis = aOther.synthesis; - fontFeatureSettings = aOther.fontFeatureSettings; - languageOverride = aOther.languageOverride; - variantAlternates = aOther.variantAlternates; - variantCaps = aOther.variantCaps; - variantEastAsian = aOther.variantEastAsian; - variantLigatures = aOther.variantLigatures; - variantNumeric = aOther.variantNumeric; - variantPosition = aOther.variantPosition; - alternateValues = aOther.alternateValues; - featureValueLookup = aOther.featureValueLookup; - return *this; -} +nsFont& nsFont::operator=(const nsFont& aOther) = default; void nsFont::CopyAlternates(const nsFont& aOther) diff --git a/gfx/src/nsRegion.cpp b/gfx/src/nsRegion.cpp index a46944e6807..4c4d4ae8560 100644 --- a/gfx/src/nsRegion.cpp +++ b/gfx/src/nsRegion.cpp @@ -950,11 +950,6 @@ namespace { result.mSize = result.mSizeContainingRect = kVeryLargeNegativeNumber; return result; } - SizePair& operator=(const SizePair& aOther) { - mSizeContainingRect = aOther.mSizeContainingRect; - mSize = aOther.mSize; - return *this; - } bool operator<(const SizePair& aOther) const { if (mSizeContainingRect < aOther.mSizeContainingRect) return true; From af7e2ced8453b904b968008b08d15130e0d9177f Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Tue, 2 Feb 2016 22:58:22 -0500 Subject: [PATCH 091/160] Bug 1178385. Enable DXVA on the G45 r=ajones This blocking never solved the original issue. Will remove it a little bit at first and perhaps remove the rest later. --- widget/windows/GfxInfo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index 21e3ebb2171..6c8e220af45 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -1096,10 +1096,11 @@ GfxInfo::GetGfxDriverInfo() nsIGfxInfo::FEATURE_WEBGL_ANGLE, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE, V(8,861,0,0), V(8,862,6,5000), "Radeon driver > 8.862.6.5000"); + /* This may not be needed at all */ APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_WINDOWS_7, (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1155608), nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, - DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2869)); + DRIVER_LESS_THAN, V(8,15,10,2869)); /* Bug 1203199/1092166: DXVA startup crashes on some intel drivers. */ APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_ALL, From 7da5b9d1204c0c775ee8d4bafbe63fab9c6df44d Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 3 Feb 2016 12:37:23 -0800 Subject: [PATCH 092/160] Bug 1245406: In ReflowBlockFrame, use Maybe<> to destroy & reconstruct a stack-allocated object, instead of an explicit call to destructor & placement 'new'. r=dbaron --- layout/generic/nsBlockFrame.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 01c9b7a275d..0b176f2e02a 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -12,6 +12,7 @@ #include "nsBlockFrame.h" #include "mozilla/DebugOnly.h" +#include "mozilla/Maybe.h" #include "nsCOMPtr.h" #include "nsAbsoluteContainingBlock.h" @@ -3319,10 +3320,11 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, } // construct the html reflow state for the block. ReflowBlock - // will initialize it - nsHTMLReflowState - blockHtmlRS(aState.mPresContext, aState.mReflowState, frame, - availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm)); + // will initialize it. + Maybe blockHtmlRS; + blockHtmlRS.emplace( + aState.mPresContext, aState.mReflowState, frame, + availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm)); nsFloatManager::SavedState floatManagerState; nsReflowStatus frameReflowStatus; @@ -3347,16 +3349,16 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, } if (mayNeedRetry) { - blockHtmlRS.mDiscoveredClearance = &clearanceFrame; + blockHtmlRS->mDiscoveredClearance = &clearanceFrame; } else if (!applyBStartMargin) { - blockHtmlRS.mDiscoveredClearance = + blockHtmlRS->mDiscoveredClearance = aState.mReflowState.mDiscoveredClearance; } frameReflowStatus = NS_FRAME_COMPLETE; brc.ReflowBlock(availSpace, applyBStartMargin, aState.mPrevBEndMargin, clearance, aState.IsAdjacentWithTop(), - aLine.get(), blockHtmlRS, frameReflowStatus, aState); + aLine.get(), *blockHtmlRS, frameReflowStatus, aState); // Now the block has a height. Using that height, get the // available space again and call ComputeBlockAvailSpace again. @@ -3433,11 +3435,10 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, clearance = 0; } - blockHtmlRS.~nsHTMLReflowState(); - new (&blockHtmlRS) nsHTMLReflowState(aState.mPresContext, - aState.mReflowState, frame, - availSpace.Size(wm).ConvertTo( - frame->GetWritingMode(), wm)); + blockHtmlRS.reset(); + blockHtmlRS.emplace( + aState.mPresContext, aState.mReflowState, frame, + availSpace.Size(wm).ConvertTo(frame->GetWritingMode(), wm)); } while (true); if (mayNeedRetry && clearanceFrame) { @@ -3449,7 +3450,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, aState.mPrevChild = frame; - if (blockHtmlRS.WillReflowAgainForClearance()) { + if (blockHtmlRS->WillReflowAgainForClearance()) { // If an ancestor of ours is going to reflow for clearance, we // need to avoid calling PlaceBlock, because it unsets dirty bits // on the child block (both itself, and through its call to @@ -3487,7 +3488,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, !floatAvailableSpace.mHasFloats; nsCollapsingMargin collapsedBEndMargin; nsOverflowAreas overflowAreas; - *aKeepReflowGoing = brc.PlaceBlock(blockHtmlRS, forceFit, aLine.get(), + *aKeepReflowGoing = brc.PlaceBlock(*blockHtmlRS, forceFit, aLine.get(), collapsedBEndMargin, overflowAreas, frameReflowStatus); From 4eb5ae47a78ecaa047c5f037e936795bce11b131 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 3 Feb 2016 14:44:12 -0600 Subject: [PATCH 093/160] Also back out bug 1243072 for mac bustage on a CLOSED TREE --- gfx/gl/GLTextureImage.cpp | 23 +-------- gfx/gl/GLTextureImage.h | 7 +-- gfx/gl/GLUploadHelpers.cpp | 62 ++----------------------- gfx/gl/GLUploadHelpers.h | 3 -- gfx/gl/GfxTexturesReporter.cpp | 85 +++++++++++++++++++++++++++++++--- gfx/gl/GfxTexturesReporter.h | 13 +++--- gfx/gl/TextureImageEGL.cpp | 5 -- 7 files changed, 91 insertions(+), 107 deletions(-) diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp index 5663fb3dcdb..6973231126e 100644 --- a/gfx/gl/GLTextureImage.cpp +++ b/gfx/gl/GLTextureImage.cpp @@ -12,7 +12,6 @@ #include "mozilla/gfx/2D.h" #include "ScopedGLHelpers.h" #include "GLUploadHelpers.h" -#include "GfxTexturesReporter.h" #include "TextureImageEGL.h" #ifdef XP_MACOSX @@ -96,16 +95,6 @@ gfx::IntRect TextureImage::GetSrcTileRect() { return GetTileRect(); } -void -TextureImage::UpdateUploadSize(size_t amount) -{ - if (mUploadSize > 0) { - GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryFreed, mUploadSize); - } - mUploadSize = amount; - GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryAllocated, mUploadSize); -} - BasicTextureImage::~BasicTextureImage() { GLContext *ctx = mGLContext; @@ -173,20 +162,16 @@ BasicTextureImage::EndUpdate() RefPtr updateData = updateSnapshot->GetDataSurface(); bool relative = FinishedSurfaceUpdate(); - size_t uploadSize; + mTextureFormat = UploadSurfaceToTexture(mGLContext, updateData, mUpdateRegion, mTexture, - &uploadSize, mTextureState == Created, mUpdateOffset, relative); FinishedSurfaceUpload(); - if (uploadSize > 0) { - UpdateUploadSize(uploadSize); - } mUpdateDrawTarget = nullptr; mTextureState = Valid; @@ -229,19 +214,14 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion region = aRegion; } - size_t uploadSize; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, - &uploadSize, mTextureState == Created, bounds.TopLeft() + IntPoint(aFrom.x, aFrom.y), false); - if (uploadSize > 0) { - UpdateUploadSize(uploadSize); - } mTextureState = Valid; return true; } @@ -293,7 +273,6 @@ TextureImage::TextureImage(const gfx::IntSize& aSize, , mTextureFormat(gfx::SurfaceFormat::UNKNOWN) , mFilter(Filter::GOOD) , mFlags(aFlags) - , mUploadSize(0) {} BasicTextureImage::BasicTextureImage(GLuint aTexture, diff --git a/gfx/gl/GLTextureImage.h b/gfx/gl/GLTextureImage.h index 958d6ae5067..231f6b6d182 100644 --- a/gfx/gl/GLTextureImage.h +++ b/gfx/gl/GLTextureImage.h @@ -203,8 +203,6 @@ public: protected: friend class GLContext; - void UpdateUploadSize(size_t amount); - /** * After the ctor, the TextureImage is invalid. Implementations * must allocate resources successfully before returning the new @@ -216,9 +214,7 @@ protected: Flags aFlags = NoFlags); // Protected destructor, to discourage deletion outside of Release(): - virtual ~TextureImage() { - UpdateUploadSize(0); - } + virtual ~TextureImage() {} virtual gfx::IntRect GetSrcTileRect(); @@ -228,7 +224,6 @@ protected: gfx::SurfaceFormat mTextureFormat; gfx::Filter mFilter; Flags mFlags; - size_t mUploadSize; }; /** diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp index fa37dd0b8d6..b92c47a61d9 100644 --- a/gfx/gl/GLUploadHelpers.cpp +++ b/gfx/gl/GLUploadHelpers.cpp @@ -9,7 +9,6 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Tools.h" // For BytesPerPixel #include "nsRegion.h" -#include "GfxTexturesReporter.h" namespace mozilla { @@ -380,50 +379,6 @@ TexImage2DHelper(GLContext *gl, } } -static uint32_t -GetBytesPerTexel(GLenum format, GLenum type) -{ - // If there is no defined format or type, we're not taking up any memory - if (!format || !type) { - return 0; - } - - if (format == LOCAL_GL_DEPTH_COMPONENT) { - if (type == LOCAL_GL_UNSIGNED_SHORT) - return 2; - else if (type == LOCAL_GL_UNSIGNED_INT) - return 4; - } else if (format == LOCAL_GL_DEPTH_STENCIL) { - if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) - return 4; - } - - if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) { - uint32_t multiplier = type == LOCAL_GL_FLOAT ? 4 : 1; - switch (format) { - case LOCAL_GL_ALPHA: - case LOCAL_GL_LUMINANCE: - return 1 * multiplier; - case LOCAL_GL_LUMINANCE_ALPHA: - return 2 * multiplier; - case LOCAL_GL_RGB: - return 3 * multiplier; - case LOCAL_GL_RGBA: - return 4 * multiplier; - default: - break; - } - } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 || - type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 || - type == LOCAL_GL_UNSIGNED_SHORT_5_6_5) - { - return 2; - } - - MOZ_RELEASE_ASSERT(false, "Unknown type and/or format"); - return 0; -} - SurfaceFormat UploadImageDataToTexture(GLContext* gl, unsigned char* aData, @@ -431,7 +386,6 @@ UploadImageDataToTexture(GLContext* gl, SurfaceFormat aFormat, const nsIntRegion& aDstRegion, GLuint& aTexture, - size_t* aOutUploadSize, bool aOverwrite, bool aPixelBuffer, GLenum aTextureUnit, @@ -551,10 +505,6 @@ UploadImageDataToTexture(GLContext* gl, // Top left point of the region's bounding rectangle. IntPoint topLeft = paintRegion.GetBounds().TopLeft(); - if (aOutUploadSize) { - *aOutUploadSize = 0; - } - for (auto iter = paintRegion.RectIter(); !iter.Done(); iter.Next()) { const IntRect& rect = iter.Get(); // The inital data pointer is at the top left point of the region's @@ -594,11 +544,6 @@ UploadImageDataToTexture(GLContext* gl, rectData); } - if (aOutUploadSize && !textureInited) { - uint32_t texelSize = GetBytesPerTexel(internalFormat, type); - size_t numTexels = size_t(rect.width) * size_t(rect.height); - *aOutUploadSize += texelSize * numTexels; - } } return surfaceFormat; @@ -606,10 +551,9 @@ UploadImageDataToTexture(GLContext* gl, SurfaceFormat UploadSurfaceToTexture(GLContext* gl, - DataSourceSurface* aSurface, + DataSourceSurface *aSurface, const nsIntRegion& aDstRegion, GLuint& aTexture, - size_t* aOutUploadSize, bool aOverwrite, const gfx::IntPoint& aSrcPoint, bool aPixelBuffer, @@ -621,8 +565,8 @@ UploadSurfaceToTexture(GLContext* gl, SurfaceFormat format = aSurface->GetFormat(); data += DataOffset(aSrcPoint, stride, format); return UploadImageDataToTexture(gl, data, stride, format, - aDstRegion, aTexture, aOutUploadSize, - aOverwrite, aPixelBuffer, aTextureUnit, + aDstRegion, aTexture, aOverwrite, + aPixelBuffer, aTextureUnit, aTextureTarget); } diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h index 25a3348855a..46db6fe0681 100644 --- a/gfx/gl/GLUploadHelpers.h +++ b/gfx/gl/GLUploadHelpers.h @@ -40,7 +40,6 @@ class GLContext; * \param aData Image data to upload. * \param aDstRegion Region of texture to upload to. * \param aTexture Texture to use, or 0 to have one created for you. - * \param aOutUploadSize if set, the number of bytes the texture requires will be returned here * \param aOverwrite Over an existing texture with a new one. * \param aSrcPoint Offset into aSrc where the region's bound's * TopLeft() sits. @@ -60,7 +59,6 @@ UploadImageDataToTexture(GLContext* gl, gfx::SurfaceFormat aFormat, const nsIntRegion& aDstRegion, GLuint& aTexture, - size_t* aOutUploadSize = nullptr, bool aOverwrite = false, bool aPixelBuffer = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0, @@ -74,7 +72,6 @@ UploadSurfaceToTexture(GLContext* gl, gfx::DataSourceSurface *aSurface, const nsIntRegion& aDstRegion, GLuint& aTexture, - size_t* aOutUploadSize = nullptr, bool aOverwrite = false, const gfx::IntPoint& aSrcPoint = gfx::IntPoint(0, 0), bool aPixelBuffer = false, diff --git a/gfx/gl/GfxTexturesReporter.cpp b/gfx/gl/GfxTexturesReporter.cpp index 416349c0b2c..c4d97e9ad66 100644 --- a/gfx/gl/GfxTexturesReporter.cpp +++ b/gfx/gl/GfxTexturesReporter.cpp @@ -5,22 +5,95 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GfxTexturesReporter.h" +#include "GLDefs.h" using namespace mozilla; using namespace mozilla::gl; NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter) -Atomic GfxTexturesReporter::sAmount(0); -Atomic GfxTexturesReporter::sTileWasteAmount(0); +Atomic GfxTexturesReporter::sAmount(0); +Atomic GfxTexturesReporter::sTileWasteAmount(0); + +static uint32_t +GetBitsPerTexel(GLenum format, GLenum type) +{ + // If there is no defined format or type, we're not taking up any memory + if (!format || !type) { + return 0; + } + + if (format == LOCAL_GL_DEPTH_COMPONENT) { + if (type == LOCAL_GL_UNSIGNED_SHORT) + return 2*8; + else if (type == LOCAL_GL_UNSIGNED_INT) + return 4*8; + } else if (format == LOCAL_GL_DEPTH_STENCIL) { + if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) + return 4*8; + } + + if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) { + uint32_t multiplier = type == LOCAL_GL_FLOAT ? 32 : 8; + switch (format) { + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + return 1 * multiplier; + case LOCAL_GL_LUMINANCE_ALPHA: + return 2 * multiplier; + case LOCAL_GL_RGB: + return 3 * multiplier; + case LOCAL_GL_RGBA: + return 4 * multiplier; + case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1: + case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1: + return 2; + case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case LOCAL_GL_ATC_RGB: + case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1: + case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1: + case LOCAL_GL_ETC1_RGB8_OES: + case LOCAL_GL_COMPRESSED_RGB8_ETC2: + case LOCAL_GL_COMPRESSED_SRGB8_ETC2: + case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case LOCAL_GL_COMPRESSED_R11_EAC: + case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC: + return 4; + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA: + case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA: + case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC: + case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case LOCAL_GL_COMPRESSED_RG11_EAC: + case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC: + return 8; + default: + break; + } + } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 || + type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 || + type == LOCAL_GL_UNSIGNED_SHORT_5_6_5) + { + return 2*8; + } + + MOZ_ASSERT(false); + return 0; +} /* static */ void -GfxTexturesReporter::UpdateAmount(MemoryUse action, size_t amount) +GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format, + GLenum type, int32_t tileWidth, + int32_t tileHeight) { + int64_t bitsPerTexel = GetBitsPerTexel(format, type); + int64_t bytes = int64_t(tileWidth) * int64_t(tileHeight) * bitsPerTexel/8; if (action == MemoryFreed) { - MOZ_RELEASE_ASSERT(amount <= sAmount); - sAmount -= amount; + sAmount -= bytes; } else { - sAmount += amount; + sAmount += bytes; } } diff --git a/gfx/gl/GfxTexturesReporter.h b/gfx/gl/GfxTexturesReporter.h index 7553853f144..89f9c4d151d 100644 --- a/gfx/gl/GfxTexturesReporter.h +++ b/gfx/gl/GfxTexturesReporter.h @@ -41,9 +41,10 @@ public: // When memory is used/freed for tile textures, call this method to update // the value reported by this memory reporter. - static void UpdateAmount(MemoryUse action, size_t amount); + static void UpdateAmount(MemoryUse action, GLenum format, GLenum type, + int32_t tileWidth, int32_t tileHeight); - static void UpdateWasteAmount(size_t delta) { + static void UpdateWasteAmount(int32_t delta) { sTileWasteAmount += delta; } @@ -51,17 +52,17 @@ public: nsISupports* aData, bool aAnonymize) override { MOZ_COLLECT_REPORT("gfx-tiles-waste", KIND_OTHER, UNITS_BYTES, - int64_t(sTileWasteAmount), + sTileWasteAmount, "Memory lost due to tiles extending past content boundaries"); return MOZ_COLLECT_REPORT( - "gfx-textures", KIND_OTHER, UNITS_BYTES, int64_t(sAmount), + "gfx-textures", KIND_OTHER, UNITS_BYTES, sAmount, "Memory used for storing GL textures."); } private: - static Atomic sAmount; + static Atomic sAmount; // Count the amount of memory lost to tile waste - static Atomic sTileWasteAmount; + static Atomic sTileWasteAmount; }; class GfxTextureWasteTracker { diff --git a/gfx/gl/TextureImageEGL.cpp b/gfx/gl/TextureImageEGL.cpp index 31150f08b7e..1f4323b60e6 100644 --- a/gfx/gl/TextureImageEGL.cpp +++ b/gfx/gl/TextureImageEGL.cpp @@ -207,19 +207,14 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& region = aRegion; } - size_t uploadSize = 0; mTextureFormat = UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, - &uploadSize, mTextureState == Created, bounds.TopLeft() + gfx::IntPoint(aFrom.x, aFrom.y), false); - if (uploadSize > 0) { - UpdateUploadSize(uploadSize); - } mTextureState = Valid; return true; From a815623c0344e93a01a194d49bc3ae04dbb04b85 Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Wed, 3 Feb 2016 13:59:26 -0500 Subject: [PATCH 094/160] Bug 1245586 - add debugging aids for thread shutdown; r=khuey These bits were helpful in debugging recent thread shutdown leaks. --- xpcom/threads/nsThread.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index 1df052b7f6e..2fcd6ad512c 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -36,6 +36,7 @@ #include "nsXPCOMPrivate.h" #include "mozilla/ChaosMode.h" #include "mozilla/TimeStamp.h" +#include "mozilla/unused.h" #include "nsThreadSyncDispatch.h" #include "LeakRefPtr.h" @@ -238,6 +239,15 @@ private: struct nsThreadShutdownContext { + nsThreadShutdownContext() + { + MOZ_COUNT_CTOR(nsThreadShutdownContext); + } + ~nsThreadShutdownContext() + { + MOZ_COUNT_DTOR(nsThreadShutdownContext); + } + // NB: This will be the last reference. RefPtr terminatingThread; nsThread* joiningThread; @@ -505,6 +515,19 @@ nsThread::nsThread(MainThreadFlag aMainThread, uint32_t aStackSize) nsThread::~nsThread() { + NS_ASSERTION(mRequestedShutdownContexts.IsEmpty(), + "shouldn't be waiting on other threads to shutdown"); +#ifdef DEBUG + // We deliberately leak these so they can be tracked by the leak checker. + // If you're having nsThreadShutdownContext leaks, you can set: + // XPCOM_MEM_LOG_CLASSES=nsThreadShutdownContext + // during a test run and that will at least tell you what thread is + // requesting shutdown on another, which can be helpful for diagnosing + // the leak. + for (size_t i = 0; i < mRequestedShutdownContexts.Length(); ++i) { + Unused << mRequestedShutdownContexts[i].forget(); + } +#endif } nsresult From c6093e6eb29a4da7b4486929eb140254bb2c771b Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 3 Feb 2016 13:30:45 -0800 Subject: [PATCH 095/160] Bug 1245182: Move a few event handling functions to nsPIDOMWindowInner. r=smaug --- dom/base/nsPIDOMWindow.h | 122 +++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 63 deletions(-) diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index c76852e5a65..23cfc7d6114 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -151,32 +151,6 @@ public: return mParentTarget; } - bool HasMutationListeners(uint32_t aMutationEventType) const - { - MOZ_ASSERT(IsInnerWindow()); - - if (!mOuterWindow) { - NS_ERROR("HasMutationListeners() called on orphan inner window!"); - - return false; - } - - return (mMutationBits & aMutationEventType) != 0; - } - - void SetMutationListeners(uint32_t aType) - { - MOZ_ASSERT(IsInnerWindow()); - - if (!mOuterWindow) { - NS_ERROR("HasMutationListeners() called on orphan inner window!"); - - return; - } - - mMutationBits |= aType; - } - virtual void MaybeUpdateTouchState() {} nsIDocument* GetExtantDoc() const @@ -383,43 +357,6 @@ public: */ virtual void FinishFullscreenChange(bool aIsFullscreen) = 0; - /** - * Call this to check whether some node (this window, its document, - * or content in that document) has a mouseenter/leave event listener. - */ - bool HasMouseEnterLeaveEventListeners() - { - return mMayHaveMouseEnterLeaveEventListener; - } - - /** - * Call this to indicate that some node (this window, its document, - * or content in that document) has a mouseenter/leave event listener. - */ - void SetHasMouseEnterLeaveEventListeners() - { - mMayHaveMouseEnterLeaveEventListener = true; - } - - /** - * Call this to check whether some node (this window, its document, - * or content in that document) has a Pointerenter/leave event listener. - */ - bool HasPointerEnterLeaveEventListeners() - { - return mMayHavePointerEnterLeaveEventListener; - } - - /** - * Call this to indicate that some node (this window, its document, - * or content in that document) has a Pointerenter/leave event listener. - */ - void SetHasPointerEnterLeaveEventListeners() - { - mMayHavePointerEnterLeaveEventListener = true; - } - - virtual JSObject* GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) = 0; virtual void CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey, JS::Handle aHandler) = 0; @@ -798,6 +735,65 @@ public: nsPerformance* GetPerformance(); + bool HasMutationListeners(uint32_t aMutationEventType) const + { + if (!mOuterWindow) { + NS_ERROR("HasMutationListeners() called on orphan inner window!"); + + return false; + } + + return (mMutationBits & aMutationEventType) != 0; + } + + void SetMutationListeners(uint32_t aType) + { + if (!mOuterWindow) { + NS_ERROR("HasMutationListeners() called on orphan inner window!"); + + return; + } + + mMutationBits |= aType; + } + + /** + * Call this to check whether some node (this window, its document, + * or content in that document) has a mouseenter/leave event listener. + */ + bool HasMouseEnterLeaveEventListeners() + { + return mMayHaveMouseEnterLeaveEventListener; + } + + /** + * Call this to indicate that some node (this window, its document, + * or content in that document) has a mouseenter/leave event listener. + */ + void SetHasMouseEnterLeaveEventListeners() + { + mMayHaveMouseEnterLeaveEventListener = true; + } + + /** + * Call this to check whether some node (this window, its document, + * or content in that document) has a Pointerenter/leave event listener. + */ + bool HasPointerEnterLeaveEventListeners() + { + return mMayHavePointerEnterLeaveEventListener; + } + + /** + * Call this to indicate that some node (this window, its document, + * or content in that document) has a Pointerenter/leave event listener. + */ + void SetHasPointerEnterLeaveEventListeners() + { + mMayHavePointerEnterLeaveEventListener = true; + } + + protected: void CreatePerformanceObjectIfNeeded(); }; From 902ce021184b7aa11e19bf8127fb602e4601c3d8 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 3 Feb 2016 13:30:45 -0800 Subject: [PATCH 096/160] Bug 1245185: Remove dead event handling code from nsPIDOMWindow. r=smaug --- dom/base/nsGlobalWindow.h | 10 ++-------- dom/base/nsPIDOMWindow.h | 8 -------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index edfa2e9919f..293643a90cc 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1427,7 +1427,7 @@ public: // |interval| is in milliseconds. nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler, int32_t interval, - bool aIsInterval, int32_t* aReturn) override; + bool aIsInterval, int32_t* aReturn); int32_t SetTimeoutOrInterval(JSContext* aCx, mozilla::dom::Function& aFunction, int32_t aTimeout, @@ -1437,13 +1437,7 @@ public: int32_t aTimeout, bool aIsInterval, mozilla::ErrorResult& aError); void ClearTimeoutOrInterval(int32_t aTimerID, - mozilla::ErrorResult& aError); - nsresult ClearTimeoutOrInterval(int32_t aTimerID) override - { - mozilla::ErrorResult rv; - ClearTimeoutOrInterval(aTimerID, rv); - return rv.StealNSResult(); - } + mozilla::ErrorResult& aError); // JS specific timeout functions (JS args grabbed from context). nsresult ResetTimersForNonBackgroundWindow(); diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 23cfc7d6114..cdf556935d9 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -216,14 +216,6 @@ public: virtual bool IsFrozen() const = 0; - // Add a timeout to this window. - virtual nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler, - int32_t interval, - bool aIsInterval, int32_t *aReturn) = 0; - - // Clear a timeout from this window. - virtual nsresult ClearTimeoutOrInterval(int32_t aTimerID) = 0; - nsPIDOMWindowOuter* GetOuterWindow() { return mIsInnerWindow ? mOuterWindow.get() : AsOuter(); From 8272275b2103a3fd860da4dcf95b870502aed26d Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 3 Feb 2016 13:30:45 -0800 Subject: [PATCH 097/160] Bug 1245306: Devirtualize RefreshCompartmentPrincipal. r=smaug --- dom/base/nsDocument.cpp | 2 +- dom/base/nsGlobalWindow.h | 2 +- dom/base/nsPIDOMWindow.h | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index d4a88f29718..2a3f759b50f 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -2272,7 +2272,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, // Refresh the principal on the compartment. if (nsPIDOMWindowInner* win = GetInnerWindow()) { - win->RefreshCompartmentPrincipal(); + nsGlobalWindow::Cast(win)->RefreshCompartmentPrincipal(); } } diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 293643a90cc..57e3aa2db2e 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -480,7 +480,7 @@ public: bool DispatchResizeEvent(const mozilla::CSSIntSize& aSize); // Inner windows only. - virtual void RefreshCompartmentPrincipal() override; + void RefreshCompartmentPrincipal(); // For accessing protected field mFullScreen friend class FullscreenTransitionTask; diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index cdf556935d9..77bbac8b93e 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -507,14 +507,6 @@ public: */ virtual bool DispatchCustomEvent(const nsAString& aEventName) = 0; - /** - * Call when the document principal may have changed and the compartment - * principal needs to be updated. - * - * Inner windows only. - */ - virtual void RefreshCompartmentPrincipal() = 0; - /** * Like nsIDOMWindow::Open, except that we don't navigate to the given URL. * From 68e8762048bf660cd41e31eccf16a6e801959353 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 3 Feb 2016 13:30:46 -0800 Subject: [PATCH 098/160] Bug 1245314: Restore a null check for a non-existent inner window in form submission. r=baku --- dom/html/HTMLFormElement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 7b1d1c25f7d..a9410f5d8cf 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -1017,7 +1017,7 @@ HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL, do_QueryInterface(inst)); if (formSubmitObserver) { rv = formSubmitObserver->Notify(this, - window->GetCurrentInnerWindow(), + window ? window->GetCurrentInnerWindow() : nullptr, aActionURL, aCancelSubmit); NS_ENSURE_SUCCESS(rv, rv); From af4f71e5b2babf71ff0ec57510d66e8dbe62728b Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 3 Feb 2016 13:30:46 -0800 Subject: [PATCH 099/160] Bug 1244798: Check for null before proceeding. r=smaug --- toolkit/components/typeaheadfind/nsTypeAheadFind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp index 0897e7e60f9..1e4b90a0bac 100644 --- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp +++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp @@ -493,7 +493,7 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly, if (fm) { nsCOMPtr focusedWindow; nsresult rv = fm->GetFocusedWindow(getter_AddRefs(focusedWindow)); - if (NS_SUCCEEDED(rv)) { + if (NS_SUCCEEDED(rv) && focusedWindow) { auto* fwPI = nsPIDOMWindowOuter::From(focusedWindow); nsCOMPtr fwTreeItem (do_QueryInterface(fwPI->GetDocShell(), &rv)); From 82f8cc894772415c3bb9553350bd17ae679808b8 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 3 Feb 2016 11:01:06 -0800 Subject: [PATCH 100/160] Bug 1232229 - Add some instrumentation and more fencing to ArenaLists; r=ehoogeveen --- js/src/jsgc.cpp | 1 + js/src/jsgc.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 25fa074500a..19add8094e3 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3410,6 +3410,7 @@ GCRuntime::sweepBackgroundThings(ZoneList& zones, LifoAlloc& freeBlocks, ThreadT for (unsigned index = 0 ; index < BackgroundFinalizePhases[phase].length ; ++index) { AllocKind kind = BackgroundFinalizePhases[phase].kinds[index]; ArenaHeader* arenas = zone->arenas.arenaListsToSweep[kind]; + MOZ_RELEASE_ASSERT(uintptr_t(arenas) != uintptr_t(-1)); if (arenas) ArenaLists::backgroundFinalize(&fop, arenas, &emptyArenas); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 2ceaa7bbdd4..54ce98097d8 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -594,7 +594,7 @@ class ArenaLists enum BackgroundFinalizeStateEnum { BFS_DONE, BFS_RUN }; - typedef mozilla::Atomic + typedef mozilla::Atomic BackgroundFinalizeState; /* The current background finalization state, accessed atomically. */ From 5206c5981fa1b10f00e22084504e21f3e2b1e941 Mon Sep 17 00:00:00 2001 From: Andrew Halberstadt Date: Mon, 25 Jan 2016 09:55:57 -0500 Subject: [PATCH 101/160] Bug 1231784 - Install specialpowers and mochikit extensions at runtime via AddonManager.loadTemporaryAddon(), r=jgriffin --- build/mobile/remoteautomation.py | 3 +- .../driver/marionette_driver/marionette.py | 5 +- testing/mochitest/bootstrap.js | 84 +++++++++++ testing/mochitest/browser-harness.xul | 2 +- testing/mochitest/browser-test-overlay.xul | 2 +- testing/mochitest/browser-test.js | 89 +++++------- testing/mochitest/install.rdf | 3 + testing/mochitest/jetpack-addon-harness.js | 9 +- testing/mochitest/jetpack-package-harness.js | 9 +- testing/mochitest/mochitest_options.py | 16 ++- testing/mochitest/moz.build | 7 +- testing/mochitest/runtests.py | 136 ++++++++++-------- testing/mochitest/runtestsb2g.py | 22 +-- testing/mochitest/runtestsremote.py | 19 ++- .../{b2g_start_script.js => start_b2g.js} | 0 testing/mochitest/start_desktop.js | 15 ++ testing/profiles/prefs_general.js | 3 + 17 files changed, 274 insertions(+), 150 deletions(-) create mode 100644 testing/mochitest/bootstrap.js rename testing/mochitest/{b2g_start_script.js => start_b2g.js} (100%) create mode 100644 testing/mochitest/start_desktop.js diff --git a/build/mobile/remoteautomation.py b/build/mobile/remoteautomation.py index c402031b3ae..b8940c02954 100644 --- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -7,6 +7,7 @@ import glob import time import re import os +import posixpath import tempfile import shutil import subprocess @@ -214,7 +215,7 @@ class RemoteAutomation(Automation): try: dumpDir = tempfile.mkdtemp() - remoteCrashDir = self._remoteProfile + '/minidumps/' + remoteCrashDir = posixpath.join(self._remoteProfile, 'minidumps') if not self._devicemanager.dirExists(remoteCrashDir): # If crash reporting is enabled (MOZ_CRASHREPORTER=1), the # minidumps directory is automatically created when Fennec diff --git a/testing/marionette/driver/marionette_driver/marionette.py b/testing/marionette/driver/marionette_driver/marionette.py index 3b60feb380f..0c7f66e94a6 100644 --- a/testing/marionette/driver/marionette_driver/marionette.py +++ b/testing/marionette/driver/marionette_driver/marionette.py @@ -1149,8 +1149,11 @@ class Marionette(object): self.host, self.port, self.socket_timeout) - self.protocol, _ = self.client.connect() + + # Call wait_for_port() before attempting to connect in + # the event gecko hasn't started yet. self.wait_for_port(timeout=timeout) + self.protocol, _ = self.client.connect() body = {"capabilities": desired_capabilities, "sessionId": session_id} resp = self._send_message("newSession", body) diff --git a/testing/mochitest/bootstrap.js b/testing/mochitest/bootstrap.js new file mode 100644 index 00000000000..b6111232cf2 --- /dev/null +++ b/testing/mochitest/bootstrap.js @@ -0,0 +1,84 @@ +/* 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/. */ + +const { utils: Cu, interfaces: Ci, classes: Cc } = Components; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +var WindowListener = { + // browser-test.js is only loaded into the first window. Setup that + // needs to happen in all navigator:browser windows should go here. + setupWindow: function(win) { + win.nativeConsole = win.console; + XPCOMUtils.defineLazyModuleGetter(win, "console", + "resource://gre/modules/Console.jsm"); + }, + + tearDownWindow: function(win) { + if (win.nativeConsole) { + win.console = win.nativeConsole; + win.nativeConsole = undefined; + } + }, + + onOpenWindow: function (win) { + win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); + + win.addEventListener("load", function listener() { + win.removeEventListener("load", listener, false); + if (win.document.documentElement.getAttribute("windowtype") == "navigator:browser") { + WindowListener.setupWindow(win); + } + }, false); + } +} + +function loadMochitest(e) { + let flavor = e.detail[0]; + let url = e.detail[1]; + + let win = Services.wm.getMostRecentWindow("navigator:browser"); + win.removeEventListener('mochitest-load', loadMochitest); + + // for mochitest-plain, navigating to the url is all we need + win.loadURI(url); + if (flavor == "mochitest") { + return; + } + + WindowListener.setupWindow(win); + Services.wm.addListener(WindowListener); + + let overlay; + if (flavor == "jetpack-addon") { + overlay = "chrome://mochikit/content/jetpack-addon-overlay.xul"; + } else if (flavor == "jetpack-package") { + overlay = "chrome://mochikit/content/jetpack-package-overlay.xul"; + } else { + overlay = "chrome://mochikit/content/browser-test-overlay.xul"; + } + + win.document.loadOverlay(overlay, null); +} + +function startup(data, reason) { + let win = Services.wm.getMostRecentWindow("navigator:browser"); + // wait for event fired from start_desktop.js containing the + // suite and url to load + win.addEventListener('mochitest-load', loadMochitest); +} + +function shutdown(data, reason) { + let windows = Services.wm.getEnumerator("navigator:browser"); + while (windows.hasMoreElements()) { + let win = windows.getNext().QueryInterface(Ci.nsIDOMWindow); + WindowListener.tearDownWindow(win); + } + + Services.wm.removeListener(WindowListener); +} + +function install(data, reason) {} +function uninstall(data, reason) {} diff --git a/testing/mochitest/browser-harness.xul b/testing/mochitest/browser-harness.xul index a513b66cf09..53edaa552e6 100644 --- a/testing/mochitest/browser-harness.xul +++ b/testing/mochitest/browser-harness.xul @@ -251,7 +251,7 @@ waitForFocus(() => { // Focus the test window and start tests. waitForFocus(() => { - var Tester = new testWin.Tester(links, gDumper, testsFinished); + var Tester = new testWin.Tester(links, gDumper.structuredLogger, testsFinished); Tester.start(); }, testWin); }, window); diff --git a/testing/mochitest/browser-test-overlay.xul b/testing/mochitest/browser-test-overlay.xul index 4c5b71bdd40..2aaaf247f1b 100644 --- a/testing/mochitest/browser-test-overlay.xul +++ b/testing/mochitest/browser-test-overlay.xul @@ -7,7 +7,7 @@ - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html deleted file mode 100644 index 903269e6b66..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html deleted file mode 100644 index 3ac21299c68..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html deleted file mode 100644 index e0b90adbbb5..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html deleted file mode 100644 index 3c7f3867917..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html deleted file mode 100644 index da5aa0a3fbf..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html deleted file mode 100644 index e64ff94848c..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html deleted file mode 100644 index 877c4440bf3..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html deleted file mode 100644 index 3e7b7a39622..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html deleted file mode 100644 index aeb8f271ea0..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html deleted file mode 100644 index 6d68f0b4e2b..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html deleted file mode 100644 index 21c824ad854..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html deleted file mode 100644 index 327625c0184..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html deleted file mode 100644 index c9548139842..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html deleted file mode 100644 index 6ad80011064..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html deleted file mode 100644 index 957171c160e..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html deleted file mode 100644 index 18774d0d68a..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html deleted file mode 100644 index 3b5907a8a88..00000000000 --- a/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - diff --git a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py index 919ba232804..bac482c3d73 100644 --- a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py +++ b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py @@ -28,8 +28,7 @@ def ReadLocalFile(include): return data -kSimpleTestReplacement = ''' - +kSimpleTestReplacement = '''\n
    - -''' +\n''' fin = open(mochiPath, 'rb') fout = open(testPath, 'wb') From 30250cc29bd4fb4b6a45562625edce2dea51b501 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:41:44 +1100 Subject: [PATCH 105/160] Bug 1236745 - Fix infinite loop resulting from block formatting context entering resize oscillation due to considering floats over its whole height when sizing it. r=dholbert What's happening here is that we enter an infinite loop by oscillating between two states. The code assumes that (a) the available space will never grow, only stay the same or shrink, and (b) that we should break out of the loop if it stays the same. This also means we hit the assertion about the available space growing every other time through the loop. This is in the inner loop in nsBlockFrame::ReflowBlockFrame that was introduced in https://hg.mozilla.org/mozilla-central/rev/80ef9bb2c2e9 . The problem is fundamentally a logic error in that code. The makes the assumption that if you reduce the width available to a block formatting context or replaced block-level element, its height does not shrink. (The "replaced block" (really block formatting context) in this case, as in the original testcase, is a scroll frame. I didn't debug the original testcase enough to figure out what caused its sizing characteristics, although a percentage-width image does seem like the most likely candidate.) Without the patch, the reftest test (but not reference) hangs, as does the semi-simplified test in the bug (given a narrow window). With the patch, neither the semi-simplified test in the bug nor the reference hangs, and the reftest passes. --- layout/generic/nsBlockFrame.cpp | 56 +++++++++++++++++++---- layout/reftests/floats/1236745-1-ref.html | 39 ++++++++++++++++ layout/reftests/floats/1236745-1.html | 49 ++++++++++++++++++++ layout/reftests/floats/reftest.list | 1 + 4 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 layout/reftests/floats/1236745-1-ref.html create mode 100644 layout/reftests/floats/1236745-1.html diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 0b176f2e02a..e84acc20895 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -908,21 +908,44 @@ nsBlockFrame::GetPrefWidthTightBounds(nsRenderingContext* aRenderingContext, return NS_OK; } +/** + * Return whether aNewAvailableSpace is smaller *on either side* + * (inline-start or inline-end) than aOldAvailableSpace, so that we know + * if we need to redo layout on an line, replaced block, or block + * formatting context, because its height (which we used to compute + * aNewAvailableSpace) caused it to intersect additional floats. + */ static bool AvailableSpaceShrunk(WritingMode aWM, const LogicalRect& aOldAvailableSpace, - const LogicalRect& aNewAvailableSpace) + const LogicalRect& aNewAvailableSpace, + bool aCanGrow /* debug-only */) { if (aNewAvailableSpace.ISize(aWM) == 0) { // Positions are not significant if the inline size is zero. return aOldAvailableSpace.ISize(aWM) != 0; } - NS_ASSERTION(aOldAvailableSpace.IStart(aWM) <= - aNewAvailableSpace.IStart(aWM) && - aOldAvailableSpace.IEnd(aWM) >= - aNewAvailableSpace.IEnd(aWM), - "available space should never grow"); - return aOldAvailableSpace.ISize(aWM) != aNewAvailableSpace.ISize(aWM); + if (aCanGrow) { + NS_ASSERTION(aNewAvailableSpace.IStart(aWM) <= + aOldAvailableSpace.IStart(aWM) || + aNewAvailableSpace.IEnd(aWM) <= aOldAvailableSpace.IEnd(aWM), + "available space should not shrink on the start side and " + "grow on the end side"); + NS_ASSERTION(aNewAvailableSpace.IStart(aWM) >= + aOldAvailableSpace.IStart(aWM) || + aNewAvailableSpace.IEnd(aWM) >= aOldAvailableSpace.IEnd(aWM), + "available space should not grow on the start side and " + "shrink on the end side"); + } else { + NS_ASSERTION(aOldAvailableSpace.IStart(aWM) <= + aNewAvailableSpace.IStart(aWM) && + aOldAvailableSpace.IEnd(aWM) >= + aNewAvailableSpace.IEnd(aWM), + "available space should never grow"); + } + // Have we shrunk on either side? + return aNewAvailableSpace.IStart(aWM) > aOldAvailableSpace.IStart(aWM) || + aNewAvailableSpace.IEnd(aWM) < aOldAvailableSpace.IEnd(aWM); } static LogicalSize @@ -3379,8 +3402,18 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, // Restore the height to the position of the next band. floatAvailableSpace.mRect.BSize(wm) = oldFloatAvailableSpaceRect.BSize(wm); + // Determine whether the available space shrunk on either side, + // because (the first time round) we now know the block's height, + // and it may intersect additional floats, or (on later + // iterations) because narrowing the width relative to the + // previous time may cause the block to become taller. Note that + // since we're reflowing the block, narrowing the width might also + // make it shorter, so we must pass aCanGrow as true. if (!AvailableSpaceShrunk(wm, oldFloatAvailableSpaceRect, - floatAvailableSpace.mRect)) { + floatAvailableSpace.mRect, true)) { + // The size and position we chose before are fine (i.e., they + // don't cause intersecting with floats that requires a change + // in size or position), so we're done. break; } @@ -4417,8 +4450,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, aFloatAvailableSpace.BSize(wm) = oldFloatAvailableSpace.BSize(wm); // If the available space between the floats is smaller now that we // know the height, return false (and cause another pass with - // LINE_REFLOW_REDO_MORE_FLOATS). - if (AvailableSpaceShrunk(wm, oldFloatAvailableSpace, aFloatAvailableSpace)) { + // LINE_REFLOW_REDO_MORE_FLOATS). We ensure aAvailableSpaceHeight + // never decreases, which means that we can't reduce the set of floats + // we intersect, which means that the available space cannot grow. + if (AvailableSpaceShrunk(wm, oldFloatAvailableSpace, aFloatAvailableSpace, + false)) { return false; } diff --git a/layout/reftests/floats/1236745-1-ref.html b/layout/reftests/floats/1236745-1-ref.html new file mode 100644 index 00000000000..79da184857f --- /dev/null +++ b/layout/reftests/floats/1236745-1-ref.html @@ -0,0 +1,39 @@ + +Reftest, bug 1236745 + + + +
    +
    +
    +
    +
    diff --git a/layout/reftests/floats/1236745-1.html b/layout/reftests/floats/1236745-1.html new file mode 100644 index 00000000000..e1264fb9a54 --- /dev/null +++ b/layout/reftests/floats/1236745-1.html @@ -0,0 +1,49 @@ + +Reftest, bug 1236745 + + + +
    +
    +
    +
    + +
    +
    diff --git a/layout/reftests/floats/reftest.list b/layout/reftests/floats/reftest.list index 801074d4b87..02acdd046e8 100644 --- a/layout/reftests/floats/reftest.list +++ b/layout/reftests/floats/reftest.list @@ -20,6 +20,7 @@ fails == 345369-2.html 345369-2-ref.html == 546048-1.html 546048-1-ref.html == 775350-1.html 775350-1-ref.html == 1114329.html 1114329-ref.html +== 1236745-1.html 1236745-1-ref.html == float-in-rtl-1a.html float-in-rtl-1-ref.html == float-in-rtl-1b.html float-in-rtl-1-ref.html == float-in-rtl-1c.html float-in-rtl-1-ref.html From 898c7bc9b25574d879e5e98b9031934e5acdf4b0 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:02 +1100 Subject: [PATCH 106/160] Bug 823483 patch 1 - Check for percentage max-width in addition to percentage width when deciding to ignore intrinsic min-width of replaced elements. r=dholbert This (modulo changes in later patches) matches the behavior of Chromium and Edge. It increases the set of elements to which this quirky behavior applies. --- layout/base/nsLayoutUtils.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 2cd96e32136..a2bbdc9575a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4548,12 +4548,11 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext, result = nsLayoutUtils::AddPercents(aType, size + coordOutsideSize, pctOutsideSize); } else if (aType == nsLayoutUtils::MIN_ISIZE && - // The only cases of coord-percent-calc() units that - // GetAbsoluteCoord didn't handle are percent and calc()s - // containing percent. - aStyleSize.IsCoordPercentCalcUnit() && + (aStyleSize.HasPercent() || + aStyleMaxSize.HasPercent()) && aFrame->IsFrameOfType(nsIFrame::eReplaced)) { - // A percentage width on replaced elements means they can shrink to 0. + // A percentage width or max-width on replaced elements means they + // can shrink to 0. result = 0; // let |min| handle padding/border/margin } else { // NOTE: We could really do a lot better for percents and for some From 7b38f7df36238837a6923f2503a50454db71ef25 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:02 +1100 Subject: [PATCH 107/160] Bug 823483 patch 2 - Add frame state bit to indicate frame classes that do replaced-element-like sizing. r=dholbert This is needed for patch 3. --- layout/generic/nsHTMLCanvasFrame.h | 3 ++- layout/generic/nsIFrame.h | 5 +++++ layout/generic/nsImageFrame.h | 3 ++- layout/generic/nsPluginFrame.h | 3 ++- layout/generic/nsSubDocumentFrame.h | 4 +++- layout/generic/nsVideoFrame.h | 3 ++- 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsHTMLCanvasFrame.h b/layout/generic/nsHTMLCanvasFrame.h index aada81e0410..db436548746 100644 --- a/layout/generic/nsHTMLCanvasFrame.h +++ b/layout/generic/nsHTMLCanvasFrame.h @@ -86,7 +86,8 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const override { - return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced)); + return nsSplittableFrame::IsFrameOfType(aFlags & + ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); } #ifdef DEBUG_FRAME_DUMP diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index e26436b4676..65869a5ac1b 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2137,6 +2137,11 @@ public: eExcludesIgnorableWhitespace = 1 << 14, eSupportsCSSTransforms = 1 << 15, + // A replaced element that has replaced-element sizing + // characteristics (i.e., like images or iframes), as opposed to + // inline-block sizing characteristics (like form controls). + eReplacedSizing = 1 << 16, + // These are to allow nsFrame::Init to assert that IsFrameOfType // implementations all call the base class method. They are only // meaningful in DEBUG builds. diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 901c69596af..0a400f68416 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -112,7 +112,8 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const override { - return ImageFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced)); + return ImageFrameSuper::IsFrameOfType(aFlags & + ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); } #ifdef DEBUG_FRAME_DUMP diff --git a/layout/generic/nsPluginFrame.h b/layout/generic/nsPluginFrame.h index b04bcd97781..1758b84043b 100644 --- a/layout/generic/nsPluginFrame.h +++ b/layout/generic/nsPluginFrame.h @@ -91,7 +91,8 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const override { - return nsPluginFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced)); + return nsPluginFrameSuper::IsFrameOfType(aFlags & + ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); } virtual bool NeedsView() override { return true; } diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index ddb6eb7d385..98916cfb997 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -38,7 +38,9 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const override { return nsSubDocumentFrameSuper::IsFrameOfType(aFlags & - ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); + ~(nsIFrame::eReplaced | + nsIFrame::eReplacedSizing | + nsIFrame::eReplacedContainsBlock)); } virtual void Init(nsIContent* aContent, diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h index 9c5a9973c3f..f01f07ccd49 100644 --- a/layout/generic/nsVideoFrame.h +++ b/layout/generic/nsVideoFrame.h @@ -77,7 +77,8 @@ public: virtual bool IsFrameOfType(uint32_t aFlags) const override { - return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced)); + return nsSplittableFrame::IsFrameOfType(aFlags & + ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); } virtual nsresult CreateAnonymousContent(nsTArray& aElements) override; From 193030b1b7b0b59784c898dd781abf02af06d1a7 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:02 +1100 Subject: [PATCH 108/160] Bug 823483 patch 3 - Limit effect of percentage width and max-width on intrinsic size to elements with replaced element sizing. r=dholbert This reduces the set of elements to which this quirky behavior applies. This matches the behavior of Chromium and Edge. --- layout/base/nsLayoutUtils.cpp | 2 +- layout/reftests/bugs/reftest.list | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index a2bbdc9575a..5777f67632c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4550,7 +4550,7 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext, } else if (aType == nsLayoutUtils::MIN_ISIZE && (aStyleSize.HasPercent() || aStyleMaxSize.HasPercent()) && - aFrame->IsFrameOfType(nsIFrame::eReplaced)) { + aFrame->IsFrameOfType(nsIFrame::eReplacedSizing)) { // A percentage width or max-width on replaced elements means they // can shrink to 0. result = 0; // let |min| handle padding/border/margin diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index e78fe836b12..4cd322dadfa 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -58,15 +58,15 @@ skip-if(B2G||Mulet) == 28811-1a.html 28811-1-ref.html # Initial mulet triage: pa fuzzy-if(gtkWidget,6,26200) == 28811-1b.html 28811-1-ref.html # Bug 1128229 skip-if(B2G||Mulet) == 28811-2a.html 28811-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(gtkWidget,6,26200) == 28811-2b.html 28811-2-ref.html # Bug 1128229 -== 40596-1a.html 40596-1-ref.html +!= 40596-1a.html 40596-1-ref.html != 40596-1b.html 40596-1-ref.html -== 40596-1c.html 40596-1-ref.html +!= 40596-1c.html 40596-1-ref.html != 40596-1d.html 40596-1-ref.html -== 40596-1e.html 40596-1-ref.html +!= 40596-1e.html 40596-1-ref.html != 40596-1f.html 40596-1-ref.html -== 40596-1g.html 40596-1-ref.html +!= 40596-1g.html 40596-1-ref.html != 40596-1h.html 40596-1-ref.html -== 40596-1i.html 40596-1-ref.html +!= 40596-1i.html 40596-1-ref.html != 40596-1j.html 40596-1-ref.html == 50630-1a.html 50630-1-ref.html == 50630-1b.html 50630-1-ref.html From edb72e8240f95fd2af2ba0f7b282824985286189 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:02 +1100 Subject: [PATCH 109/160] Bug 823483 patch 4 - Make a percentage max-width override a fixed width for replaced element intrinsic size computation. r=dholbert This just reorders the if-else chain to change which conditions are tested first. Prior to patch 1, the order didn't matter, but with patch 1, the order does matter, and the order that we happened to have was the opposite of the one that matches Chromium and Edge. --- layout/base/nsLayoutUtils.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 5777f67632c..999ae265606 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4542,18 +4542,20 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext, pctTotal += pctOutsideSize; nscoord size; - if (GetAbsoluteCoord(aStyleSize, size) || - GetIntrinsicCoord(aStyleSize, aRenderingContext, aFrame, - PROP_WIDTH, size)) { - result = nsLayoutUtils::AddPercents(aType, size + coordOutsideSize, - pctOutsideSize); - } else if (aType == nsLayoutUtils::MIN_ISIZE && - (aStyleSize.HasPercent() || - aStyleMaxSize.HasPercent()) && - aFrame->IsFrameOfType(nsIFrame::eReplacedSizing)) { + if (aType == nsLayoutUtils::MIN_ISIZE && + (aStyleSize.HasPercent() || + aStyleMaxSize.HasPercent()) && + aFrame->IsFrameOfType(nsIFrame::eReplacedSizing)) { // A percentage width or max-width on replaced elements means they // can shrink to 0. + // Note that if this is max-width, this overrides the fixed-width + // rule in the next condition. result = 0; // let |min| handle padding/border/margin + } else if (GetAbsoluteCoord(aStyleSize, size) || + GetIntrinsicCoord(aStyleSize, aRenderingContext, aFrame, + PROP_WIDTH, size)) { + result = nsLayoutUtils::AddPercents(aType, size + coordOutsideSize, + pctOutsideSize); } else { // NOTE: We could really do a lot better for percents and for some // cases of calc() containing percent (certainly including any where From a7fce76906eb1a48145269b18f3b343546f5bda3 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:02 +1100 Subject: [PATCH 110/160] Bug 823483 patch 5 - Make (again) percentage width on text inputs make intrinsic minimum width be 0. r=dholbert This restores the quirky behavior for text inputs, which was removed by patch 2, but only halfway (for width but not max-width), which matches Chromium and Edge. --- layout/base/nsLayoutUtils.cpp | 9 ++++++--- layout/reftests/bugs/reftest.list | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 999ae265606..71424b13c8c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4543,11 +4543,14 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext, nscoord size; if (aType == nsLayoutUtils::MIN_ISIZE && - (aStyleSize.HasPercent() || - aStyleMaxSize.HasPercent()) && - aFrame->IsFrameOfType(nsIFrame::eReplacedSizing)) { + (((aStyleSize.HasPercent() || aStyleMaxSize.HasPercent()) && + aFrame->IsFrameOfType(nsIFrame::eReplacedSizing)) || + (aStyleSize.HasPercent() && + aFrame->GetType() == nsGkAtoms::textInputFrame))) { // A percentage width or max-width on replaced elements means they // can shrink to 0. + // This is also true for percentage widths (but not max-widths) on + // text inputs. // Note that if this is max-width, this overrides the fixed-width // rule in the next condition. result = 0; // let |min| handle padding/border/margin diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 4cd322dadfa..d0abbc89166 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -58,7 +58,7 @@ skip-if(B2G||Mulet) == 28811-1a.html 28811-1-ref.html # Initial mulet triage: pa fuzzy-if(gtkWidget,6,26200) == 28811-1b.html 28811-1-ref.html # Bug 1128229 skip-if(B2G||Mulet) == 28811-2a.html 28811-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(gtkWidget,6,26200) == 28811-2b.html 28811-2-ref.html # Bug 1128229 -!= 40596-1a.html 40596-1-ref.html +== 40596-1a.html 40596-1-ref.html != 40596-1b.html 40596-1-ref.html != 40596-1c.html 40596-1-ref.html != 40596-1d.html 40596-1-ref.html From 9269f6dd16ab289f5d38e1e4465ea7a1f6df2f21 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Thu, 4 Feb 2016 09:43:03 +1100 Subject: [PATCH 111/160] Bug 823483 patch 6 - Tests r=dholbert Our behavior on these tests is reasonably close to matching Chromium thanks to the combination of patches 1, 3, and 4, and 5. --- ...sic-with-percents-across-elements-ref.html | 126 ++++++++++++++++++ ...trinsic-with-percents-across-elements.html | 124 +++++++++++++++++ ...ic-with-percents-across-img-cases-ref.html | 88 ++++++++++++ ...rinsic-with-percents-across-img-cases.html | 88 ++++++++++++ layout/reftests/css-sizing/reftest.list | 2 + layout/reftests/reftest.list | 3 + 6 files changed, 431 insertions(+) create mode 100644 layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements-ref.html create mode 100644 layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements.html create mode 100644 layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases-ref.html create mode 100644 layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases.html create mode 100644 layout/reftests/css-sizing/reftest.list diff --git a/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements-ref.html b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements-ref.html new file mode 100644 index 00000000000..dbd50f8f4bc --- /dev/null +++ b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements-ref.html @@ -0,0 +1,126 @@ + +References for bug 823483 + + + + + +
    img, unstyled
    + + + + +
    img, width: 50%
    + + + + +
    img, max-width: 50%
    + + + + +
    canvas, unstyled
    + + + + +
    canvas, width: 50%
    + + + + +
    canvas, max-width: 50%
    + + + + +
    iframe, almost unstyled
    + + + + +
    iframe, width: 50%
    + + + + +
    iframe, max-width: 50%
    + + + + +
    input type="text", unstyled
    + + + + +
    input type="text", width: 50%
    + + + + +
    input type="text", max-width: 50%
    + + + + +
    empty input type="button", unstyled
    + + + + + +
    empty input type="button", width: 50%
    + + + + + +
    empty input type="button", max-width: 50%
    + + + + +
    nonempty input type="button", unstyled
    + + + + +
    nonempty input type="button", width: 50%
    + + + + +
    nonempty input type="button", max-width: 50%
    + + diff --git a/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements.html b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements.html new file mode 100644 index 00000000000..5abfa93e782 --- /dev/null +++ b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-elements.html @@ -0,0 +1,124 @@ + +Tests for bug 823483 + + + + + +
    img, unstyled
    + + + + +
    img, width: 50%
    + + + + +
    img, max-width: 50%
    + + + + +
    canvas, unstyled
    + + + + +
    canvas, width: 50%
    + + + + +
    canvas, max-width: 50%
    + + + + +
    iframe, almost unstyled
    + + + + +
    iframe, width: 50%
    + + + + +
    iframe, max-width: 50%
    + + + + +
    input type="text", unstyled
    + + + + +
    input type="text", width: 50%
    + + + + +
    input type="text", max-width: 50%
    + + + + +
    empty input type="button", unstyled
    + + + + +
    empty input type="button", width: 50%
    + + + + +
    empty input type="button", max-width: 50%
    + + + + +
    nonempty input type="button", unstyled
    + + + + +
    nonempty input type="button", width: 50%
    + + + + +
    nonempty input type="button", max-width: 50%
    + + diff --git a/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases-ref.html b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases-ref.html new file mode 100644 index 00000000000..efc63f344b8 --- /dev/null +++ b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases-ref.html @@ -0,0 +1,88 @@ + +References for bug 823483 + + + + + + +
    unstyled
    + + + + +
    width: 10px
    + + + + +
    width: 50%
    + + + + +
    min-width: 50%
    + + + + +
    max-width: 50%
    + + + + +
    width: 10px; max-width: 50%
    + + + + +
    width: 10px; min-width: 50%
    + + + + +
    width: 150%
    + + + + +
    min-width: 150%
    + + + + +
    max-width: 150%
    + + + + +
    width: 10px; max-width: 150%
    + + + + +
    width: 10px; min-width: 150%
    + + diff --git a/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases.html b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases.html new file mode 100644 index 00000000000..9679aa04774 --- /dev/null +++ b/layout/reftests/css-sizing/min-intrinsic-with-percents-across-img-cases.html @@ -0,0 +1,88 @@ + +Tests for bug 823483 + + + + + + +
    unstyled
    + + + + +
    width: 10px
    + + + + +
    width: 50%
    + + + + +
    min-width: 50%
    + + + + +
    max-width: 50%
    + + + + +
    width: 10px; max-width: 50%
    + + + + +
    width: 10px; min-width: 50%
    + + + + +
    width: 150%
    + + + + +
    min-width: 150%
    + + + + +
    max-width: 150%
    + + + + +
    width: 10px; max-width: 150%
    + + + + +
    width: 10px; min-width: 150%
    + + diff --git a/layout/reftests/css-sizing/reftest.list b/layout/reftests/css-sizing/reftest.list new file mode 100644 index 00000000000..5ffce29be3e --- /dev/null +++ b/layout/reftests/css-sizing/reftest.list @@ -0,0 +1,2 @@ +== min-intrinsic-with-percents-across-img-cases.html min-intrinsic-with-percents-across-img-cases-ref.html +== min-intrinsic-with-percents-across-elements.html min-intrinsic-with-percents-across-elements-ref.html diff --git a/layout/reftests/reftest.list b/layout/reftests/reftest.list index 0a889acc7e2..e2f55999902 100644 --- a/layout/reftests/reftest.list +++ b/layout/reftests/reftest.list @@ -118,6 +118,9 @@ include text-overflow/reftest.list # css selectors include css-selectors/reftest.list +# css sizing +include css-sizing/reftest.list + # css transitions include css-transitions/reftest.list From 39210a1a9bf1ff55cee18f32e0afc088755125b4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 24 Nov 2015 19:42:28 -0800 Subject: [PATCH 112/160] Bug 1181444 (part 2) - Remove nsBaseHashtable::Enumerate(). r=froydnj. \o/ --- xpcom/glue/nsBaseHashtable.h | 44 ------------------ xpcom/tests/TestHashtables.cpp | 74 +++++++++++++------------------ xpcom/tests/gtest/TestPLDHash.cpp | 4 +- 3 files changed, 34 insertions(+), 88 deletions(-) diff --git a/xpcom/glue/nsBaseHashtable.h b/xpcom/glue/nsBaseHashtable.h index 99705b3f323..d4a708b161f 100644 --- a/xpcom/glue/nsBaseHashtable.h +++ b/xpcom/glue/nsBaseHashtable.h @@ -12,15 +12,6 @@ #include "nsTHashtable.h" #include "nsDebug.h" -// These type is returned by |EnumFunction| and controls the behavior of -// Enumerate(). The PLD/PL_D prefix is because it originated in PLDHashTable, -// but that class no longer uses it. -enum PLDHashOperator -{ - PL_DHASH_NEXT = 0, // enumerator says continue - PL_DHASH_REMOVE = 2 // enumerator says remove -}; - template class nsBaseHashtable; // forward declaration @@ -155,41 +146,6 @@ public: */ void Remove(KeyType aKey) { this->RemoveEntry(aKey); } - /** - * function type provided by the application for enumeration. - * @param aKey the key being enumerated - * @param aData Reference to data being enumerated, may be altered. e.g. for - * nsInterfaceHashtable this is an nsCOMPtr reference... - * @parm aUserArg passed unchanged from Enumerate - * @return bitflag combination of - * @link PLDHashOperator::PL_DHASH_REMOVE @endlink or - * @link PLDHashOperator::PL_DHASH_NEXT PL_DHASH_NEXT @endlink - */ - typedef PLDHashOperator (*EnumFunction)(KeyType aKey, - DataType& aData, - void* aUserArg); - - /** - * enumerate entries in the hashtable, allowing changes. - * WARNING: this function is deprecated. Please use Iterator and/or - * MutatingIterator instead. - * @param aEnumFunc enumeration callback - * @param aUserArg passed unchanged to the EnumFunction - */ - uint32_t Enumerate(EnumFunction aEnumFunc, void* aUserArg) - { - uint32_t n = 0; - for (auto iter = this->mTable.Iter(); !iter.Done(); iter.Next()) { - auto entry = static_cast(iter.Get()); - PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg); - n++; - if (op & PL_DHASH_REMOVE) { - iter.Remove(); - } - } - return n; - } - // This is an iterator that also allows entry removal. Example usage: // // for (auto iter = table.Iter(); !iter.Done(); iter.Next()) { diff --git a/xpcom/tests/TestHashtables.cpp b/xpcom/tests/TestHashtables.cpp index b72fe45985a..9dd4fecd0ce 100644 --- a/xpcom/tests/TestHashtables.cpp +++ b/xpcom/tests/TestHashtables.cpp @@ -170,19 +170,6 @@ testTHashtable(nsTHashtable& hash, uint32_t numEntries) { } } -PLDHashOperator -nsDEnum(const uint32_t& aKey, const char*& aData, void* userArg) { - printf(" enumerated %u = \"%s\"\n", aKey, aData); - return PL_DHASH_NEXT; -} - -PLDHashOperator -nsCEnum(const nsACString& aKey, nsAutoPtr& aData, void* userArg) { - printf(" enumerated \"%s\" = %c\n", - PromiseFlatCString(aKey).get(), aData->GetChar()); - return PL_DHASH_NEXT; -} - // // all this nsIFoo stuff was copied wholesale from TestCOMPtr.cpp // @@ -326,25 +313,6 @@ CreateIFoo( IFoo** result ) return NS_OK; } -PLDHashOperator -nsIEnum(const uint32_t& aKey, nsCOMPtr& aData, void* userArg) { - nsAutoCString str; - aData->GetString(str); - - printf(" enumerated %u = \"%s\"\n", aKey, str.get()); - return PL_DHASH_NEXT; -} - -PLDHashOperator -nsIEnum2(nsISupports* aKey, uint32_t& aData, void* userArg) { - nsAutoCString str; - nsCOMPtr foo = do_QueryInterface(aKey); - foo->GetString(str); - - printf(" enumerated \"%s\" = %u\n", str.get(), aData); - return PL_DHASH_NEXT; -} - } // namespace TestHashtables using namespace TestHashtables; @@ -369,7 +337,7 @@ main(void) { printf("Check enumeration..."); count = nsTIterPrint(EntityToUnicode); - if (count) { + if (count != 0) { printf("entries remain in table!\n"); exit (8); } @@ -384,7 +352,7 @@ main(void) { printf("Check enumeration..."); count = nsTIterPrint(EntityToUnicode); - if (count) { + if (count != 0) { printf("entries remain in table!\n"); exit (9); } @@ -445,8 +413,12 @@ main(void) { printf("OK\n"); printf("Checking count..."); - count = UniToEntity.Enumerate(nsDEnum, nullptr); - if (count) { + count = 0; + for (auto iter = UniToEntity.Iter(); !iter.Done(); iter.Next()) { + printf(" enumerated %u = \"%s\"\n", iter.Key(), iter.Data()); + count++; + } + if (count != 0) { printf(" Clear did not remove all entries.\n"); exit (15); } @@ -510,8 +482,13 @@ main(void) { printf(" Clearing OK\n"); printf("Checking count..."); - count = EntToUniClass.Enumerate(nsCEnum, nullptr); - if (count) { + count = 0; + for (auto iter = EntToUniClass.Iter(); !iter.Done(); iter.Next()) { + printf(" enumerated \"%s\" = %c\n", + PromiseFlatCString(iter.Key()).get(), iter.Data()->GetChar()); + count++; + } + if (count != 0) { printf(" Clear did not remove all entries.\n"); exit (21); } @@ -584,8 +561,15 @@ main(void) { printf(" Clearing OK\n"); printf("Checking count..."); - count = EntToUniClass2.Enumerate(nsIEnum2, nullptr); - if (count) { + count = 0; + for (auto iter = EntToUniClass2.Iter(); !iter.Done(); iter.Next()) { + nsAutoCString s; + nsCOMPtr foo = do_QueryInterface(iter.Key()); + foo->GetString(s); + printf(" enumerated \"%s\" = %u\n", s.get(), iter.Data()); + count++; + } + if (count != 0) { printf(" Clear did not remove all entries.\n"); exit (27); } @@ -656,8 +640,14 @@ main(void) { printf(" Clearing OK\n"); printf("Checking count..."); - count = UniToEntClass2.Enumerate(nsIEnum, nullptr); - if (count) { + count = 0; + for (auto iter = UniToEntClass2.Iter(); !iter.Done(); iter.Next()) { + nsAutoCString s; + iter.Data()->GetString(s); + printf(" enumerated %u = \"%s\"\n", iter.Key(), s.get()); + count++; + } + if (count != 0) { printf(" Clear did not remove all entries.\n"); exit (33); } diff --git a/xpcom/tests/gtest/TestPLDHash.cpp b/xpcom/tests/gtest/TestPLDHash.cpp index e5c82734485..6d7150088cd 100644 --- a/xpcom/tests/gtest/TestPLDHash.cpp +++ b/xpcom/tests/gtest/TestPLDHash.cpp @@ -345,8 +345,8 @@ TEST(PLDHashTableTest, GrowToMaxCapacity) numInserted++; } - // We stop when the element count is 96.875% of PL_DHASH_MAX_SIZE (see - // MaxLoadOnGrowthFailure()). + // We stop when the element count is 96.875% of PLDHashTable::kMaxCapacity + // (see MaxLoadOnGrowthFailure()). if (numInserted != PLDHashTable::kMaxCapacity - (PLDHashTable::kMaxCapacity >> 5)) { delete t; From 9baf1789bad25464d06505f1f2d40bbdb00dd15c Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 3 Feb 2016 15:46:59 -0800 Subject: [PATCH 113/160] Bug 1245286 - Do not access the shell's interruptFunc off the main thread; r=jonco --- js/src/shell/js.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 81c85c02127..23ec93cd058 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -144,6 +144,7 @@ struct ShellRuntime bool isWorker; double timeoutInterval; Atomic serviceInterrupt; + Atomic haveInterruptFunc; JS::PersistentRootedValue interruptFunc; bool lastWarningEnabled; JS::PersistentRootedValue lastWarning; @@ -290,6 +291,7 @@ ShellRuntime::ShellRuntime() : isWorker(false), timeoutInterval(-1.0), serviceInterrupt(false), + haveInterruptFunc(false), lastWarningEnabled(false), watchdogLock(nullptr), watchdogWakeup(nullptr), @@ -430,12 +432,11 @@ ShellInterruptCallback(JSContext* cx) sr->serviceInterrupt = false; bool result; - RootedValue interruptFunc(cx, sr->interruptFunc); - if (!interruptFunc.isNull()) { + if (sr->haveInterruptFunc) { JS::AutoSaveExceptionState savedExc(cx); - JSAutoCompartment ac(cx, &interruptFunc.toObject()); + JSAutoCompartment ac(cx, &sr->interruptFunc.toObject()); RootedValue rval(cx); - if (!JS_CallFunctionValue(cx, nullptr, interruptFunc, + if (!JS_CallFunctionValue(cx, nullptr, sr->interruptFunc, JS::HandleValueArray::empty(), &rval)) { return false; @@ -3126,7 +3127,7 @@ CancelExecution(JSRuntime* rt) sr->serviceInterrupt = true; JS_RequestInterruptCallback(rt); - if (!sr->interruptFunc.isNull()) { + if (sr->haveInterruptFunc) { static const char msg[] = "Script runs for too long, terminating.\n"; fputs(msg, stderr); } @@ -3175,6 +3176,7 @@ Timeout(JSContext* cx, unsigned argc, Value* vp) return false; } sr->interruptFunc = value; + sr->haveInterruptFunc = true; } args.rval().setUndefined(); @@ -3246,6 +3248,7 @@ SetInterruptCallback(JSContext* cx, unsigned argc, Value* vp) return false; } GetShellRuntime(cx)->interruptFunc = value; + GetShellRuntime(cx)->haveInterruptFunc = true; args.rval().setUndefined(); return true; From bfad5deb296d15edb21d3580ed0f9f4be2f0e129 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 3 Feb 2016 15:49:04 -0800 Subject: [PATCH 114/160] Bug 1141579 - Synchronize access to warmUpCount; r=jandem --- js/src/jsscript.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/js/src/jsscript.h b/js/src/jsscript.h index b13598cbe0a..2ef42fe054f 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -1045,11 +1045,10 @@ class JSScript : public js::gc::TenuredCell uint32_t sourceStart_; uint32_t sourceEnd_; - uint32_t warmUpCount; /* Number of times the script has been called - * or has had backedges taken. When running in - * ion, also increased for any inlined scripts. - * Reset if the script's JIT code is forcibly - * discarded. */ + // Number of times the script has been called or has had backedges taken. + // When running in ion, also increased for any inlined scripts. Reset if + // the script's JIT code is forcibly discarded. + mozilla::Atomic warmUpCount; // 16-bit fields. @@ -1714,7 +1713,7 @@ class JSScript : public js::gc::TenuredCell public: uint32_t getWarmUpCount() const { return warmUpCount; } uint32_t incWarmUpCounter(uint32_t amount = 1) { return warmUpCount += amount; } - uint32_t* addressOfWarmUpCounter() { return &warmUpCount; } + uint32_t* addressOfWarmUpCounter() { return reinterpret_cast(&warmUpCount); } static size_t offsetOfWarmUpCounter() { return offsetof(JSScript, warmUpCount); } void resetWarmUpCounter() { incWarmUpResetCounter(); warmUpCount = 0; } From b3d6037c8be86c27be9de4e261871450515ef28d Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Thu, 4 Feb 2016 10:45:08 +1100 Subject: [PATCH 115/160] Bug 1181981: [MSE] Force TrackId for MSE tracks. r=gerald YouTube sets the track ID at 1 for both audio and video tracks. Attempting to use mozCaptureStream would cause an assert as it always expect tracks to have a different track Id. --- dom/media/mediasource/TrackBuffersManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp index 20f42b1e0c9..a83e5e8059b 100644 --- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -936,6 +936,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult) mVideoTracks.mDemuxer = mInputDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0); MOZ_ASSERT(mVideoTracks.mDemuxer); info.mVideo = *mVideoTracks.mDemuxer->GetInfo()->GetAsVideoInfo(); + info.mVideo.mTrackId = 2; } uint32_t numAudios = mInputDemuxer->GetNumberTracks(TrackInfo::kAudioTrack); @@ -944,6 +945,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult) mAudioTracks.mDemuxer = mInputDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0); MOZ_ASSERT(mAudioTracks.mDemuxer); info.mAudio = *mAudioTracks.mDemuxer->GetInfo()->GetAsAudioInfo(); + info.mAudio.mTrackId = 1; } int64_t videoDuration = numVideos ? info.mVideo.mDuration : 0; From 6ceb1b2b3a6f4a24e1dd86df820e00775487f6e7 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 19:13:34 -0500 Subject: [PATCH 116/160] Bug 990916 - Disable synth mousemove events during pointer event testing, since the test doesn't expect them and fails. r=smaug --- layout/base/tests/test_bug976963.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/base/tests/test_bug976963.html b/layout/base/tests/test_bug976963.html index 374759cdeba..4b8da3a6e8b 100644 --- a/layout/base/tests/test_bug976963.html +++ b/layout/base/tests/test_bug976963.html @@ -15,7 +15,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=976963 SimpleTest.requestFlakyTimeout("untriaged"); SpecialPowers.pushPrefEnv({ "set": [ - ["dom.w3c_pointer_events.enabled", true] + ["dom.w3c_pointer_events.enabled", true], + ["layout.reflow.synthMouseMove", false] ] }, startTest); } From 7ecf5868d8960428855e2a9c22800500d5090466 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 19:13:35 -0500 Subject: [PATCH 117/160] Bug 990916 - Track if a scrollframe is a scroll parent for something else. r=tnikkel --- layout/generic/nsGfxScrollFrame.cpp | 6 +++++- layout/generic/nsGfxScrollFrame.h | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 5f8c2014bcc..fed7e36e16b 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1861,6 +1861,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, , mHasBeenScrolledRecently(false) , mCollapsedResizer(false) , mWillBuildScrollableLayer(false) + , mIsScrollParent(false) , mIsScrollableLayerInRootContainer(false) , mHasBeenScrolled(false) , mIgnoreMomentumScroll(false) @@ -3179,6 +3180,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, clipNonCaret, scrollClipNonCaret); } + if (aBuilder->IsPaintingToWindow()) { + mIsScrollParent = idSetter.ShouldForceLayerForScrollParent(); + } if (idSetter.ShouldForceLayerForScrollParent() && !gfxPrefs::LayoutUseContainersForRootFrames()) { @@ -3209,7 +3213,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder, } } - if (mWillBuildScrollableLayer && !gfxPrefs::LayoutUseContainersForRootFrames()) { + if (mWillBuildScrollableLayer) { aBuilder->ForceLayerForScrollParent(); } diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index cf7d666a268..fa7903cf2c7 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -509,6 +509,11 @@ public: // a scrollable layer. Used for asynchronous scrolling. bool mWillBuildScrollableLayer:1; + // If true, the scroll frame is an ancestor of other scrolling frames, so + // we shouldn't expire the displayport on this scrollframe unless those + // descendant scrollframes also have their displayports removed. + bool mIsScrollParent:1; + // Whether we are the root scroll frame that is used for containerful // scrolling with a display port. If true, the scrollable frame // shouldn't attach frame metrics to its layers because the container From 8981ef60ee617ec20028c066791e5d00b443940f Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 19:13:35 -0500 Subject: [PATCH 118/160] Bug 990916 - When setting a displayport, schedule a timer to remove it as well. r=tnikkel --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 8 +++ gfx/thebes/gfxPrefs.h | 1 + layout/base/nsLayoutUtils.cpp | 13 +++- layout/base/nsLayoutUtils.h | 5 ++ layout/generic/nsGfxScrollFrame.cpp | 67 +++++++++++++++++++ layout/generic/nsGfxScrollFrame.h | 12 ++++ layout/generic/nsIScrollableFrame.h | 7 ++ modules/libpref/init/all.js | 1 + 8 files changed, 112 insertions(+), 2 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 7e639c0008d..9bcc9473f5b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -155,6 +155,14 @@ using mozilla::gfx::PointTyped; * pixels would make us drop to low-res at y=490...990.\n * This value is in layer pixels. * + * \li\b apz.displayport_expiry_ms + * While a scrollable frame is scrolling async, we set a displayport on it + * to make sure it is layerized. However this takes up memory, so once the + * scrolling stops we want to remove the displayport. This pref controls how + * long after scrolling stops the displayport is removed. A value of 0 will + * disable the expiry behavior entirely. + * Units: milliseconds + * * \li\b apz.enlarge_displayport_when_clipped * Pref that enables enlarging of the displayport along one axis when the * generated displayport's size is beyond that of the scrollable rect on the diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index ad2f85f8fa8..95af19c2485 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -148,6 +148,7 @@ private: DECL_GFX_PREF(Live, "apz.content_response_timeout", APZContentResponseTimeout, int32_t, 300); DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50); DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100); + DECL_GFX_PREF(Live, "apz.displayport_expiry_ms", APZDisplayPortExpiryTime, uint32_t, 15000); DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false); DECL_GFX_PREF(Live, "apz.enlarge_displayport_when_clipped", APZEnlargeDisplayPortWhenClipped, bool, false); DECL_GFX_PREF(Live, "apz.fling_accel_base_mult", APZFlingAccelBaseMultiplier, float, 1.0f); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 71424b13c8c..bcc8909b8d5 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1175,14 +1175,16 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent, } } - // Display port margins changing means that the set of visible images may - // have drastically changed. Check if we should schedule an update. nsIFrame* frame = GetScrollFrameFromContent(aContent); nsIScrollableFrame* scrollableFrame = frame ? frame->GetScrollTargetFrame() : nullptr; if (!scrollableFrame) { return true; } + scrollableFrame->TriggerDisplayPortExpiration(); + + // Display port margins changing means that the set of visible images may + // have drastically changed. Check if we should schedule an update. nsRect oldDisplayPort; bool hadDisplayPort = scrollableFrame->GetDisplayPortAtLastImageVisibilityUpdate(&oldDisplayPort); @@ -1249,6 +1251,13 @@ nsLayoutUtils::HasCriticalDisplayPort(nsIContent* aContent) return GetCriticalDisplayPort(aContent, nullptr); } +void +nsLayoutUtils::RemoveDisplayPort(nsIContent* aContent) +{ + aContent->DeleteProperty(nsGkAtoms::DisplayPort); + aContent->DeleteProperty(nsGkAtoms::DisplayPortMargins); +} + nsContainerFrame* nsLayoutUtils::LastContinuationWithChild(nsContainerFrame* aFrame) { diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 54532ba20ff..dc5d95c7088 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -242,6 +242,11 @@ public: */ static bool HasCriticalDisplayPort(nsIContent* aContent); + /** + * Remove the displayport for the given element. + */ + static void RemoveDisplayPort(nsIContent* aContent); + /** * Use heuristics to figure out the child list that * aChildFrame is currently in. diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index fed7e36e16b..23e5f915775 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1909,6 +1909,10 @@ ScrollFrameHelper::~ScrollFrameHelper() mScrollActivityTimer->Cancel(); mScrollActivityTimer = nullptr; } + if (mDisplayPortExpiryTimer) { + mDisplayPortExpiryTimer->Cancel(); + mDisplayPortExpiryTimer = nullptr; + } } /* @@ -2332,6 +2336,39 @@ bool ScrollFrameHelper::IsAlwaysActive() const styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN); } +/*static*/ void +RemoveDisplayPortCallback(nsITimer* aTimer, void* aClosure) +{ + ScrollFrameHelper* helper = static_cast(aClosure); + + // This function only ever gets called from the expiry timer, so it must + // be non-null here. Set it to null here so that we don't keep resetting + // it unnecessarily in MarkRecentlyScrolled(). + MOZ_ASSERT(helper->mDisplayPortExpiryTimer); + helper->mDisplayPortExpiryTimer = nullptr; + + if (helper->IsAlwaysActive() || helper->mIsScrollParent) { + // If this is a scroll parent for some other scrollable frame, don't + // expire the displayport because it would break scroll handoff. + return; + } + + // Remove the displayport from this scrollframe if it's been a while + // since it's scrolled, except if it needs to be always active. Note that + // there is one scrollframe that doesn't fall under this general rule, and + // that is the one that nsLayoutUtils::MaybeCreateDisplayPort decides to put + // a displayport on (i.e. the first scrollframe that WantAsyncScroll()s). + // If that scrollframe is this one, we remove the displayport anyway, and + // as part of the next paint MaybeCreateDisplayPort will put another + // displayport back on it. Although the displayport will "flicker" off and + // back on, the layer itself should never disappear, because this all + // happens between actual painting. If the displayport is reset to a + // different position that's ok; this scrollframe hasn't been scrolled + // recently and so the reset should be correct. + nsLayoutUtils::RemoveDisplayPort(helper->mOuter->GetContent()); + helper->mOuter->SchedulePaint(); +} + void ScrollFrameHelper::MarkNotRecentlyScrolled() { if (!mHasBeenScrolledRecently) @@ -2355,6 +2392,36 @@ void ScrollFrameHelper::MarkRecentlyScrolled() } gScrollFrameActivityTracker->AddObject(this); } + + // If we just scrolled and there's a displayport expiry timer in place, + // reset the timer. + ResetDisplayPortExpiryTimer(); +} + +void ScrollFrameHelper::ResetDisplayPortExpiryTimer() +{ + if (mDisplayPortExpiryTimer) { + mDisplayPortExpiryTimer->InitWithFuncCallback( + RemoveDisplayPortCallback, this, + gfxPrefs::APZDisplayPortExpiryTime(), nsITimer::TYPE_ONE_SHOT); + } +} + +void ScrollFrameHelper::TriggerDisplayPortExpiration() +{ + if (IsAlwaysActive()) { + return; + } + + if (!gfxPrefs::APZDisplayPortExpiryTime()) { + // a zero time disables the expiry + return; + } + + if (!mDisplayPortExpiryTimer) { + mDisplayPortExpiryTimer = do_CreateInstance("@mozilla.org/timer;1"); + } + ResetDisplayPortExpiryTimer(); } void ScrollFrameHelper::ScrollVisual() diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index fa7903cf2c7..98b8fb3f740 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -370,6 +370,9 @@ public: void NotifyImageVisibilityUpdate(); bool GetDisplayPortAtLastImageVisibilityUpdate(nsRect* aDisplayPort); + void TriggerDisplayPortExpiration(); + void ResetDisplayPortExpiryTimer(); + void ScheduleSyntheticMouseMove(); static void ScrollActivityCallback(nsITimer *aTimer, void* anInstance); @@ -468,6 +471,9 @@ public: FrameMetrics::ViewID mScrollParentID; + // Timer to remove the displayport some time after scrolling has stopped + nsCOMPtr mDisplayPortExpiryTimer; + bool mNeverHasVerticalScrollbar:1; bool mNeverHasHorizontalScrollbar:1; bool mHasVerticalScrollbar:1; @@ -864,6 +870,9 @@ public: virtual bool GetDisplayPortAtLastImageVisibilityUpdate(nsRect* aDisplayPort) override { return mHelper.GetDisplayPortAtLastImageVisibilityUpdate(aDisplayPort); } + void TriggerDisplayPortExpiration() override { + mHelper.TriggerDisplayPortExpiration(); + } // nsIStatefulFrame NS_IMETHOD SaveState(nsPresState** aState) override { @@ -1337,6 +1346,9 @@ public: virtual bool GetDisplayPortAtLastImageVisibilityUpdate(nsRect* aDisplayPort) override { return mHelper.GetDisplayPortAtLastImageVisibilityUpdate(aDisplayPort); } + void TriggerDisplayPortExpiration() override { + mHelper.TriggerDisplayPortExpiration(); + } #ifdef DEBUG_FRAME_DUMP virtual nsresult GetFrameName(nsAString& aResult) const override; diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 3e285a892c2..e97f953c085 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -453,6 +453,13 @@ public: * false otherwise, and doesn't touch aDisplayPort. */ virtual bool GetDisplayPortAtLastImageVisibilityUpdate(nsRect* aDisplayPort) = 0; + + /** + * This is called when a descendant scrollframe's has its displayport expired. + * This function will check to see if this scrollframe may safely expire its + * own displayport and schedule a timer to do that if it is safe. + */ + virtual void TriggerDisplayPortExpiration() = 0; }; #endif diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index d513194bff5..af4a08fe0ea 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -567,6 +567,7 @@ pref("apz.content_response_timeout", 300); pref("apz.drag.enabled", false); pref("apz.danger_zone_x", 50); pref("apz.danger_zone_y", 100); +pref("apz.displayport_expiry_ms", 15000); pref("apz.enlarge_displayport_when_clipped", false); pref("apz.fling_accel_base_mult", "1.0"); pref("apz.fling_accel_interval_ms", 500); From 6d0c652e726f50033764156294b2ae9fdee84dac Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 19:13:35 -0500 Subject: [PATCH 119/160] Bug 990916 - On displayport expiry, trigger another round of expiry up the ancestor chain. r=tnikkel --- layout/base/nsLayoutUtils.cpp | 31 +++++++++++++++++++++++++++++ layout/base/nsLayoutUtils.h | 6 ++++++ layout/generic/nsGfxScrollFrame.cpp | 6 +++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index bcc8909b8d5..44572c52a07 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3177,6 +3177,37 @@ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(nsIFrame* aFra } } +void +nsLayoutUtils::ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame) +{ + nsIFrame* frame = aFrame; + while (frame) { + frame = nsLayoutUtils::GetCrossDocParentFrame(frame); + if (!frame) { + break; + } + nsIScrollableFrame* scrollAncestor = GetAsyncScrollableAncestorFrame(frame); + if (!scrollAncestor) { + break; + } + frame = do_QueryFrame(scrollAncestor); + MOZ_ASSERT(frame); + MOZ_ASSERT(scrollAncestor->WantAsyncScroll() || + frame->PresContext()->PresShell()->GetRootScrollFrame() == frame); + if (nsLayoutUtils::AsyncPanZoomEnabled(frame) && + nsLayoutUtils::HasDisplayPort(frame->GetContent())) { + scrollAncestor->TriggerDisplayPortExpiration(); + // Stop after the first trigger. If it failed, there's no point in + // continuing because all the rest of the frames we encounter are going + // to be ancestors of |scrollAncestor| which will keep its displayport. + // If the trigger succeeded, we stop because when the trigger executes + // it will call this function again to trigger the next ancestor up the + // chain. + break; + } + } +} + nsresult nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame, const nsRegion& aDirtyRegion, nscolor aBackstop, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index dc5d95c7088..152c2ecfa82 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2691,6 +2691,12 @@ public: */ static void SetZeroMarginDisplayPortOnAsyncScrollableAncestors(nsIFrame* aFrame, RepaintMode aRepaintMode); + /** + * Finds the closest ancestor async scrollable frame from aFrame that has a + * displayport and attempts to trigger the displayport expiry on that + * ancestor. + */ + static void ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame); static bool IsOutlineStyleAutoEnabled(); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 23e5f915775..c4bbe107032 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2349,7 +2349,10 @@ RemoveDisplayPortCallback(nsITimer* aTimer, void* aClosure) if (helper->IsAlwaysActive() || helper->mIsScrollParent) { // If this is a scroll parent for some other scrollable frame, don't - // expire the displayport because it would break scroll handoff. + // expire the displayport because it would break scroll handoff. Once the + // descendant scrollframes have their displayports expired, they will + // trigger the displayport expiration on this scrollframe as well, and + // mIsScrollParent will presumably be false when that kicks in. return; } @@ -2366,6 +2369,7 @@ RemoveDisplayPortCallback(nsITimer* aTimer, void* aClosure) // different position that's ok; this scrollframe hasn't been scrolled // recently and so the reset should be correct. nsLayoutUtils::RemoveDisplayPort(helper->mOuter->GetContent()); + nsLayoutUtils::ExpireDisplayPortOnAsyncScrollableAncestor(helper->mOuter); helper->mOuter->SchedulePaint(); } From c66c4c8919718eaedf817f3fde39242ed7c66bbb Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 3 Feb 2016 19:13:35 -0500 Subject: [PATCH 120/160] Bug 990916 - Update test_layerization to also test displayport expiry and de-layerization. r=tnikkel,botond --- .../test/mochitest/helper_subframe_style.css | 2 +- .../apz/test/mochitest/test_layerization.html | 80 ++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/gfx/layers/apz/test/mochitest/helper_subframe_style.css b/gfx/layers/apz/test/mochitest/helper_subframe_style.css index a911bea7115..5af9640802f 100644 --- a/gfx/layers/apz/test/mochitest/helper_subframe_style.css +++ b/gfx/layers/apz/test/mochitest/helper_subframe_style.css @@ -3,7 +3,7 @@ body { } .inner-frame { - margin-top: 25%; + margin-top: 50px; /* this should be at least 30px */ height: 200%; width: 75%; overflow: scroll; diff --git a/gfx/layers/apz/test/mochitest/test_layerization.html b/gfx/layers/apz/test/mochitest/test_layerization.html index 99e25edceb9..b25c6054b04 100644 --- a/gfx/layers/apz/test/mochitest/test_layerization.html +++ b/gfx/layers/apz/test/mochitest/test_layerization.html @@ -72,6 +72,8 @@ function scrollWheelOver(element) { var gTestContinuation = null; var utils; +const DISPLAYPORT_EXPIRY = 100; + // Return whether the element with id |elementId| has been layerized. // Assumes |elementId| will be present in the content description for the // element, and not in the content descriptions of other elements. @@ -91,6 +93,14 @@ function isLayerized(elementId) { return false; } +// Helper function to pass to waitForAllPaints rather than passing driveTest +// directly. If there are no paints pending waitForAllPaints will invoke the +// callback synchronously, and if we did waitForAllPaints(driveTest) that might +// cause reentrancy into driveTest which is bad. +function callDriveTestAsync() { + setTimeout(driveTest, 0); +} + function* runTest() { utils = SpecialPowers.getDOMWindowUtils(window); @@ -126,6 +136,72 @@ function* runTest() { yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4')); ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized"); ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized"); + + // Now we enable displayport expiry, and verify that things are still + // layerized as they were before. + yield SpecialPowers.pushPrefEnv({"set": [["apz.displayport_expiry_ms", DISPLAYPORT_EXPIRY]]}, driveTest); + ok(isLayerized('outer1'), "outer1 is still layerized after enabling expiry"); + ok(!isLayerized('inner1'), "inner1 is still not layerized after enabling expiry"); + ok(isLayerized('outer2'), "outer2 is still layerized after enabling expiry"); + ok(isLayerized('inner2'), "inner2 is still layerized after enabling expiry"); + ok(isLayerized('outer3'), "outer3 is still layerized after enabling expiry"); + ok(!isLayerized('inner3'), "inner3 is still not layerized after enabling expiry"); + ok(isLayerized('outer4'), "outer4 is still layerized after enabling expiry"); + ok(isLayerized('inner4'), "inner4 is still layerized after enabling expiry"); + + // Now we trigger a scroll on some of the things still layerized, so that + // the displayport expiry gets triggered. + + // Expire displayport with scrolling on outer1 + yield scrollWheelOver(document.getElementById('outer1')); + yield waitForAllPaints(function() { + flushApzRepaints(driveTest); + }); + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(!isLayerized('outer1'), "outer1 is no longer layerized after displayport expiry"); + ok(!isLayerized('inner1'), "inner1 is still not layerized after displayport expiry"); + + // Expire displayport with scrolling on inner2 + yield scrollWheelOver(document.getElementById('inner2')); + yield waitForAllPaints(function() { + flushApzRepaints(driveTest); + }); + // Once the expiry elapses, it will trigger expiry on outer2, so we check + // both, one at a time. + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(!isLayerized('inner2'), "inner2 is no longer layerized after displayport expiry"); + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(!isLayerized('outer2'), "outer2 got de-layerized with inner2"); + + // Scroll on inner3. inner3 isn't layerized, and this will cause it to + // get layerized, but it will also trigger displayport expiration for inner3 + // which will eventually trigger displayport expiration on outer3. + yield scrollWheelOver(document.getElementById('outer3').contentDocument.getElementById('inner3')); + yield waitForAllPaints(function() { + flushApzRepaints(driveTest); + }); + ok(isLayerized('inner3'), "inner3 becomes layerized after scroll"); + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(!isLayerized('inner3'), "inner3 becomes unlayerized after expiry"); + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(!isLayerized('outer3'), "outer3 is no longer layerized after inner3 triggered expiry"); + + // Scroll outer4 and wait for the expiry. It should NOT get expired because + // inner4 is still layerized + yield scrollWheelOver(document.getElementById('outer4').contentDocument.documentElement); + yield waitForAllPaints(function() { + flushApzRepaints(driveTest); + }); + // Wait for the expiry to elapse + yield setTimeout(driveTest, DISPLAYPORT_EXPIRY); + yield waitForAllPaints(callDriveTestAsync); + ok(isLayerized('inner4'), "inner4 is still layerized because it never expired"); + ok(isLayerized('outer4'), "outer4 is still layerized because inner4 is still layerized"); } function driveTest() { @@ -153,7 +229,8 @@ function startTest() { } SimpleTest.waitForExplicitFinish(); -SimpleTest.testInChaosMode(); +SimpleTest.requestFlakyTimeout("we are testing code that measures an actual timeout"); +SimpleTest.expectAssertions(0, 8); // we get a bunch of "ASSERTION: Bounds computation mismatch" sometimes (bug 1232856) // Disable smooth scrolling, because it results in long-running scroll // animations that can result in a 'scroll' event triggered by an earlier @@ -161,6 +238,7 @@ SimpleTest.testInChaosMode(); // Also enable APZ test logging, since we use that data to determine whether // a scroll frame was layerized. SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false], + ["apz.displayport_expiry_ms", 0], ["apz.test.logging_enabled", true]]}, function() { SimpleTest.waitForFocus(startTest, window); From bad967fba473ee7ac8d9880a4906322e35e1d2b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Feb 2016 17:30:54 +1100 Subject: [PATCH 121/160] Bug 1245393 - Measure s{,Default}RootBranch in the Preferences memory reporter. r=froydnj. --- modules/libpref/Preferences.cpp | 8 ++++++-- modules/libpref/nsPrefBranch.cpp | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 80948250268..5e613f9b43f 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -245,8 +245,12 @@ Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeO n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf); } } - // We don't measure sRootBranch and sDefaultRootBranch here because - // DMD indicates they are not significant. + if (sRootBranch) { + n += reinterpret_cast(sRootBranch)->SizeOfIncludingThis(aMallocSizeOf); + } + if (sDefaultRootBranch) { + n += reinterpret_cast(sDefaultRootBranch)->SizeOfIncludingThis(aMallocSizeOf); + } n += pref_SizeOfPrivateData(aMallocSizeOf); return n; } diff --git a/modules/libpref/nsPrefBranch.cpp b/modules/libpref/nsPrefBranch.cpp index 0f5046dfd72..6c341722e09 100644 --- a/modules/libpref/nsPrefBranch.cpp +++ b/modules/libpref/nsPrefBranch.cpp @@ -687,6 +687,15 @@ void nsPrefBranch::NotifyObserver(const char *newpref, void *data) NS_ConvertASCIItoUTF16(suffix).get()); } +size_t +nsPrefBranch::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) +{ + size_t n = aMallocSizeOf(this); + n += mPrefRoot.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf); + return n; +} + void nsPrefBranch::freeObserverList(void) { // We need to prevent anyone from modifying mObservers while we're iterating From 87feabd84d61c32602245d0df8fb7374eb477879 Mon Sep 17 00:00:00 2001 From: Gerald Squelart Date: Thu, 4 Feb 2016 11:29:00 +1100 Subject: [PATCH 122/160] Bug 1237848 - Check lookahead ctx - r=rillian Copied from https://chromium-review.googlesource.com/324510 --- media/libvpx/vp8/encoder/lookahead.c | 1 + media/libvpx/vp9/encoder/vp9_lookahead.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/media/libvpx/vp8/encoder/lookahead.c b/media/libvpx/vp8/encoder/lookahead.c index ce2ce08c170..66233857433 100644 --- a/media/libvpx/vp8/encoder/lookahead.c +++ b/media/libvpx/vp8/encoder/lookahead.c @@ -181,6 +181,7 @@ vp8_lookahead_pop(struct lookahead_ctx *ctx, { struct lookahead_entry* buf = NULL; + assert(ctx != NULL); if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) { buf = pop(ctx, &ctx->read_idx); diff --git a/media/libvpx/vp9/encoder/vp9_lookahead.c b/media/libvpx/vp9/encoder/vp9_lookahead.c index b8e2ca88c8c..fd32a16b49e 100644 --- a/media/libvpx/vp9/encoder/vp9_lookahead.c +++ b/media/libvpx/vp9/encoder/vp9_lookahead.c @@ -207,7 +207,7 @@ struct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx, int drain) { struct lookahead_entry *buf = NULL; - if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) { + if (ctx && ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) { buf = pop(ctx, &ctx->read_idx); ctx->sz--; } From 0664e26fa15efef9e022d1ce119b53f7cde8a0d2 Mon Sep 17 00:00:00 2001 From: Gerald Squelart Date: Thu, 4 Feb 2016 11:29:02 +1100 Subject: [PATCH 123/160] Bug 1237848 - Updated update.py patch - r=rillian --- .../libvpx/1237848-check-lookahead-ctx.patch | 50 +++++++++++++++++++ media/libvpx/update.py | 2 + 2 files changed, 52 insertions(+) create mode 100644 media/libvpx/1237848-check-lookahead-ctx.patch diff --git a/media/libvpx/1237848-check-lookahead-ctx.patch b/media/libvpx/1237848-check-lookahead-ctx.patch new file mode 100644 index 00000000000..a2ebe5cd755 --- /dev/null +++ b/media/libvpx/1237848-check-lookahead-ctx.patch @@ -0,0 +1,50 @@ +# HG changeset patch +# User Gerald Squelart +# Parent 5f9ba76eb3b1fd9377bbdb4cc2f98a7e75eabdfb +Bug 1237848 - Check lookahead ctx - r=rillian + +Copied from https://chromium-review.googlesource.com/324510 + +diff --git a/media/libvpx/vp8/encoder/lookahead.c b/media/libvpx/vp8/encoder/lookahead.c +--- a/media/libvpx/vp8/encoder/lookahead.c ++++ b/media/libvpx/vp8/encoder/lookahead.c +@@ -176,16 +176,17 @@ vp8_lookahead_push(struct lookahead_ctx + + + struct lookahead_entry* + vp8_lookahead_pop(struct lookahead_ctx *ctx, + int drain) + { + struct lookahead_entry* buf = NULL; + ++ assert(ctx != NULL); + if(ctx->sz && (drain || ctx->sz == ctx->max_sz - 1)) + { + buf = pop(ctx, &ctx->read_idx); + ctx->sz--; + } + return buf; + } + +diff --git a/media/libvpx/vp9/encoder/vp9_lookahead.c b/media/libvpx/vp9/encoder/vp9_lookahead.c +--- a/media/libvpx/vp9/encoder/vp9_lookahead.c ++++ b/media/libvpx/vp9/encoder/vp9_lookahead.c +@@ -202,17 +202,17 @@ int vp9_lookahead_push(struct lookahead_ + return 0; + } + + + struct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx, + int drain) { + struct lookahead_entry *buf = NULL; + +- if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) { ++ if (ctx && ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) { + buf = pop(ctx, &ctx->read_idx); + ctx->sz--; + } + return buf; + } + + + struct lookahead_entry *vp9_lookahead_peek(struct lookahead_ctx *ctx, diff --git a/media/libvpx/update.py b/media/libvpx/update.py index 5acf21eb30f..3a36c271a05 100755 --- a/media/libvpx/update.py +++ b/media/libvpx/update.py @@ -602,6 +602,8 @@ def apply_patches(): os.system("patch -p3 < clang-cl.patch") # Bug 1224371 - Cast uint8_t to uint32_t before shift os.system("patch -p3 < cast-char-to-uint-before-shift.patch") + # Bug 1237848 - Check lookahead ctx + os.system("patch -p3 < 1237848-check-lookahead-ctx.patch") def update_readme(commit): with open('README_MOZILLA') as f: From 1e0476fde71676d18c972e9319aa6d478c478955 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Fri, 22 Jan 2016 18:00:54 -0800 Subject: [PATCH 124/160] Bug 1243907 - Don't query _BITS enums on Core profiles. - r=jrmuizel --- dom/canvas/WebGLContext.h | 3 +- dom/canvas/WebGLContextGL.cpp | 4 + dom/canvas/WebGLContextState.cpp | 138 +++++++++++++++++++++++++------ 3 files changed, 121 insertions(+), 24 deletions(-) diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index a7eeba956f2..dafbe702306 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -827,7 +827,8 @@ protected: public: void Disable(GLenum cap); void Enable(GLenum cap); - bool GetStencilBits(GLint* out_stencilBits); + bool GetStencilBits(GLint* const out_stencilBits); + bool GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val); virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv); void GetParameter(JSContext* cx, GLenum pname, diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index ef3716142ae..34543116fea 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -994,6 +994,10 @@ WebGLContext::Hint(GLenum target, GLenum mode) switch (target) { case LOCAL_GL_GENERATE_MIPMAP_HINT: + // Deprecated and removed in desktop GL Core profiles. + if (gl->IsCoreProfile()) + return; + isValid = true; break; diff --git a/dom/canvas/WebGLContextState.cpp b/dom/canvas/WebGLContextState.cpp index 8f3563a0dcf..ea818e4004f 100644 --- a/dom/canvas/WebGLContextState.cpp +++ b/dom/canvas/WebGLContextState.cpp @@ -73,7 +73,7 @@ StringValue(JSContext* cx, const nsAString& str, ErrorResult& rv) } bool -WebGLContext::GetStencilBits(GLint* out_stencilBits) +WebGLContext::GetStencilBits(GLint* const out_stencilBits) { *out_stencilBits = 0; if (mBoundDrawFramebuffer) { @@ -97,9 +97,107 @@ WebGLContext::GetStencilBits(GLint* out_stencilBits) return true; } +bool +WebGLContext::GetChannelBits(const char* funcName, GLenum pname, GLint* const out_val) +{ + if (mBoundDrawFramebuffer) { + if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName)) + return false; + } + + if (!mBoundDrawFramebuffer) { + switch (pname) { + case LOCAL_GL_RED_BITS: + case LOCAL_GL_GREEN_BITS: + case LOCAL_GL_BLUE_BITS: + *out_val = 8; + break; + + case LOCAL_GL_ALPHA_BITS: + *out_val = (mOptions.alpha ? 8 : 0); + break; + + case LOCAL_GL_DEPTH_BITS: + if (mOptions.depth) { + const auto& glFormats = gl->GetGLFormats(); + + GLenum depthFormat = glFormats.depth; + if (mOptions.stencil && glFormats.depthStencil) { + depthFormat = glFormats.depthStencil; + } + + if (depthFormat == LOCAL_GL_DEPTH_COMPONENT16) { + *out_val = 16; + } else { + *out_val = 24; + } + } else { + *out_val = 0; + } + break; + + case LOCAL_GL_STENCIL_BITS: + *out_val = (mOptions.stencil ? 8 : 0); + break; + + default: + MOZ_CRASH("bad pname"); + } + return true; + } + + if (!gl->IsCoreProfile()) { + gl->fGetIntegerv(pname, out_val); + return true; + } + + GLenum fbAttachment = 0; + GLenum fbPName = 0; + switch (pname) { + case LOCAL_GL_RED_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE; + break; + + case LOCAL_GL_GREEN_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE; + break; + + case LOCAL_GL_BLUE_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE; + break; + + case LOCAL_GL_ALPHA_BITS: + fbAttachment = LOCAL_GL_COLOR_ATTACHMENT0; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE; + break; + + case LOCAL_GL_DEPTH_BITS: + fbAttachment = LOCAL_GL_DEPTH_ATTACHMENT; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE; + break; + + case LOCAL_GL_STENCIL_BITS: + fbAttachment = LOCAL_GL_STENCIL_ATTACHMENT; + fbPName = LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE; + break; + + default: + MOZ_CRASH("bad pname"); + } + + gl->fGetFramebufferAttachmentParameteriv(LOCAL_GL_DRAW_FRAMEBUFFER, fbAttachment, + fbPName, out_val); + return true; +} + JS::Value WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) { + const char funcName[] = "getParameter"; + if (IsContextLost()) return JS::NullValue(); @@ -356,11 +454,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) return JS::Int32Value(refValue & stencilMask); } - case LOCAL_GL_STENCIL_BITS: { - GLint stencilBits = 0; - GetStencilBits(&stencilBits); - return JS::Int32Value(stencilBits); - } + case LOCAL_GL_STENCIL_CLEAR_VALUE: case LOCAL_GL_UNPACK_ALIGNMENT: case LOCAL_GL_PACK_ALIGNMENT: @@ -370,28 +464,26 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) case LOCAL_GL_MAX_VERTEX_ATTRIBS: case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: - case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: - case LOCAL_GL_RED_BITS: - case LOCAL_GL_GREEN_BITS: - case LOCAL_GL_BLUE_BITS: { + case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS: { GLint i = 0; gl->fGetIntegerv(pname, &i); return JS::Int32Value(i); } - case LOCAL_GL_DEPTH_BITS: { - GLint i = 0; - if (!mNeedsFakeNoDepth) { - gl->fGetIntegerv(pname, &i); - } - return JS::Int32Value(i); - } - case LOCAL_GL_ALPHA_BITS: { - GLint i = 0; - if (!mNeedsFakeNoAlpha) { - gl->fGetIntegerv(pname, &i); - } - return JS::Int32Value(i); + + case LOCAL_GL_RED_BITS: + case LOCAL_GL_GREEN_BITS: + case LOCAL_GL_BLUE_BITS: + case LOCAL_GL_ALPHA_BITS: + case LOCAL_GL_DEPTH_BITS: + case LOCAL_GL_STENCIL_BITS: { + // Deprecated and removed in GL Core profiles, so special handling required. + GLint val; + if (!GetChannelBits(funcName, pname, &val)) + return JS::NullValue(); + + return JS::Int32Value(val); } + case LOCAL_GL_MAX_TEXTURE_SIZE: return JS::Int32Value(mImplMaxTextureSize); From 042a3d870b19ed6f8f60eb111a437d0dddefeeb2 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Tue, 26 Jan 2016 12:42:39 -0800 Subject: [PATCH 125/160] Bug 1243908 - Use DrawBuffers through GLScreenBuffer when operating on fb0. - r=jrmuizel --- dom/canvas/WebGLContext.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 2d1989def2d..5bb46165e19 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -1304,8 +1304,7 @@ WebGLContext::ClearScreen() const bool changeDrawBuffers = (mDefaultFB_DrawBuffer0 != LOCAL_GL_BACK); if (changeDrawBuffers) { - const GLenum back = LOCAL_GL_BACK; - gl->fDrawBuffers(1, &back); + gl->Screen()->SetDrawBuffer(LOCAL_GL_BACK); } GLbitfield bufferBits = LOCAL_GL_COLOR_BUFFER_BIT; @@ -1317,7 +1316,7 @@ WebGLContext::ClearScreen() ForceClearFramebufferWithDefaultValues(bufferBits, mNeedsFakeNoAlpha); if (changeDrawBuffers) { - gl->fDrawBuffers(1, &mDefaultFB_DrawBuffer0); + gl->Screen()->SetDrawBuffer(mDefaultFB_DrawBuffer0); } } From 808cf51937a42fb2f68e095977311a3f0d5ea6c1 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Thu, 28 Jan 2016 14:27:57 -0800 Subject: [PATCH 126/160] Bug 1233046 - Fix OES_texture_float on OSX. - r=jrmuizel --- dom/canvas/WebGLExtensionTextureFloat.cpp | 27 ++++++++++++------- dom/canvas/WebGLExtensionTextureHalfFloat.cpp | 27 ++++++++++++------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/dom/canvas/WebGLExtensionTextureFloat.cpp b/dom/canvas/WebGLExtensionTextureFloat.cpp index a7a58939ad1..4568e994ee9 100644 --- a/dom/canvas/WebGLExtensionTextureFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureFloat.cpp @@ -32,15 +32,17 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) fua->AllowUnsizedTexFormat(pi, usage); }; - const bool needSizedInternal = !gl->IsGLES(); - MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle)); + const bool needsSwizzle = gl->IsCoreProfile(); + MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle)); + + const bool needsSizedFormat = !gl->IsGLES(); //////////////// pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGBA32F; } fnAdd(webgl::EffectiveFormat::RGBA32F); @@ -50,7 +52,7 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGB32F; } fnAdd(webgl::EffectiveFormat::RGB32F); @@ -60,9 +62,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance32F); @@ -71,9 +75,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R32F, LOCAL_GL_RED, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_ALPHA32F_ARB; } fnAdd(webgl::EffectiveFormat::Alpha32F); @@ -82,9 +88,11 @@ WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl) pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT}; dui = {pi.format, pi.format, pi.type}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_RG32F, LOCAL_GL_RG, LOCAL_GL_FLOAT}; swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F); } @@ -101,10 +109,9 @@ WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl) if (!gl->IsSupported(gl::GLFeature::texture_float)) return false; - const bool needSizedInternal = !gl->IsGLES(); + const bool needsSwizzle = gl->IsCoreProfile(); const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle); - - if (needSizedInternal && !hasSwizzle) + if (needsSwizzle && !hasSwizzle) return false; return true; diff --git a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp index a5770999d67..e59f9b232ee 100644 --- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp @@ -30,8 +30,10 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web fua->AllowUnsizedTexFormat(pi, usage); }; - const bool needSizedInternal = !gl->IsGLES(); - MOZ_ASSERT_IF(needSizedInternal, gl->IsSupported(gl::GLFeature::texture_swizzle)); + const bool needsSwizzle = gl->IsCoreProfile(); + MOZ_ASSERT_IF(needsSwizzle, gl->IsSupported(gl::GLFeature::texture_swizzle)); + + const bool needsSizedFormat = !gl->IsGLES(); GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT; if (!gl->IsSupported(gl::GLFeature::texture_half_float)) { @@ -44,7 +46,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGBA16F; } fnAdd(webgl::EffectiveFormat::RGBA16F); @@ -54,7 +56,7 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSizedFormat) { dui.internalFormat = LOCAL_GL_RGB16F; } fnAdd(webgl::EffectiveFormat::RGB16F); @@ -64,9 +66,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance16F); @@ -75,9 +79,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_R16F, LOCAL_GL_RED, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_ALPHA16F_ARB; } fnAdd(webgl::EffectiveFormat::Alpha16F); @@ -86,9 +92,11 @@ WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* web pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES}; dui = {pi.format, pi.format, driverUnpackType}; swizzle = nullptr; - if (needSizedInternal) { + if (needsSwizzle) { dui = {LOCAL_GL_RG16F, LOCAL_GL_RG, driverUnpackType}; swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA; + } else if (needsSizedFormat) { + dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB; } fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F); } @@ -108,10 +116,9 @@ WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl) return false; } - const bool needSizedInternal = !gl->IsGLES(); + const bool needsSwizzle = gl->IsCoreProfile(); const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle); - - if (needSizedInternal && !hasSwizzle) + if (needsSwizzle && !hasSwizzle) return false; return true; From a27233211b8edef22688e791225ddd5cff881298 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Tue, 26 Jan 2016 16:51:42 -0800 Subject: [PATCH 127/160] Bug 1233046 - Add requestFlakeyTimeout to SimpleTest shim. - r=jrmuizel --- dom/canvas/test/webgl-mochitest/mochi-to-testcase.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py index bac482c3d73..919ba232804 100644 --- a/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py +++ b/dom/canvas/test/webgl-mochitest/mochi-to-testcase.py @@ -28,7 +28,8 @@ def ReadLocalFile(include): return data -kSimpleTestReplacement = '''\n +kSimpleTestReplacement = ''' +
    -\n''' + +''' fin = open(mochiPath, 'rb') fout = open(testPath, 'wb') From aab7eb8ac81703cd843688be0d74ef585b4ead2f Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Thu, 28 Jan 2016 14:28:59 -0800 Subject: [PATCH 128/160] Bug 1233046 - Add ensure-extension tests. - r=jrmuizel --- dom/canvas/test/webgl-mochitest.ini | 41 ++++++++++ .../webgl-mochitest/ensure-exts/ensure-ext.js | 32 ++++++++ .../test_ANGLE_instanced_arrays.html | 17 +++++ .../ensure-exts/test_EXT_blend_minmax.html | 17 +++++ .../test_EXT_color_buffer_half_float.html | 17 +++++ .../test_EXT_disjoint_timer_query.html | 17 +++++ .../ensure-exts/test_EXT_frag_depth.html | 17 +++++ .../ensure-exts/test_EXT_sRGB.html | 17 +++++ .../test_EXT_shader_texture_lod.html | 17 +++++ .../test_EXT_texture_filter_anisotropic.html | 17 +++++ .../test_OES_standard_derivatives.html | 17 +++++ .../test_WEBGL_color_buffer_float.html | 17 +++++ .../test_WEBGL_compressed_texture_atc.html | 17 +++++ .../test_WEBGL_compressed_texture_es3.html | 17 +++++ .../test_WEBGL_compressed_texture_etc1.html | 17 +++++ .../test_WEBGL_compressed_texture_pvrtc.html | 17 +++++ .../test_WEBGL_compressed_texture_s3tc.html | 17 +++++ .../ensure-exts/test_WEBGL_depth_texture.html | 17 +++++ .../ensure-exts/test_WEBGL_draw_buffers.html | 17 +++++ .../ensure-exts/test_common.html | 75 +++++++++++++++++++ 20 files changed, 437 insertions(+) create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html create mode 100644 dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index d6cd17dd6b4..2fe2009587c 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -3,10 +3,51 @@ subsuite = webgl skip-if = ((os == 'linux') && (buildapp == 'b2g')) support-files = + webgl-mochitest/ensure-exts/ensure-ext.js webgl-mochitest/driver-info.js webgl-mochitest/es3-data.js webgl-mochitest/webgl-util.js +[webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html] +fail-if = (os == 'android') || (os == 'mac') +[webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_EXT_sRGB.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') +[webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html] +fail-if = (os == 'android') || (os == 'linux') +[webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html] +fail-if = (os == 'android') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html] +# Win7 is 6.1 +fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && os_version == '6.1') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html] +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +[webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html] +fail-if = (os == 'android') || (os == 'linux') +[webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html] +fail-if = (os == 'mac') +[webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html] +# Win7 is 6.1 +fail-if = (os == 'android') || (os == 'win' && os_version == '6.1') + +[webgl-mochitest/ensure-exts/test_common.html] + + [webgl-mochitest/test_backbuffer_channels.html] fail-if = (os == 'b2g') [webgl-mochitest/test_depth_readpixels.html] diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js new file mode 100644 index 00000000000..798067d5e42 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/ensure-ext.js @@ -0,0 +1,32 @@ +'use strict'; + +function EnsureExt(name, shouldBe = true) { + var c = document.createElement('canvas'); + var gl = c.getContext('experimental-webgl'); + + if (shouldBe) { + ok(gl.getExtension(name), 'Should have extension ' + name + '.'); + } else { + ok(!gl.getExtension(name), 'Should not have extension ' + name + '.'); + } +} + +function EnsureDraftExt(name, shouldBe = true) { + SimpleTest.waitForExplicitFinish(); + + var fnEnsure = function() { + EnsureExt(name, shouldBe); + SimpleTest.finish(); + }; + + if ('SpecialPowers' in window) { + var prefStateList = [ + ['webgl.enable-draft-extensions', true], + ]; + var prefEnv = {'set': prefStateList}; + SpecialPowers.pushPrefEnv(prefEnv, fnEnsure); + } else { + console.log('Couldn\'t use SpecialPowers to enable draft extensions.'); + fnEnsure(); + } +} diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html new file mode 100644 index 00000000000..04b24d90c10 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html new file mode 100644 index 00000000000..903269e6b66 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html new file mode 100644 index 00000000000..3ac21299c68 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html new file mode 100644 index 00000000000..e0b90adbbb5 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html new file mode 100644 index 00000000000..3c7f3867917 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_frag_depth.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html new file mode 100644 index 00000000000..da5aa0a3fbf --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_sRGB.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html new file mode 100644 index 00000000000..e64ff94848c --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html new file mode 100644 index 00000000000..877c4440bf3 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html new file mode 100644 index 00000000000..3e7b7a39622 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_OES_standard_derivatives.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html new file mode 100644 index 00000000000..aeb8f271ea0 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_color_buffer_float.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html new file mode 100644 index 00000000000..6d68f0b4e2b --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_atc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html new file mode 100644 index 00000000000..21c824ad854 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_es3.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html new file mode 100644 index 00000000000..327625c0184 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html new file mode 100644 index 00000000000..c9548139842 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html new file mode 100644 index 00000000000..6ad80011064 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html new file mode 100644 index 00000000000..957171c160e --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html new file mode 100644 index 00000000000..18774d0d68a --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html new file mode 100644 index 00000000000..3b5907a8a88 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/ensure-exts/test_common.html @@ -0,0 +1,75 @@ + + + + + + + + + + + From c9a550e3154bbfd0a7f88fd4d8f25112c8669272 Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Wed, 3 Feb 2016 16:27:36 -0800 Subject: [PATCH 129/160] Bug 1233046 - Mark non-try platforms. --- dom/canvas/moz.build | 2 +- dom/canvas/test/webgl-mochitest.ini | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index ffa942025ce..a157e9d91c8 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -7,7 +7,7 @@ TEST_DIRS += ['compiledtest'] # Number changes to this file to avoid bug 1081323 (clobber after changing a manifest): -# 3 +# 5 MOCHITEST_MANIFESTS += [ 'test/crossorigin/mochitest.ini', diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index 2fe2009587c..138ee94d696 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -9,7 +9,7 @@ support-files = webgl-mochitest/webgl-util.js [webgl-mochitest/ensure-exts/test_ANGLE_instanced_arrays.html] -fail-if = (os == 'android') || (os == 'mac') +fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') [webgl-mochitest/ensure-exts/test_EXT_blend_minmax.html] fail-if = (os == 'android') [webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html] @@ -19,7 +19,7 @@ fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') [webgl-mochitest/ensure-exts/test_EXT_frag_depth.html] fail-if = (os == 'android') [webgl-mochitest/ensure-exts/test_EXT_sRGB.html] -fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') +fail-if = (os == 'android') || (os == 'linux') || (os == 'mac' && os_version == '10.6') || (os == 'win') [webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html] fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') [webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html] @@ -34,16 +34,16 @@ fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') [webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_etc1.html] # Win7 is 6.1 -fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && os_version == '6.1') +fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1')) [webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_pvrtc.html] fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win') [webgl-mochitest/ensure-exts/test_WEBGL_compressed_texture_s3tc.html] fail-if = (os == 'android') || (os == 'linux') [webgl-mochitest/ensure-exts/test_WEBGL_depth_texture.html] -fail-if = (os == 'mac') +fail-if = (os == 'mac' && os_version == '10.6') [webgl-mochitest/ensure-exts/test_WEBGL_draw_buffers.html] # Win7 is 6.1 -fail-if = (os == 'android') || (os == 'win' && os_version == '6.1') +fail-if = (os == 'android') || (os == 'win' && (os_version == '5.1' || os_version == '6.1')) [webgl-mochitest/ensure-exts/test_common.html] From bb23f2de9e1f49f1b3d95450e22c150080f1617c Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 3 Nov 2015 11:55:02 -0600 Subject: [PATCH 130/160] Bug 1221144 - Part 6: Introduce StaticModuleScope. Pretty silly so far. Bindings are still stored in the script. r=shu. --- js/src/builtin/ModuleObject.cpp | 14 +++-- js/src/builtin/ModuleObject.h | 6 +- js/src/frontend/BytecodeCompiler.cpp | 6 +- js/src/frontend/BytecodeEmitter.cpp | 7 ++- js/src/frontend/SharedContext.h | 2 +- js/src/jsscript.cpp | 2 +- js/src/vm/ScopeObject-inl.h | 24 +++----- js/src/vm/ScopeObject.cpp | 51 ++++++++++++++++- js/src/vm/ScopeObject.h | 84 +++++++++++++++++++++------- js/src/vm/Stack.cpp | 2 +- 10 files changed, 143 insertions(+), 55 deletions(-) diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp index f0decbf4f6a..13d6c9f7d07 100644 --- a/js/src/builtin/ModuleObject.cpp +++ b/js/src/builtin/ModuleObject.cpp @@ -573,7 +573,7 @@ ModuleObject::isInstance(HandleValue value) } /* static */ ModuleObject* -ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope) +ModuleObject::create(ExclusiveContext* cx, Handle enclosingStaticScope) { RootedObject proto(cx, cx->global()->getModulePrototype()); RootedObject obj(cx, NewObjectWithGivenProto(cx, &class_, proto)); @@ -581,7 +581,11 @@ ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope) return nullptr; RootedModuleObject self(cx, &obj->as()); - self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(enclosingStaticScope)); + Rooted scope(cx, StaticModuleScope::create(cx, self, + enclosingStaticScope)); + if (!scope) + return nullptr; + self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(scope)); Zone* zone = cx->zone(); IndirectBindingMap* bindings = zone->new_(zone); @@ -729,10 +733,10 @@ ModuleObject::initialEnvironment() const return getReservedSlot(InitialEnvironmentSlot).toObject().as(); } -JSObject* -ModuleObject::enclosingStaticScope() const +StaticModuleScope* +ModuleObject::staticScope() const { - return getReservedSlot(StaticScopeSlot).toObjectOrNull(); + return &getReservedSlot(StaticScopeSlot).toObject().as(); } /* static */ void diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h index 1bf80aa9bad..80c3088cb4d 100644 --- a/js/src/builtin/ModuleObject.h +++ b/js/src/builtin/ModuleObject.h @@ -21,6 +21,8 @@ namespace js { class ModuleEnvironmentObject; class ModuleObject; +class StaticScope; +class StaticModuleScope; namespace frontend { class ParseNode; @@ -225,7 +227,7 @@ class ModuleObject : public NativeObject static bool isInstance(HandleValue value); - static ModuleObject* create(ExclusiveContext* cx, HandleObject enclosingStaticScope); + static ModuleObject* create(ExclusiveContext* cx, Handle enclosingStaticScope); void init(HandleScript script); void setInitialEnvironment(Handle initialEnvironment); void initImportExportData(HandleArrayObject requestedModules, @@ -235,7 +237,7 @@ class ModuleObject : public NativeObject HandleArrayObject starExportEntries); JSScript* script() const; - JSObject* enclosingStaticScope() const; + StaticModuleScope* staticScope() const; ModuleEnvironmentObject& initialEnvironment() const; ModuleEnvironmentObject* environment() const; ModuleNamespaceObject* namespace_(); diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 3ea9abe339f..aaacbce0e9c 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -562,7 +562,8 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller return script; } -ModuleObject* BytecodeCompiler::compileModule() +ModuleObject* +BytecodeCompiler::compileModule() { if (!createSourceAndParser()) return nullptr; @@ -571,7 +572,8 @@ ModuleObject* BytecodeCompiler::compileModule() if (!module) return nullptr; - if (!createScript(module)) + Rooted moduleScope(cx, module->staticScope()); + if (!createScript(moduleScope)) return nullptr; module->init(script); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 30660c59ce6..8ca9be7847d 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1468,7 +1468,7 @@ BytecodeEmitter::computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definitio // computeAliasedSlots. uint32_t slot = dn->pn_scopecoord.slot(); if (blockScopeOfDef(dn)->is() || - blockScopeOfDef(dn)->is()) + blockScopeOfDef(dn)->is()) { MOZ_ASSERT(IsArgOp(*op) || slot < bceOfDef->script->bindings.numBodyLevelLocals()); MOZ_ALWAYS_TRUE(bceOfDef->lookupAliasedName(bceOfDef->script, dn->name(), &slot)); @@ -1582,7 +1582,7 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn) } } } else if (ssi.type() == StaticScopeIter::Module) { - RootedScript moduleScript(cx, ssi.moduleScript()); + RootedScript moduleScript(cx, ssi.module().script()); uint32_t slot_; if (lookupAliasedName(moduleScript, name, &slot_, pn)) { slot = Some(slot_); @@ -1590,7 +1590,8 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn) } // Convert module import accesses to use JSOP_GETIMPORT. - RootedModuleEnvironmentObject env(cx, &ssi.module().initialEnvironment()); + RootedModuleEnvironmentObject env(cx, &ssi.module().moduleObject() + .initialEnvironment()); RootedPropertyName propName(cx, name); MOZ_ASSERT(env); if (env->hasImportBinding(propName)) { diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index a70fe79c80c..575cf7dd194 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -427,7 +427,7 @@ class ModuleBox : public ObjectBox, public SharedContext ObjectBox* toObjectBox() override { return this; } ModuleObject* module() const { return &object->as(); } - JSObject* staticScope() const override { return module(); } + JSObject* staticScope() const override { return module()->staticScope(); } void trace(JSTracer* trc) override; }; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index e404ea4dc69..81e51dbc8b1 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -4089,7 +4089,7 @@ JSScript::innermostStaticScopeInScript(jsbytecode* pc) if (JSObject* scope = getStaticBlockScope(pc)) return scope; if (module()) - return module(); + return module()->staticScope(); return functionNonDelazifying(); } diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 7db235859b4..87bfd1a16b5 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -90,8 +90,8 @@ StaticScopeIter::operator++(int) obj = obj->template as().enclosingScope(); } else if (obj->template is()) { obj = obj->template as().enclosingScope(); - } else if (obj->template is()) { - obj = obj->template as().enclosingStaticScope(); + } else if (obj->template is()) { + obj = obj->template as().enclosingScope(); } else if (onNamedLambda || !obj->template as().isNamedLambda()) { onNamedLambda = false; JSFunction& fun = obj->template as(); @@ -116,7 +116,7 @@ StaticScopeIter::hasSyntacticDynamicScopeObject() const return fun.functionBox()->needsCallObject(); return fun.needsCallObject(); } - if (obj->template is()) + if (obj->template is()) return true; if (obj->template is()) { return obj->template as().needsClone() || @@ -139,7 +139,7 @@ StaticScopeIter::scopeShape() const if (type() == Block) return block().lastProperty(); if (type() == Module) - return moduleScript()->callObjShape(); + return module().environmentShape(); return funScript()->callObjShape(); } @@ -151,14 +151,14 @@ StaticScopeIter::type() const return NamedLambda; if (obj->template is()) return Block; + if (obj->template is()) + return Module; if (obj->template is()) return With; if (obj->template is()) return Eval; if (obj->template is()) return NonSyntactic; - if (obj->template is()) - return Module; MOZ_ASSERT(obj->template is()); return Function; } @@ -222,19 +222,11 @@ StaticScopeIter::maybeFunctionBox() const } template -inline JSScript* -StaticScopeIter::moduleScript() const -{ - MOZ_ASSERT(type() == Module); - return obj->template as().script(); -} - -template -inline ModuleObject& +inline StaticModuleScope& StaticScopeIter::module() const { MOZ_ASSERT(type() == Module); - return obj->template as(); + return obj->template as(); } } /* namespace js */ diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 7405336b9a5..4919ec809ae 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -118,6 +118,41 @@ StaticBlockScope::addVar(ExclusiveContext* cx, Handle block, /* allowDictionary = */ false); } +StaticModuleScope* +StaticModuleScope::create(ExclusiveContext* cx, Handle moduleObject, + Handle enclosingScope) +{ + Rooted nullProto(cx, TaggedProto(nullptr)); + JSObject* obj = NewObjectWithGivenTaggedProto(cx, &ModuleEnvironmentObject::class_, nullProto, + TenuredObject, BaseShape::DELEGATE); + if (!obj) + return nullptr; + + StaticModuleScope* scope = &obj->as(); + scope->initEnclosingScope(enclosingScope); + scope->setReservedSlot(MODULE_OBJECT_SLOT, ObjectValue(*moduleObject)); + return scope; +} + +ModuleObject& +StaticModuleScope::moduleObject() +{ + return getReservedSlot(MODULE_OBJECT_SLOT).toObject().as(); +} + +JSScript* +StaticModuleScope::script() +{ + return moduleObject().script(); +} + +Shape* +StaticModuleScope::environmentShape() +{ + ModuleObject* module = &getReservedSlot(MODULE_OBJECT_SLOT).toObject().as(); + return module->script()->bindings.callObjShape(); +} + const Class StaticWithScope::class_ = { "WithTemplate", JSCLASS_HAS_RESERVED_SLOTS(StaticWithScope::RESERVED_SLOTS) | @@ -440,6 +475,9 @@ const Class CallObject::class_ = { /*****************************************************************************/ +static_assert(StaticModuleScope::RESERVED_SLOTS == ModuleEnvironmentObject::RESERVED_SLOTS, + "static module scopes and dynamic module environments share a Class"); + const Class ModuleEnvironmentObject::class_ = { "ModuleEnvironmentObject", JSCLASS_HAS_RESERVED_SLOTS(ModuleEnvironmentObject::RESERVED_SLOTS) | @@ -480,7 +518,8 @@ ModuleEnvironmentObject::create(ExclusiveContext* cx, HandleModuleObject module) RootedShape shape(cx, script->bindings.callObjShape()); MOZ_ASSERT(shape->getObjectClass() == &class_); - RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, TaggedProto(nullptr))); + Rooted proto(cx, module->staticScope()); + RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &class_, proto)); if (!group) return nullptr; @@ -525,6 +564,12 @@ ModuleEnvironmentObject::module() return getReservedSlot(MODULE_SLOT).toObject().as(); } +StaticModuleScope& +ModuleEnvironmentObject::staticScope() +{ + return getProto()->as(); +} + IndirectBindingMap& ModuleEnvironmentObject::importBindings() { @@ -1476,7 +1521,7 @@ ScopeIter::settle() if (!ssi_.done() && hasAnyScopeObject()) { switch (ssi_.type()) { case StaticScopeIter::Module: - MOZ_ASSERT(scope_->as().module() == ssi_.module()); + MOZ_ASSERT(scope_->as().staticScope() == ssi_.module()); break; case StaticScopeIter::Function: MOZ_ASSERT(scope_->as().callee().nonLazyScript() == ssi_.funScript()); @@ -3146,7 +3191,7 @@ js::GetModuleEnvironmentForScript(JSScript* script) if (ssi.done()) return nullptr; - return ssi.module().environment(); + return ssi.module().moduleObject().environment(); } bool diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index a8109db504a..9473d132043 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -53,7 +53,7 @@ typedef Handle HandleModuleObject; * JSFunction * Scope for function bodies. e.g., |function f() { var x; let y; }| * - * ModuleObject + * StaticModuleScope * Scope for moddules. * * StaticWithScope @@ -300,6 +300,23 @@ class StaticBlockScope : public NestedStaticScope bool constant, unsigned index, bool* redeclared); }; +// The top-level scope of a module. +// Shares ModuleEnvironmentObject::class_. +class StaticModuleScope : public StaticScope +{ + static const unsigned MODULE_OBJECT_SLOT = StaticScope::RESERVED_SLOTS; + + public: + static const unsigned RESERVED_SLOTS = MODULE_OBJECT_SLOT + 1; + + static StaticModuleScope* create(ExclusiveContext* cx, Handle moduleObject, + Handle enclosingScope); + + ModuleObject& moduleObject(); + JSScript* script(); + Shape* environmentShape(); +}; + // Represents the lexical scope of a 'with' statement. class StaticWithScope : public NestedStaticScope { @@ -472,11 +489,11 @@ class StaticScopeIter static bool IsStaticScope(JSObject* obj) { return obj->is() || + obj->is() || obj->is() || obj->is() || obj->is() || - obj->is() || - obj->is(); + obj->is(); } public: @@ -527,14 +544,13 @@ class StaticScopeIter Type type() const; StaticBlockScope& block() const; + StaticModuleScope& module() const; StaticWithScope& staticWith() const; StaticEvalScope& eval() const; StaticNonSyntacticScope& nonSyntactic() const; JSScript* funScript() const; JSFunction& fun() const; frontend::FunctionBox* maybeFunctionBox() const; - JSScript* moduleScript() const; - ModuleObject& module() const; }; @@ -604,11 +620,13 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc); * * JSObject Generic object * | | - * | StaticScope Created at compile time + * | StaticScope--+ Created at compile time + * | | | | | + * | | | | StaticNonSyntacticScope See "Non-syntactic scopes" * | | | | - * | | | StaticNonSyntacticScope See "Non-syntactic scopes" + * | | | StaticEvalScope Placeholder so eval scopes may be iterated through * | | | - * | | StaticEvalScope Placeholder so eval scopes may be iterated through + * | | StaticModuleScope Toplevel scope in a module * | | * | NestedStaticScope Enclosing scope is in the same JSScript * | | | @@ -750,23 +768,13 @@ class CallObject : public LexicalScopeBase static CallObject* createHollowForDebug(JSContext* cx, HandleFunction callee); /* True if this is for a strict mode eval frame. */ - bool isForEval() const { - if (is()) - return false; - MOZ_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull()); - MOZ_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(), - getFixedSlot(CALLEE_SLOT).toObject().is()); - return getFixedSlot(CALLEE_SLOT).isNull(); - } + inline bool isForEval() const; /* * Returns the function for which this CallObject was created. (This may * only be called if !isForEval.) */ - JSFunction& callee() const { - MOZ_ASSERT(!is()); - return getFixedSlot(CALLEE_SLOT).toObject().as(); - } + inline JSFunction& callee() const; /* For jit access. */ static size_t offsetOfCallee() { @@ -789,6 +797,7 @@ class ModuleEnvironmentObject : public LexicalScopeBase static ModuleEnvironmentObject* create(ExclusiveContext* cx, HandleModuleObject module); ModuleObject& module(); + StaticModuleScope& staticScope(); IndirectBindingMap& importBindings(); bool createImportBinding(JSContext* cx, HandleAtom importName, HandleModuleObject module, @@ -1107,11 +1116,11 @@ class MOZ_RAII ScopeIter JSObject* maybeStaticScope() const; StaticBlockScope& staticBlock() const { return ssi_.block(); } + StaticModuleScope& module() const { return ssi_.module(); } StaticWithScope& staticWith() const { return ssi_.staticWith(); } StaticEvalScope& staticEval() const { return ssi_.eval(); } StaticNonSyntacticScope& staticNonSyntactic() const { return ssi_.nonSyntactic(); } JSFunction& fun() const { return ssi_.fun(); } - ModuleObject& module() const { return ssi_.module(); } bool withinInitialFrame() const { return !!frame_; } AbstractFramePtr initialFrame() const { MOZ_ASSERT(withinInitialFrame()); return frame_; } @@ -1347,6 +1356,13 @@ JSObject::is() const return hasClass(&js::ClonedBlockObject::class_) && !getProto(); } +template<> +inline bool +JSObject::is() const +{ + return hasClass(&js::ModuleEnvironmentObject::class_) && !getProto(); +} + template<> inline bool JSObject::is() const @@ -1360,10 +1376,18 @@ inline bool JSObject::is() const { return is() || + is() || is() || is(); } +template<> +inline bool +JSObject::is() const +{ + return hasClass(&js::ModuleEnvironmentObject::class_) && !!getProto(); +} + template<> inline bool JSObject::is() const @@ -1533,6 +1557,24 @@ ScopeIter::enclosingScope() const return *scope_; } +inline bool +js::CallObject::isForEval() const +{ + if (is()) + return false; + MOZ_ASSERT(getFixedSlot(CALLEE_SLOT).isObjectOrNull()); + MOZ_ASSERT_IF(getFixedSlot(CALLEE_SLOT).isObject(), + getFixedSlot(CALLEE_SLOT).toObject().is()); + return getFixedSlot(CALLEE_SLOT).isNull(); +} + +inline JSFunction& +js::CallObject::callee() const +{ + MOZ_ASSERT(!is()); + return getFixedSlot(CALLEE_SLOT).toObject().as(); +} + extern bool CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain, HandleObject dynamicTerminatingScope, diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 44cec89a9dd..76fc0217c86 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -119,7 +119,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject* } else if (i.hasSyntacticDynamicScopeObject()) { switch (i.type()) { case StaticScopeIter::Module: - MOZ_ASSERT(scope->as().module().script() == i.moduleScript()); + MOZ_ASSERT(scope->as().module().staticScope() == &i.module()); scope = &scope->as().enclosingScope(); break; case StaticScopeIter::Function: From 751a9aff51743d7ee3220e356af6978785578b9f Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 5 Nov 2015 06:12:08 -0600 Subject: [PATCH 131/160] Bug 1221144 - Part 7: Introduce StaticFunctionScope, same story. r=shu. Until now, Function.prototype had a null enclosing static scope, as a special case. Now we give it a real static scope, like all other interpreted functions. New XDR tests cover a path in XDRLazyScript() that was previously untested. --- js/src/frontend/BytecodeCompiler.cpp | 8 +- js/src/frontend/BytecodeEmitter.cpp | 36 ++++-- js/src/frontend/ParseNode.cpp | 4 +- js/src/frontend/Parser.cpp | 59 ++++++---- js/src/frontend/SharedContext.h | 14 ++- js/src/gc/Marking.cpp | 8 +- js/src/gc/Policy.h | 2 + .../tests/gc/withStatementOffThread.js | 12 ++ js/src/jit-test/tests/xdr/scope.js | 46 +++++++- js/src/jsfriendapi.cpp | 4 +- js/src/jsfun.cpp | 18 +-- js/src/jsscript.cpp | 104 +++++++++++------- js/src/jsscript.h | 49 ++++++--- js/src/jsscriptinlines.h | 15 +++ js/src/vm/Interpreter.cpp | 4 +- js/src/vm/ScopeObject-inl.h | 31 +++--- js/src/vm/ScopeObject.cpp | 43 ++++++-- js/src/vm/ScopeObject.h | 104 +++++++++++------- 18 files changed, 385 insertions(+), 176 deletions(-) create mode 100644 js/src/jit-test/tests/gc/withStatementOffThread.js diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index aaacbce0e9c..a6dc80631a9 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -653,7 +653,8 @@ BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun, if (fn->pn_funbox->function()->isInterpreted()) { MOZ_ASSERT(fun == fn->pn_funbox->function()); - if (!createScript(enclosingStaticScope)) + RootedObject scope(cx, fn->pn_funbox->staticScope()); + if (!createScript(scope)) return false; script->bindings = fn->pn_funbox->bindings; @@ -805,11 +806,12 @@ frontend::CompileLazyFunction(JSContext* cx, Handle lazy, const cha if (!NameFunctions(cx, pn)) return false; - RootedObject enclosingScope(cx, lazy->enclosingScope()); + RootedObject staticScope(cx, pn->pn_funbox->staticScope()); + MOZ_ASSERT(staticScope); RootedScriptSource sourceObject(cx, lazy->sourceObject()); MOZ_ASSERT(sourceObject); - Rooted script(cx, JSScript::Create(cx, enclosingScope, false, options, + Rooted script(cx, JSScript::Create(cx, staticScope, false, options, sourceObject, lazy->begin(), lazy->end())); if (!script) return false; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 8ca9be7847d..64519af75ff 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1467,7 +1467,7 @@ BytecodeEmitter::computeDefinitionIsAliased(BytecodeEmitter* bceOfDef, Definitio // object. Aliased block bindings do not need adjusting; see // computeAliasedSlots. uint32_t slot = dn->pn_scopecoord.slot(); - if (blockScopeOfDef(dn)->is() || + if (blockScopeOfDef(dn)->is() || blockScopeOfDef(dn)->is()) { MOZ_ASSERT(IsArgOp(*op) || slot < bceOfDef->script->bindings.numBodyLevelLocals()); @@ -1569,8 +1569,11 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn) // Look up for name in function and block scopes. if (ssi.type() == StaticScopeIter::Function) { RootedScript funScript(cx, ssi.funScript()); - if (funScript->funHasExtensibleScope() || ssi.fun().atom() == pn->pn_atom) + if (funScript->funHasExtensibleScope() || + ssi.fun().function().atom() == pn->pn_atom) + { return false; + } // Skip the current function, since we're trying to convert a // free name. @@ -1834,12 +1837,11 @@ BytecodeEmitter::bindNameToSlotHelper(ParseNode* pn) * Currently, the ALIASEDVAR ops do not support accessing the * callee of a DeclEnvObject, so use NAME. */ - JSFunction* fun = sc->asFunctionBox()->function(); - if (blockScopeOfDef(dn) != fun) + if (blockScopeOfDef(dn) != sc->asFunctionBox()->staticScope()) return true; - MOZ_ASSERT(fun->isLambda()); - MOZ_ASSERT(pn->pn_atom == fun->atom()); + MOZ_ASSERT(sc->asFunctionBox()->function()->isLambda()); + MOZ_ASSERT(pn->pn_atom == sc->asFunctionBox()->function()->atom()); /* * Leave pn->isOp(JSOP_GETNAME) if this->fun needs a CallObject to @@ -6391,14 +6393,22 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) SharedContext* outersc = sc; if (fun->isInterpretedLazy()) { if (!fun->lazyScript()->sourceObject()) { - JSObject* scope = innermostStaticScope(); + // Two cases that can arise during parsing can cause the static + // scope chain to be incorrectly linked up: (1) the + // transformation of blocks from non-scopeful to scopeful when + // the first block-scoped declaration is found; (2) legacy + // comprehension expression transplantation. The + // setEnclosingScope call below fixes these cases. + Rooted funScope(cx, fun->lazyScript()->staticScope()); + RootedObject enclosingScope(cx, innermostStaticScope()); + funScope->setEnclosingScope(enclosingScope); + JSObject* source = script->sourceObject(); - fun->lazyScript()->setParent(scope, &source->as()); + fun->lazyScript()->initSource(&source->as()); } if (emittingRunOnceLambda) fun->lazyScript()->setTreatAsRunOnce(); } else { - if (outersc->isFunctionBox() && outersc->asFunctionBox()->mightAliasLocals()) funbox->setMightAliasLocals(); // inherit mightAliasLocals from parent MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript); @@ -6411,9 +6421,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) const TransitiveCompileOptions& transitiveOptions = parser->options(); CompileOptions options(cx, transitiveOptions); - Rooted enclosingScope(cx, innermostStaticScope()); + // See comment above regarding funScope->setEnclosingScope(). + Rooted funScope(cx, &funbox->staticScope()->as()); + RootedObject enclosingScope(cx, innermostStaticScope()); + funScope->setEnclosingScope(enclosingScope); + Rooted sourceObject(cx, script->sourceObject()); - Rooted script(cx, JSScript::Create(cx, enclosingScope, false, options, + Rooted script(cx, JSScript::Create(cx, funScope, false, options, sourceObject, funbox->bufStart, funbox->bufEnd)); if (!script) diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index 30b35bd7eb7..e97278253bb 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -1193,8 +1193,8 @@ FunctionBox::trace(JSTracer* trc) { ObjectBox::trace(trc); bindings.trace(trc); - if (enclosingStaticScope_) - TraceRoot(trc, &enclosingStaticScope_, "funbox-enclosingStaticScope"); + if (staticScope_) + TraceRoot(trc, &staticScope_, "funbox-staticScope"); } void diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 984b8cf720b..fcb8e88056f 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -57,9 +57,9 @@ JSFunction::AutoParseUsingFunctionBox::AutoParseUsingFunctionBox(ExclusiveContex { fun_->unsetEnvironment(); fun_->setFunctionBox(funbox); - funbox->computeAllowSyntax(fun_); - funbox->computeInWith(fun_); - funbox->computeThisBinding(fun_); + funbox->computeAllowSyntax(funbox->staticScope_); + funbox->computeInWith(funbox->staticScope_); + funbox->computeThisBinding(funbox->staticScope_); } JSFunction::AutoParseUsingFunctionBox::~AutoParseUsingFunctionBox() @@ -122,15 +122,15 @@ void SharedContext::computeAllowSyntax(JSObject* staticScope) { for (StaticScopeIter it(context, staticScope); !it.done(); it++) { - if (it.type() == StaticScopeIter::Function && !it.fun().isArrow()) { + if (it.type() == StaticScopeIter::Function && !it.fun().function().isArrow()) { // Any function supports new.target. allowNewTarget_ = true; - allowSuperProperty_ = it.fun().allowSuperProperty(); + allowSuperProperty_ = it.fun().function().allowSuperProperty(); if (it.maybeFunctionBox()) { superScopeAlreadyNeedsHomeObject_ = it.maybeFunctionBox()->needsHomeObject(); allowSuperCall_ = it.maybeFunctionBox()->isDerivedClassConstructor(); } else { - allowSuperCall_ = it.fun().isDerivedClassConstructor(); + allowSuperCall_ = it.fun().function().isDerivedClassConstructor(); } break; } @@ -147,9 +147,10 @@ SharedContext::computeThisBinding(JSObject* staticScope) } if (it.type() == StaticScopeIter::Function) { + RootedFunction fun(context, &it.fun().function()); // Arrow functions and generator expression lambdas don't have // their own `this` binding. - if (it.fun().isArrow()) + if (fun->isArrow()) continue; bool isDerived; if (it.maybeFunctionBox()) { @@ -157,9 +158,9 @@ SharedContext::computeThisBinding(JSObject* staticScope) continue; isDerived = it.maybeFunctionBox()->isDerivedClassConstructor(); } else { - if (it.fun().nonLazyScript()->isGeneratorExp()) + if (fun->nonLazyScript()->isGeneratorExp()) continue; - isDerived = it.fun().isDerivedClassConstructor(); + isDerived = fun->isDerivedClassConstructor(); } // Derived class constructors (including nested arrow functions and @@ -195,8 +196,8 @@ SharedContext::markSuperScopeNeedsHomeObject() return; for (StaticScopeIter it(context, staticScope()); !it.done(); it++) { - if (it.type() == StaticScopeIter::Function && !it.fun().isArrow()) { - MOZ_ASSERT(it.fun().allowSuperProperty()); + if (it.type() == StaticScopeIter::Function && !it.fun().function().isArrow()) { + MOZ_ASSERT(it.fun().function().allowSuperProperty()); // If we are still emitting the outer function that needs a home // object, mark it as needing one. Otherwise, we must be emitting // an eval script, and the outer function must already be marked @@ -204,7 +205,7 @@ SharedContext::markSuperScopeNeedsHomeObject() if (it.maybeFunctionBox()) it.maybeFunctionBox()->setNeedsHomeObject(); else - MOZ_ASSERT(it.fun().nonLazyScript()->needsHomeObject()); + MOZ_ASSERT(it.funScript()->needsHomeObject()); superScopeAlreadyNeedsHomeObject_ = true; return; } @@ -754,12 +755,12 @@ Parser::newObjectBox(JSObject* obj) template FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun, - JSObject* enclosingStaticScope, ParseContext* outerpc, + ParseContext* outerpc, Directives directives, bool extraWarnings, GeneratorKind generatorKind) : ObjectBox(fun, traceListHead), SharedContext(cx, directives, extraWarnings), bindings(), - enclosingStaticScope_(enclosingStaticScope), + staticScope_(nullptr), bufStart(0), bufEnd(0), startLine(1), @@ -782,6 +783,15 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct MOZ_ASSERT(fun->isTenured()); } +bool +FunctionBox::initStaticScope(JSObject* enclosingStaticScope) +{ + RootedFunction fun(context, function()); + Rooted enclosing(context, &enclosingStaticScope->as()); + staticScope_ = StaticFunctionScope::create(context, fun, enclosing); + return staticScope_ != nullptr; +} + template FunctionBox* Parser::newFunctionBox(Node fn, JSFunction* fun, @@ -801,15 +811,17 @@ Parser::newFunctionBox(Node fn, JSFunction* fun, * function. */ FunctionBox* funbox = - alloc.new_(context, traceListHead, fun, enclosingStaticScope, outerpc, - inheritedDirectives, options().extraWarningsOption, - generatorKind); + alloc.new_(context, traceListHead, fun, outerpc, inheritedDirectives, + options().extraWarningsOption, generatorKind); if (!funbox) { ReportOutOfMemory(context); return nullptr; } - traceListHead = funbox; + + if (!funbox->initStaticScope(enclosingStaticScope)) + return nullptr; + if (fn) handler.setFunctionBox(fn, funbox); @@ -2844,7 +2856,9 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox* funbo size_t numInnerFunctions = pc->innerFunctions.length(); RootedFunction fun(context, funbox->function()); - LazyScript* lazy = LazyScript::CreateRaw(context, fun, numFreeVariables, numInnerFunctions, + Rooted funScope(context, &funbox->staticScope()->as()); + LazyScript* lazy = LazyScript::CreateRaw(context, fun, funScope, + numFreeVariables, numInnerFunctions, versionNumber(), funbox->bufStart, funbox->bufEnd, funbox->startLine, funbox->startColumn); if (!lazy) @@ -6501,8 +6515,11 @@ template <> ParseNode* Parser::withStatement(YieldHandling yieldHandling) { - // test262/ch12/12.10/12.10-0-1.js fails if we try to parse with-statements - // in syntax-parse mode. See bug 892583. + // This is intentionally different from other abortIfSyntaxParser() + // bailouts: `with` statements rule out syntax-only parsing for the entire + // compilation unit. This `return null()` causes us to bail out all the way + // to BytecodeCompiler::compileScript(), which retries with syntax parsing + // disabled. See bug 892583. if (handler.syntaxParser) { handler.disableSyntaxParser(); abortedSyntaxParse = true; diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 575cf7dd194..fa988af8bd7 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -300,7 +300,7 @@ class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext // non-function scope, so we have to compute our ThisBinding based on // the actual callee. if (maybeEvalCaller) - computeThisBinding(maybeEvalCaller); + computeThisBinding(maybeEvalCaller->nonLazyScript()->staticScope()); else computeThisBinding(staticScope); } @@ -312,7 +312,7 @@ class FunctionBox : public ObjectBox, public SharedContext { public: Bindings bindings; /* bindings for this function */ - JSObject* enclosingStaticScope_; + StaticFunctionScope* staticScope_; uint32_t bufStart; uint32_t bufEnd; uint32_t startLine; @@ -335,13 +335,15 @@ class FunctionBox : public ObjectBox, public SharedContext template FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunction* fun, - JSObject* enclosingStaticScope, ParseContext* pc, - Directives directives, bool extraWarnings, GeneratorKind generatorKind); + ParseContext* pc, Directives directives, bool extraWarnings, + GeneratorKind generatorKind); + + bool initStaticScope(JSObject* enclosingStaticScope); ObjectBox* toObjectBox() override { return this; } JSFunction* function() const { return &object->as(); } - JSObject* staticScope() const override { return function(); } - JSObject* enclosingStaticScope() const { return enclosingStaticScope_; } + JSObject* staticScope() const override { return staticScope_; } + JSObject* enclosingStaticScope() const { return staticScope_->enclosingScope(); } GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); } bool isGenerator() const { return generatorKind() != NotGenerator; } diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 2700e1f01c0..c1fdf3fa885 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -955,8 +955,8 @@ LazyScript::traceChildren(JSTracer* trc) if (sourceObject_) TraceEdge(trc, &sourceObject_, "sourceObject"); - if (enclosingScope_) - TraceEdge(trc, &enclosingScope_, "enclosingScope"); + if (staticScope_) + TraceEdge(trc, &staticScope_, "staticScope"); // We rely on the fact that atoms are always tenured. FreeVariable* freeVariables = this->freeVariables(); @@ -981,8 +981,8 @@ js::GCMarker::eagerlyMarkChildren(LazyScript *thing) if (thing->sourceObject_) traverseEdge(thing, static_cast(thing->sourceObject_)); - if (thing->enclosingScope_) - traverseEdge(thing, static_cast(thing->enclosingScope_)); + if (thing->staticScope_) + traverseEdge(thing, static_cast(thing->staticScope_)); // We rely on the fact that atoms are always tenured. LazyScript::FreeVariable* freeVariables = thing->freeVariables(); diff --git a/js/src/gc/Policy.h b/js/src/gc/Policy.h index 8243ae7efc7..1159d6ea835 100644 --- a/js/src/gc/Policy.h +++ b/js/src/gc/Policy.h @@ -100,6 +100,8 @@ class JitCode; D(js::ScriptSourceObject*) \ D(js::Shape*) \ D(js::SharedArrayBufferObject*) \ + D(js::StaticFunctionScope*) \ + D(js::StaticScope*) \ D(js::StructTypeDescr*) \ D(js::UnownedBaseShape*) \ D(js::jit::JitCode*) diff --git a/js/src/jit-test/tests/gc/withStatementOffThread.js b/js/src/jit-test/tests/gc/withStatementOffThread.js new file mode 100644 index 00000000000..8ab732d3817 --- /dev/null +++ b/js/src/jit-test/tests/gc/withStatementOffThread.js @@ -0,0 +1,12 @@ +if (helperThreadCount() != 0) + quit(); + +var code = ` +function f() { + [function() { { function g() { } } }, + function() { with ({}) { } }]; +} +`; + +offThreadCompileScript(code); +runOffThreadScript(); diff --git a/js/src/jit-test/tests/xdr/scope.js b/js/src/jit-test/tests/xdr/scope.js index 417a402d24d..90698ceebd9 100644 --- a/js/src/jit-test/tests/xdr/scope.js +++ b/js/src/jit-test/tests/xdr/scope.js @@ -1,6 +1,50 @@ load(libdir + 'bytecode-cache.js'); var test = ""; +// code a nested function after calling it +test = ` + function f() { + function g() { + return [f, g]; + } + return g(); + } + f() +`; +evalWithCache(test, { + assertEqBytecode: true, + checkAfter(ctx) { + let [f, g] = ctx.global.f(); + assertEq(f, ctx.global.f); + assertEq(f()[0], f); + assertEq(f()[1] === g, false); // second call, fresh g closure + assertEq(f()[1].toString(), g.toString()); // but the same source code + assertEq(g()[0], f); + assertEq(g()[1], g); + } +}); + +// code an unused function that contains an unused nested function +test = ` + function f() { + function g() { + return [f, g]; + } + return g; + } + f +`; +evalWithCache(test, { + assertEqBytecode: true, + checkAfter(ctx) { + let f = ctx.global.f; + let g = f(); + let [f1, g1] = g(); + assertEq(f1, f); + assertEq(g1, g); + } +}); + // code a function which has both used and unused inner functions. test = (function () { function f() { @@ -16,4 +60,4 @@ test = (function () { return "var obj = { x : 2 };" + f.toSource() + "; f()"; })(); -evalWithCache(test, { assertEqBytecode: true, assertEqResult : true }); +evalWithCache(test, { assertEqBytecode: true, assertEqResult: true }); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index e57dca138fd..b56346ee65a 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -405,9 +405,9 @@ js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext* cx) return nullptr; RootedFunction curr(cx, iter.callee(cx)); - for (StaticScopeIter i(curr); !i.done(); i++) { + for (StaticScopeIter i(curr->nonLazyScript()->staticScope()); !i.done(); i++) { if (i.type() == StaticScopeIter::Function) - curr = &i.fun(); + curr = &i.fun().function(); } return curr; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 1a63c781ae3..a1f11c4828a 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -42,6 +42,7 @@ #include "vm/Debugger.h" #include "vm/GlobalObject.h" #include "vm/Interpreter.h" +#include "vm/ScopeObject.h" #include "vm/Shape.h" #include "vm/StringBuffer.h" #include "vm/WrapperObject.h" @@ -751,15 +752,14 @@ static JSObject* CreateFunctionPrototype(JSContext* cx, JSProtoKey key) { Rooted self(cx, cx->global()); - RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject()); - /* - * Bizarrely, |Function.prototype| must be an interpreted function, so - * give it the guts to be one. - */ + + // Bizarrely, |Function.prototype| must be an interpreted function, so + // give it the guts to be one. + Rooted globalLexicalEnv(cx, &self->lexicalScope()); JSObject* functionProto_ = NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED, - self, nullptr, objectProto, AllocKind::FUNCTION, + globalLexicalEnv, nullptr, objectProto, AllocKind::FUNCTION, SingletonObject); if (!functionProto_) return nullptr; @@ -787,8 +787,12 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key) if (!sourceObject || !ScriptSourceObject::initFromOptions(cx, sourceObject, options)) return nullptr; + Rooted globalScope(cx, &globalLexicalEnv->staticBlock()); + Rooted funScope(cx, StaticFunctionScope::create(cx, functionProto, globalScope)); + if (!funScope) + return nullptr; RootedScript script(cx, JSScript::Create(cx, - /* enclosingScope = */ nullptr, + funScope, /* savedCallerFun = */ false, options, sourceObject, diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 81e51dbc8b1..62558104204 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -516,7 +516,7 @@ XDRLazyFreeVariables(XDRState* xdr, MutableHandle lazy) template static bool XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript script, - HandleObject enclosingScope, MutableHandle lazy) + HandleObject funScope, MutableHandle lazy) { MOZ_ASSERT_IF(mode == XDR_ENCODE, script->isRelazifiable() && script->maybeLazyScript()); MOZ_ASSERT_IF(mode == XDR_ENCODE, !lazy->numInnerFunctions()); @@ -546,8 +546,8 @@ XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript scri return false; if (mode == XDR_DECODE) { - lazy.set(LazyScript::Create(cx, fun, script, enclosingScope, script, - packedFields, begin, end, lineno, column)); + lazy.set(LazyScript::Create(cx, fun, script, funScope.as(), + script, packedFields, begin, end, lineno, column)); // As opposed to XDRLazyScript, we need to restore the runtime bits // of the script, as we are trying to match the fact this function @@ -849,6 +849,13 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript return false; } + if (fun) { + enclosingScope = StaticFunctionScope::create(cx, fun, + enclosingScope.as()); + if (!enclosingScope) + return false; + } + script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)), options, sourceObject, 0, 0); if (!script) @@ -1054,7 +1061,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript // This is not ternary because MSVC can't typecheck the // ternary. if (fun) - enclosingStaticScope = fun; + enclosingStaticScope = script->staticScope(); else enclosingStaticScope = enclosingScope; } @@ -1124,7 +1131,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript // This is not ternary because MSVC can't typecheck the // ternary. if (fun) - funEnclosingScope = fun; + funEnclosingScope = script->staticScope(); else funEnclosingScope = enclosingScope; } else { @@ -1268,7 +1275,12 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript } if (mode == XDR_DECODE) { - lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript, + Rooted enclosingStaticScope(cx, &enclosingScope->as()); + Rooted funScope(cx, + StaticFunctionScope::create(cx, fun, enclosingStaticScope)); + if (!funScope) + return false; + lazy.set(LazyScript::Create(cx, fun, nullptr, funScope, enclosingScript, packedFields, begin, end, lineno, column)); if (!lazy) return false; @@ -1283,13 +1295,14 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript // Code inner functions. { RootedFunction func(cx); + Rooted funScope(cx, lazy->staticScope()); HeapPtrFunction* innerFunctions = lazy->innerFunctions(); size_t numInnerFunctions = lazy->numInnerFunctions(); for (size_t i = 0; i < numInnerFunctions; i++) { if (mode == XDR_ENCODE) func = innerFunctions[i]; - if (!XDRInterpretedFunction(xdr, fun, enclosingScript, &func)) + if (!XDRInterpretedFunction(xdr, funScope, enclosingScript, &func)) return false; if (mode == XDR_DECODE) @@ -2747,7 +2760,7 @@ JSScript::initCompartment(ExclusiveContext* cx) } /* static */ JSScript* -JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCallerFun, +JSScript::Create(ExclusiveContext* cx, HandleObject staticScope, bool savedCallerFun, const ReadOnlyCompileOptions& options, HandleObject sourceObject, uint32_t bufStart, uint32_t bufEnd) { @@ -2760,7 +2773,7 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa PodZero(script.get()); new (&script->bindings) Bindings; - script->enclosingStaticScope_ = enclosingScope; + script->staticScope_ = staticScope ? &staticScope->as() : nullptr; script->savedCallerFun_ = savedCallerFun; script->initCompartment(cx); @@ -2768,10 +2781,12 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa script->noScriptRval_ = options.noScriptRval; script->treatAsRunOnce_ = options.isRunOnce; - // Compute whether this script is under a non-syntactic scope. We don't - // need to walk the entire static scope chain if the script is nested in a - // function. In that case, we can propagate the cached value from the - // outer script. + // Compute whether this script is under a non-syntactic scope, passing + // staticScope->enclosingScope() in a case where staticScope itself is not + // a non-syntactic scope and may not be fully initialized yet. + RootedObject enclosingScope(cx, staticScope); + if (staticScope && staticScope->is()) + enclosingScope = staticScope->as().enclosingScope(); script->hasNonSyntacticScope_ = HasNonSyntacticStaticScopeChain(enclosingScope); script->version = options.version; @@ -3123,15 +3138,20 @@ JSScript::uninlinedGlobal() const void JSScript::fixEnclosingStaticGlobalLexicalScope() { - MOZ_ASSERT(IsStaticGlobalLexicalScope(enclosingStaticScope_)); - enclosingStaticScope_ = &global().lexicalScope().staticBlock(); + if (function_) { + MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_->enclosingScope())); + staticScope_->setEnclosingScope(&global().lexicalScope().staticBlock()); + } else { + MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_)); + staticScope_ = &global().lexicalScope().staticBlock(); + } } void LazyScript::fixEnclosingStaticGlobalLexicalScope() { - MOZ_ASSERT(IsStaticGlobalLexicalScope(enclosingScope_)); - enclosingScope_ = &function_->global().lexicalScope().staticBlock(); + MOZ_ASSERT(IsStaticGlobalLexicalScope(staticScope_->enclosingScope())); + staticScope_->setEnclosingScope(&function_->global().lexicalScope().staticBlock()); } void @@ -3531,7 +3551,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri if (ssi.done() || ssi.type() == StaticScopeIter::NonSyntactic) { enclosingScope = scriptStaticScope; } else if (ssi.type() == StaticScopeIter::Function) { - MOZ_ASSERT(scriptStaticScope->is()); + MOZ_ASSERT(scriptStaticScope->is()); enclosingScope = scriptStaticScope; } else if (ssi.type() == StaticScopeIter::Block) { if (ssi.block().isGlobal()) { @@ -3713,13 +3733,18 @@ js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFu { MOZ_ASSERT(fun->isInterpreted()); + Rooted enclosing(cx, &enclosingScope->as()); + Rooted funScope(cx, StaticFunctionScope::create(cx, fun, enclosing)); + if (!funScope) + return nullptr; + // Allocate the destination script up front and set it as the script of // |fun|, which is to be its container. // // This is so that when cloning nested functions, they can walk the static // scope chain via fun and correctly compute the presence of a // non-syntactic global. - RootedScript dst(cx, CreateEmptyScriptForClone(cx, enclosingScope, src)); + RootedScript dst(cx, CreateEmptyScriptForClone(cx, funScope, src)); if (!dst) return nullptr; @@ -3735,7 +3760,7 @@ js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFu fun->initScript(dst); } - if (!detail::CopyScript(cx, fun, src, dst)) { + if (!detail::CopyScript(cx, funScope, src, dst)) { if (lazy) fun->initLazyScript(lazy); else @@ -3980,8 +4005,8 @@ JSScript::traceChildren(JSTracer* trc) if (module_) TraceEdge(trc, &module_, "module"); - if (enclosingStaticScope_) - TraceEdge(trc, &enclosingStaticScope_, "enclosingStaticScope"); + if (staticScope_) + TraceEdge(trc, &staticScope_, "staticScope"); if (maybeLazyScript()) TraceManuallyBarrieredEdge(trc, &lazyScript, "lazyScript"); @@ -4088,9 +4113,7 @@ JSScript::innermostStaticScopeInScript(jsbytecode* pc) { if (JSObject* scope = getStaticBlockScope(pc)) return scope; - if (module()) - return module()->staticScope(); - return functionNonDelazifying(); + return staticScope_; } JSObject* @@ -4240,10 +4263,12 @@ JSScript::formalLivesInArgumentsObject(unsigned argSlot) return argsObjAliasesFormals() && !formalIsAliased(argSlot); } -LazyScript::LazyScript(JSFunction* fun, void* table, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) +LazyScript::LazyScript(JSFunction* fun, StaticFunctionScope* funScope, void* table, + uint64_t packedFields, uint32_t begin, uint32_t end, + uint32_t lineno, uint32_t column) : script_(nullptr), function_(fun), - enclosingScope_(nullptr), + staticScope_(funScope), sourceObject_(nullptr), table_(table), packedFields_(packedFields), @@ -4271,13 +4296,10 @@ LazyScript::resetScript() } void -LazyScript::setParent(JSObject* enclosingScope, ScriptSourceObject* sourceObject) +LazyScript::initSource(ScriptSourceObject* sourceObject) { - MOZ_ASSERT(!sourceObject_ && !enclosingScope_); - MOZ_ASSERT_IF(enclosingScope, function_->compartment() == enclosingScope->compartment()); + MOZ_ASSERT(!sourceObject_); MOZ_ASSERT(function_->compartment() == sourceObject->compartment()); - - enclosingScope_ = enclosingScope; sourceObject_ = sourceObject; } @@ -4295,6 +4317,7 @@ LazyScript::maybeForwardedScriptSource() const /* static */ LazyScript* LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, + Handle funScope, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) { @@ -4324,11 +4347,12 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, cx->compartment()->scheduleDelazificationForDebugger(); - return new (res) LazyScript(fun, table.forget(), packed, begin, end, lineno, column); + return new (res) LazyScript(fun, funScope, table.forget(), packed, begin, end, lineno, column); } /* static */ LazyScript* LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, + Handle funScope, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) { @@ -4349,14 +4373,15 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun, p.isDerivedClassConstructor = false; p.needsHomeObject = false; - LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column); + LazyScript* res = LazyScript::CreateRaw(cx, fun, funScope, packedFields, + begin, end, lineno, column); MOZ_ASSERT_IF(res, res->version() == version); return res; } /* static */ LazyScript* LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, - HandleScript script, HandleObject enclosingScope, + HandleScript script, Handle funScope, HandleScript sourceObjectScript, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column) @@ -4368,7 +4393,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, // holding this lazy script. HandleFunction dummyFun = fun; - LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column); + LazyScript* res = LazyScript::CreateRaw(cx, fun, funScope, packedFields, + begin, end, lineno, column); if (!res) return nullptr; @@ -4386,7 +4412,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun, // Set the enclosing scope of the lazy function, this would later be // used to define the environment when the function would be used. MOZ_ASSERT(!res->sourceObject()); - res->setParent(enclosingScope, &sourceObjectScript->scriptSourceUnwrap()); + res->initSource(&sourceObjectScript->scriptSourceUnwrap()); MOZ_ASSERT(!res->hasScript()); if (script) @@ -4419,10 +4445,10 @@ LazyScript::hasUncompiledEnclosingScript() const // If the enclosing scope is a function with a null script or has a script // without code, it was not successfully compiled. - if (!enclosingScope() || !enclosingScope()->is()) + if (!enclosingScope() || !enclosingScope()->is()) return false; - JSFunction& fun = enclosingScope()->as(); + JSFunction& fun = enclosingScope()->as().function(); return !fun.hasScript() || fun.hasUncompiledScript() || !fun.nonLazyScript()->code(); } diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 2ef42fe054f..037f81d413e 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -50,6 +50,7 @@ class LazyScript; class ModuleObject; class NestedStaticScope; class StaticScope; +class StaticFunctionScope; class RegExpObject; struct SourceCompressionTask; class Shape; @@ -1004,7 +1005,22 @@ class JSScript : public js::gc::TenuredCell js::HeapPtrFunction function_; js::HeapPtr module_; - js::HeapPtrObject enclosingStaticScope_; + + // The static scope this script runs in. + // + // Specifically, it depends on the case: + // + // * direct eval: staticScope_ is the StaticEvalScope for the eval call. + // + // * function script: staticScope_ is function_'s StaticFunctionScope. + // + // * module script: staticScope_ is module_'s StaticModuleScope. + // + // * plain old global script or indirect eval: staticScope_ is the static + // global lexical scope (regardless of whether the script uses any + // global lexical bindings). + // + js::HeapPtr staticScope_; /* * Information attached by Ion. Nexto a valid IonScript this could be @@ -1213,7 +1229,7 @@ class JSScript : public js::gc::TenuredCell public: static JSScript* Create(js::ExclusiveContext* cx, - js::HandleObject enclosingScope, bool savedCallerFun, + js::HandleObject staticScope, bool savedCallerFun, const JS::ReadOnlyCompileOptions& options, js::HandleObject sourceObject, uint32_t sourceStart, uint32_t sourceEnd); @@ -1698,10 +1714,13 @@ class JSScript : public js::gc::TenuredCell inline js::GlobalObject& global() const; js::GlobalObject& uninlinedGlobal() const; - /* See StaticScopeIter comment. */ - JSObject* enclosingStaticScope() const { - return enclosingStaticScope_; - } + js::StaticScope* staticScope() const { return staticScope_; } + + /* + * The static scope this script runs in, skipping the StaticFunctionScope + * if this is a non-eval function script. + */ + inline JSObject* enclosingStaticScope() const; // Switch the script over from the off-thread compartment's static // global lexical scope to the main thread compartment's. @@ -2141,8 +2160,9 @@ class LazyScript : public gc::TenuredCell // Original function with which the lazy script is associated. HeapPtrFunction function_; - // Function or block chain in which the script is nested, or nullptr. - HeapPtrObject enclosingScope_; + // Static scope of this function. (All lazy scripts are for functions; + // global scripts and eval scripts are never lazified.) + HeapPtr staticScope_; // ScriptSourceObject, or nullptr if the script in which this is nested // has not been compiled yet. This is never a CCW; we don't clone @@ -2194,13 +2214,14 @@ class LazyScript : public gc::TenuredCell uint32_t lineno_; uint32_t column_; - LazyScript(JSFunction* fun, void* table, uint64_t packedFields, + LazyScript(JSFunction* fun, StaticFunctionScope* funScope, void* table, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); // Create a LazyScript without initializing the freeVariables and the // innerFunctions. To be GC-safe, the caller must initialize both vectors // with valid atoms and functions. static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun, + Handle funScope, uint64_t packedData, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); @@ -2209,6 +2230,7 @@ class LazyScript : public gc::TenuredCell // innerFunctions. To be GC-safe, the caller must initialize both vectors // with valid atoms and functions. static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun, + Handle funScope, uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); @@ -2223,7 +2245,7 @@ class LazyScript : public gc::TenuredCell // The sourceObjectScript argument must be non-null and is the script that // should be used to get the sourceObject_ of this lazyScript. static LazyScript* Create(ExclusiveContext* cx, HandleFunction fun, - HandleScript script, HandleObject enclosingScope, + HandleScript script, Handle funScope, HandleScript sourceObjectScript, uint64_t packedData, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column); @@ -2248,9 +2270,8 @@ class LazyScript : public gc::TenuredCell return bool(script_); } - JSObject* enclosingScope() const { - return enclosingScope_; - } + StaticFunctionScope* staticScope() const { return staticScope_; } + JSObject* enclosingScope() const; // Switch the script over from the off-thread compartment's static // global lexical scope to the main thread compartment's. @@ -2269,7 +2290,7 @@ class LazyScript : public gc::TenuredCell return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version); } - void setParent(JSObject* enclosingScope, ScriptSourceObject* sourceObject); + void initSource(ScriptSourceObject* sourceObject); uint32_t numFreeVariables() const { return p_.numFreeVariables; diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index 31ff63e4f02..eadd8ebe01a 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -92,8 +92,23 @@ LazyScript::functionDelazifying(JSContext* cx) const return function_; } +inline JSObject* +LazyScript::enclosingScope() const +{ + return staticScope_->enclosingScope(); +} + } // namespace js +inline JSObject* +JSScript::enclosingStaticScope() const +{ + // The static scope of a function script is the function scope (which + // contains arguments and local variables). This method's callers want to + // skip that scope. + return function_ ? staticScope_->enclosingScope() : staticScope_; +} + inline JSFunction* JSScript::functionDelazifying() const { diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index bfdbcc8aa97..f2f77499519 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1039,8 +1039,8 @@ SettleOnTryNote(JSContext* cx, JSTryNote* tn, ScopeIter& si, InterpreterRegs& re // Unwind the scope to the beginning of the JSOP_TRY. UnwindScope(cx, si, UnwindScopeToTryPc(regs.fp()->script(), tn)); - // Set pc to the first bytecode after the the try note to point - // to the beginning of catch or finally. + // Set pc to the first bytecode after the span of the try note, the + // beginning of the first catch or finally block. regs.pc = regs.fp()->script()->main() + tn->start + tn->length; regs.sp = regs.spForStackDepth(tn->stackDepth); } diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 87bfd1a16b5..8ae890c24ce 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -92,26 +92,22 @@ StaticScopeIter::operator++(int) obj = obj->template as().enclosingScope(); } else if (obj->template is()) { obj = obj->template as().enclosingScope(); - } else if (onNamedLambda || !obj->template as().isNamedLambda()) { + } else if (onNamedLambda || !obj->template as().isNamedLambda()) { onNamedLambda = false; - JSFunction& fun = obj->template as(); - if (fun.isBeingParsed()) - obj = fun.functionBox()->enclosingStaticScope(); - else - obj = fun.nonLazyScript()->enclosingStaticScope(); + obj = obj->template as().enclosingScope(); } else { onNamedLambda = true; } MOZ_ASSERT_IF(obj, IsStaticScope(obj)); - MOZ_ASSERT_IF(onNamedLambda, obj->template is()); + MOZ_ASSERT_IF(onNamedLambda, obj->template is()); } template inline bool StaticScopeIter::hasSyntacticDynamicScopeObject() const { - if (obj->template is()) { - JSFunction& fun = obj->template as(); + if (obj->template is()) { + JSFunction& fun = obj->template as().function(); if (fun.isBeingParsed()) return fun.functionBox()->needsCallObject(); return fun.needsCallObject(); @@ -140,7 +136,7 @@ StaticScopeIter::scopeShape() const return block().lastProperty(); if (type() == Module) return module().environmentShape(); - return funScript()->callObjShape(); + return fun().environmentShape(); } template @@ -159,7 +155,7 @@ StaticScopeIter::type() const return Eval; if (obj->template is()) return NonSyntactic; - MOZ_ASSERT(obj->template is()); + MOZ_ASSERT(obj->template is()); return Function; } @@ -200,15 +196,15 @@ inline JSScript* StaticScopeIter::funScript() const { MOZ_ASSERT(type() == Function); - return obj->template as().nonLazyScript(); + return obj->template as().function().nonLazyScript(); } template -inline JSFunction& +inline StaticFunctionScope& StaticScopeIter::fun() const { MOZ_ASSERT(type() == Function); - return obj->template as(); + return obj->template as(); } template @@ -216,8 +212,8 @@ inline frontend::FunctionBox* StaticScopeIter::maybeFunctionBox() const { MOZ_ASSERT(type() == Function); - if (fun().isBeingParsed()) - return fun().functionBox(); + if (fun().function().isBeingParsed()) + return fun().function().functionBox(); return nullptr; } @@ -243,7 +239,8 @@ JSObject::enclosingScope() if (is()) return nullptr; - MOZ_ASSERT_IF(is(), as().isInterpreted()); + MOZ_ASSERT(!is()); + MOZ_ASSERT(!is()); return &global(); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 4919ec809ae..ca0d60743ed 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -39,7 +39,7 @@ typedef MutableHandle MutableHandleArgumentsObject; /*** Static scope objects ************************************************************************/ void -StaticScope::setEnclosingScope(HandleObject obj) +StaticScope::setEnclosingScope(JSObject* obj) { MOZ_ASSERT_IF(obj->is(), obj->isDelegate()); setFixedSlot(ENCLOSING_SCOPE_SLOT, ObjectValue(*obj)); @@ -118,6 +118,28 @@ StaticBlockScope::addVar(ExclusiveContext* cx, Handle block, /* allowDictionary = */ false); } +const Class StaticFunctionScope::class_ = { + "StaticFunctionScope", + JSCLASS_HAS_RESERVED_SLOTS(StaticFunctionScope::RESERVED_SLOTS) | + JSCLASS_IS_ANONYMOUS +}; + +StaticFunctionScope* +StaticFunctionScope::create(ExclusiveContext* cx, Handle functionObject, + Handle enclosingScope) +{ + Rooted proto(cx, TaggedProto(nullptr)); + JSObject* obj = NewObjectWithGivenTaggedProto(cx, &class_, proto, TenuredObject, + BaseShape::DELEGATE); + if (!obj) + return nullptr; + + StaticFunctionScope* scope = &obj->as(); + scope->initEnclosingScope(enclosingScope); + scope->setReservedSlot(FUNCTION_OBJECT_SLOT, ObjectValue(*functionObject)); + return scope; +} + StaticModuleScope* StaticModuleScope::create(ExclusiveContext* cx, Handle moduleObject, Handle enclosingScope) @@ -2623,7 +2645,7 @@ DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& MOZ_ASSERT(!si.hasSyntacticScopeObject()); MOZ_ASSERT(cx->compartment() == debugScope.compartment()); // Generators should always reify their scopes. - MOZ_ASSERT_IF(si.type() == ScopeIter::Call, !si.fun().isGenerator()); + MOZ_ASSERT_IF(si.type() == ScopeIter::Call, !si.fun().function().isGenerator()); if (!CanUseDebugScopeMaps(cx)) return true; @@ -2981,7 +3003,8 @@ GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si) break; case ScopeIter::Call: { - RootedFunction callee(cx, &si.fun()); + RootedFunction callee(cx, &si.fun().function()); + // Generators should always reify their scopes. MOZ_ASSERT(!callee->isGenerator()); @@ -3204,10 +3227,10 @@ js::GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr fra return true; } - if (si.type() != ScopeIter::Call || si.fun().hasLexicalThis()) + if (si.type() != ScopeIter::Call || si.fun().function().hasLexicalThis()) continue; - RootedScript script(cx, si.fun().nonLazyScript()); + RootedScript script(cx, si.fun().function().nonLazyScript()); if (!script->functionHasThisBinding()) { MOZ_ASSERT(!script->isDerivedClassConstructor(), @@ -3403,10 +3426,12 @@ js::DumpStaticScopeChain(JSObject* staticScope) fprintf(stdout, "module [%p]", &ssi.module()); break; case StaticScopeIter::Function: - if (ssi.fun().isBeingParsed()) - fprintf(stdout, "funbox [%p fun=%p]", ssi.maybeFunctionBox(), &ssi.fun()); - else - fprintf(stdout, "function [%p]", &ssi.fun()); + if (ssi.fun().function().isBeingParsed()) { + fprintf(stdout, "funbox [%p box=%p fun=%p]", + &ssi.fun(), ssi.maybeFunctionBox(), &ssi.fun().function()); + } else { + fprintf(stdout, "function [%p fun=%p]", &ssi.fun(), &ssi.fun().function()); + } break; case StaticScopeIter::Block: fprintf(stdout, "block [%p]", &ssi.block()); diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 9473d132043..256d212d5d6 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -50,11 +50,11 @@ typedef Handle HandleModuleObject; * StaticBlockScope * Scope for non-function body blocks. e.g., |{ let x; }| * - * JSFunction + * StaticFunctionScope * Scope for function bodies. e.g., |function f() { var x; let y; }| * * StaticModuleScope - * Scope for moddules. + * Scope for modules. * * StaticWithScope * Scope for |with|. e.g., |with ({}) { ... }| @@ -91,7 +91,7 @@ class StaticScope : public NativeObject setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(obj)); } - void setEnclosingScope(HandleObject obj); + void setEnclosingScope(JSObject* obj); }; class NestedStaticScope : public StaticScope @@ -180,7 +180,7 @@ class StaticBlockScope : public NestedStaticScope /* * A refinement of enclosingStaticScope that returns nullptr if the enclosing - * static scope is a JSFunction. + * static scope is a StaticFunctionScope. */ inline StaticBlockScope* enclosingBlock() const; @@ -213,7 +213,7 @@ class StaticBlockScope : public NestedStaticScope /* * A let binding is aliased if accessed lexically by nested functions or - * dynamically through dynamic name lookup (eval, with, function::, etc). + * dynamically through dynamic name lookup (eval, with, etc). */ bool isAliased(unsigned i) { return slotValue(i).isTrue(); @@ -232,7 +232,10 @@ class StaticBlockScope : public NestedStaticScope // Is this the static global lexical scope? bool isGlobal() const { - return !enclosingStaticScope(); + // This method is called from js::gc::MergeCompartments() on scopes + // that may be otherwise unreachable (!) and whose enclosing scope slot + // may be `undefined`. + return getFixedSlot(ENCLOSING_SCOPE_SLOT).isNull(); } bool isSyntactic() const { @@ -300,6 +303,28 @@ class StaticBlockScope : public NestedStaticScope bool constant, unsigned index, bool* redeclared); }; +class StaticFunctionScope : public StaticScope +{ + static const unsigned FUNCTION_OBJECT_SLOT = StaticScope::RESERVED_SLOTS; + + public: + static const unsigned RESERVED_SLOTS = FUNCTION_OBJECT_SLOT + 1; + static const Class class_; + + static StaticFunctionScope* create(ExclusiveContext* cx, HandleFunction functionObject, + Handle enclosingScope); + + JSFunction& function() { + return getFixedSlot(FUNCTION_OBJECT_SLOT).toObject().as(); + } + + bool isNamedLambda() { return function().isNamedLambda(); } + + Shape* environmentShape() { + return function().nonLazyScript()->callObjShape(); + } +}; + // The top-level scope of a module. // Shares ModuleEnvironmentObject::class_. class StaticModuleScope : public StaticScope @@ -489,11 +514,11 @@ class StaticScopeIter static bool IsStaticScope(JSObject* obj) { return obj->is() || + obj->is() || obj->is() || obj->is() || obj->is() || - obj->is() || - obj->is(); + obj->is(); } public: @@ -548,8 +573,8 @@ class StaticScopeIter StaticWithScope& staticWith() const; StaticEvalScope& eval() const; StaticNonSyntacticScope& nonSyntactic() const; + StaticFunctionScope& fun() const; JSScript* funScript() const; - JSFunction& fun() const; frontend::FunctionBox* maybeFunctionBox() const; }; @@ -618,44 +643,46 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc); * chain (that is, fp->scopeChain() or fun->environment()). The hierarchy of * scope objects is: * - * JSObject Generic object - * | | - * | StaticScope--+ Created at compile time - * | | | | | - * | | | | StaticNonSyntacticScope See "Non-syntactic scopes" - * | | | | - * | | | StaticEvalScope Placeholder so eval scopes may be iterated through - * | | | - * | | StaticModuleScope Toplevel scope in a module - * | | - * | NestedStaticScope Enclosing scope is in the same JSScript - * | | | - * | | StaticBlockScope See NB - * | | - * | StaticWithScope Template for "with" object in static scope chain + * JSObject Generic object * | - * ScopeObject Engine-internal scope - * | | | - * | | DeclEnvObject Holds name of recursive/needsCallObject named lambda + * +--StaticScope Created at compile time * | | - * | LexicalScopeBase Shared base for function and modules scopes - * | | | - * | | CallObject Scope of entire function or strict eval + * | +--StaticNonSyntacticScope See "Non-syntactic scopes" * | | - * | ModuleEnvironmentObject Module top-level scope on run-time scope chain + * | +--StaticEvalScope Placeholder so eval scopes may be iterated through + * | | + * | +--StaticFunctionScope Scope in a function + * | | + * | +--StaticModuleScope Toplevel scope in a module + * | | + * | +--NestedStaticScope Enclosing scope is in the same JSScript + * | | + * | +--StaticBlockScope See "N.B." below. + * | | + * | +--StaticWithScope Template for "with" object in static scope chain * | - * NestedScopeObject Statement scopes; don't cross script boundaries - * | | - * | DynamicWithObject Run-time "with" object on scope chain - * | - * ClonedBlockObject let, switch, catch, for + * +--ScopeObject Engine-internal scope + * | + * +--DeclEnvObject Holds name of recursive/needsCallObject named lambda + * | + * +--LexicalScopeBase Shared base for function and modules scopes + * | | + * | +--CallObject Scope of entire function or strict eval + * | | + * | +--ModuleEnvironmentObject Module top-level scope on run-time scope chain + * | + * +--NestedScopeObject Statement scopes; don't cross script boundaries + * | + * +--ClonedBlockObject let, switch, catch, for + * | + * +--DynamicWithObject Run-time "with" object on scope chain * * This hierarchy represents more than just the interface hierarchy: reserved * slots in base classes are fixed for all derived classes. Thus, for example, * ScopeObject::enclosingScope() can simply access a fixed slot without further * dynamic type information. * - * NB: Static block objects are a special case: these objects are created at + * N.B. Static block objects are a special case: these objects are created at * compile time to hold the shape/binding information from which block objects * are cloned at runtime. These objects should never escape into the wild and * support a restricted set of ScopeObject operations. @@ -1120,7 +1147,7 @@ class MOZ_RAII ScopeIter StaticWithScope& staticWith() const { return ssi_.staticWith(); } StaticEvalScope& staticEval() const { return ssi_.eval(); } StaticNonSyntacticScope& staticNonSyntactic() const { return ssi_.nonSyntactic(); } - JSFunction& fun() const { return ssi_.fun(); } + StaticFunctionScope& fun() const { return ssi_.fun(); } bool withinInitialFrame() const { return !!frame_; } AbstractFramePtr initialFrame() const { MOZ_ASSERT(withinInitialFrame()); return frame_; } @@ -1376,6 +1403,7 @@ inline bool JSObject::is() const { return is() || + is() || is() || is() || is(); From 25f7c09cd8d0645bba1ad008f8f027794c5b66a8 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 9 Nov 2015 17:08:58 -0600 Subject: [PATCH 132/160] Bug 1221144 - Part 8: Change C++ type of static scopes everywhere from JSObject* to StaticScope*. r=shu. --- js/src/builtin/Eval.cpp | 3 +- js/src/frontend/BytecodeCompiler.cpp | 15 ++-- js/src/frontend/BytecodeEmitter.cpp | 19 ++--- js/src/frontend/BytecodeEmitter.h | 6 +- js/src/frontend/Parser.cpp | 18 ++--- js/src/frontend/Parser.h | 16 ++-- js/src/frontend/SharedContext.h | 18 ++--- js/src/jsapi.cpp | 14 ++-- js/src/jscompartment.cpp | 2 +- js/src/jscompartment.h | 8 +- js/src/jsfun.cpp | 14 ++-- js/src/jsfun.h | 4 +- js/src/jsfuninlines.h | 2 +- js/src/jsscript.cpp | 108 ++++++++++++++++----------- js/src/jsscript.h | 41 +++++----- js/src/jsscriptinlines.h | 4 +- js/src/vm/Interpreter.cpp | 8 +- js/src/vm/Interpreter.h | 5 +- js/src/vm/ScopeObject-inl.h | 64 +++++++--------- js/src/vm/ScopeObject.cpp | 65 ++++++++-------- js/src/vm/ScopeObject.h | 87 ++++++++++----------- js/src/vm/SelfHosting.cpp | 3 +- js/src/vm/Stack.cpp | 2 +- js/src/vm/Xdr.cpp | 4 +- 24 files changed, 269 insertions(+), 261 deletions(-) diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index d9ed9f6d875..5cc0983e6f1 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -476,7 +476,8 @@ js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScri // Unlike the non-syntactic scope chain API used by the subscript loader, // this API creates a fresh block scope each time. - RootedObject enclosingStaticScope(cx, script->enclosingStaticScope()); + Rooted enclosingStaticScope(cx, + &script->enclosingStaticScope()->as()); scope = ClonedBlockObject::createNonSyntactic(cx, enclosingStaticScope, scope); if (!scope) return false; diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index a6dc80631a9..2c7d10c6795 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -72,7 +72,7 @@ class MOZ_STACK_CLASS BytecodeCompiler bool canLazilyParse(); bool createParser(); bool createSourceAndParser(); - bool createScript(HandleObject staticScope, bool savedCallerFun = false); + bool createScript(Handle staticScope, bool savedCallerFun = false); bool createEmitter(SharedContext* sharedContext, HandleScript evalCaller = nullptr, bool insideNonGlobalEval = false); bool isEvalCompilationUnit(); @@ -255,7 +255,7 @@ BytecodeCompiler::createSourceAndParser() } bool -BytecodeCompiler::createScript(HandleObject staticScope, bool savedCallerFun) +BytecodeCompiler::createScript(Handle staticScope, bool savedCallerFun) { script = JSScript::Create(cx, staticScope, savedCallerFun, options, sourceObject, /* sourceStart = */ 0, sourceBuffer.length()); @@ -284,11 +284,8 @@ BytecodeCompiler::isEvalCompilationUnit() bool BytecodeCompiler::isNonGlobalEvalCompilationUnit() { - if (!isEvalCompilationUnit()) - return false; - StaticEvalScope& eval = enclosingStaticScope->as(); - JSObject* enclosing = eval.enclosingScopeForStaticScopeIter(); - return !IsStaticGlobalLexicalScope(enclosing); + return isEvalCompilationUnit() && + !IsStaticGlobalLexicalScope(enclosingStaticScope->enclosingScope()); } bool @@ -653,7 +650,7 @@ BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun, if (fn->pn_funbox->function()->isInterpreted()) { MOZ_ASSERT(fun == fn->pn_funbox->function()); - RootedObject scope(cx, fn->pn_funbox->staticScope()); + Rooted scope(cx, fn->pn_funbox->staticScope()); if (!createScript(scope)) return false; @@ -806,7 +803,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle lazy, const cha if (!NameFunctions(cx, pn)) return false; - RootedObject staticScope(cx, pn->pn_funbox->staticScope()); + Rooted staticScope(cx, pn->pn_funbox->staticScope()); MOZ_ASSERT(staticScope); RootedScriptSource sourceObject(cx, lazy->sourceObject()); MOZ_ASSERT(sourceObject); diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 64519af75ff..1fd782b8ab9 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -733,7 +733,7 @@ BytecodeEmitter::pushLoopStatement(LoopStmtInfo* stmt, StmtType type, ptrdiff_t } } -JSObject* +StaticScope* BytecodeEmitter::innermostStaticScope() const { if (StmtInfoBCE* stmt = innermostScopeStmt()) @@ -1362,9 +1362,7 @@ BytecodeEmitter::atBodyLevel(StmtInfoBCE* stmt) const if (sc->staticScope()->is()) { bool bl = !stmt->enclosing; MOZ_ASSERT_IF(bl, stmt->type == StmtType::BLOCK); - MOZ_ASSERT_IF(bl, stmt->staticScope - ->as() - .enclosingStaticScope() == sc->staticScope()); + MOZ_ASSERT_IF(bl, stmt->staticScope->enclosingScope() == sc->staticScope()); return bl; } return !stmt; @@ -3541,9 +3539,9 @@ BytecodeEmitter::emitSetThis(ParseNode* pn) } static bool -IsModuleOnScopeChain(JSObject* obj) +IsModuleOnScopeChain(StaticScope* scope) { - for (StaticScopeIter ssi(obj); !ssi.done(); ssi++) { + for (StaticScopeIter ssi(scope); !ssi.done(); ssi++) { if (ssi.type() == StaticScopeIter::Module) return true; } @@ -6399,9 +6397,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) // the first block-scoped declaration is found; (2) legacy // comprehension expression transplantation. The // setEnclosingScope call below fixes these cases. - Rooted funScope(cx, fun->lazyScript()->staticScope()); - RootedObject enclosingScope(cx, innermostStaticScope()); - funScope->setEnclosingScope(enclosingScope); + Rooted enclosingScope(cx, innermostStaticScope()); + fun->lazyScript()->staticScope()->setEnclosingScope(enclosingScope); JSObject* source = script->sourceObject(); fun->lazyScript()->initSource(&source->as()); @@ -6422,8 +6419,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) CompileOptions options(cx, transitiveOptions); // See comment above regarding funScope->setEnclosingScope(). - Rooted funScope(cx, &funbox->staticScope()->as()); - RootedObject enclosingScope(cx, innermostStaticScope()); + Rooted funScope(cx, funbox->staticScope()); + Rooted enclosingScope(cx, innermostStaticScope()); funScope->setEnclosingScope(enclosingScope); Rooted sourceObject(cx, script->sourceObject()); diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index b7cacb6249d..0d4348a21e1 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -249,9 +249,9 @@ struct BytecodeEmitter StmtInfoBCE* innermostStmt() const { return stmtStack.innermost(); } StmtInfoBCE* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); } - JSObject* innermostStaticScope() const; - JSObject* blockScopeOfDef(Definition* dn) const { - return parser->blockScopes[dn->pn_blockid]; + StaticScope* innermostStaticScope() const; + StaticScope* blockScopeOfDef(Definition* dn) const { + return &parser->blockScopes[dn->pn_blockid].get()->as(); } bool atBodyLevel(StmtInfoBCE* stmt) const; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index fcb8e88056f..650b9aba335 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -119,7 +119,7 @@ MarkUsesAsHoistedLexical(ParseNode* pn) } void -SharedContext::computeAllowSyntax(JSObject* staticScope) +SharedContext::computeAllowSyntax(StaticScope* staticScope) { for (StaticScopeIter it(context, staticScope); !it.done(); it++) { if (it.type() == StaticScopeIter::Function && !it.fun().function().isArrow()) { @@ -138,7 +138,7 @@ SharedContext::computeAllowSyntax(JSObject* staticScope) } void -SharedContext::computeThisBinding(JSObject* staticScope) +SharedContext::computeThisBinding(StaticScope* staticScope) { for (StaticScopeIter it(context, staticScope); !it.done(); it++) { if (it.type() == StaticScopeIter::Module) { @@ -177,7 +177,7 @@ SharedContext::computeThisBinding(JSObject* staticScope) } void -SharedContext::computeInWith(JSObject* staticScope) +SharedContext::computeInWith(StaticScope* staticScope) { for (StaticScopeIter it(context, staticScope); !it.done(); it++) { if (it.type() == StaticScopeIter::With) { @@ -784,10 +784,10 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct } bool -FunctionBox::initStaticScope(JSObject* enclosingStaticScope) +FunctionBox::initStaticScope(StaticScope* enclosingStaticScope) { RootedFunction fun(context, function()); - Rooted enclosing(context, &enclosingStaticScope->as()); + Rooted enclosing(context, enclosingStaticScope); staticScope_ = StaticFunctionScope::create(context, fun, enclosing); return staticScope_ != nullptr; } @@ -798,7 +798,7 @@ Parser::newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives inheritedDirectives, GeneratorKind generatorKind, - JSObject* enclosingStaticScope) + StaticScope* enclosingStaticScope) { MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope()); MOZ_ASSERT(fun); @@ -1170,7 +1170,7 @@ Parser::standaloneFunctionBody(HandleFunction fun, GeneratorKind generatorKind, Directives inheritedDirectives, Directives* newDirectives, - HandleObject enclosingStaticScope) + Handle enclosingStaticScope) { MOZ_ASSERT(checkOptionsCalled); @@ -2856,7 +2856,7 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox* funbo size_t numInnerFunctions = pc->innerFunctions.length(); RootedFunction fun(context, funbox->function()); - Rooted funScope(context, &funbox->staticScope()->as()); + Rooted funScope(context, funbox->staticScope()); LazyScript* lazy = LazyScript::CreateRaw(context, fun, funScope, numFreeVariables, numInnerFunctions, versionNumber(), funbox->bufStart, funbox->bufEnd, @@ -3061,7 +3061,7 @@ Parser::standaloneLazyFunction(HandleFunction fun, bool strict if (!tokenStream.peekTokenPos(&pn->pn_pos)) return null(); - RootedObject enclosing(context, fun->lazyScript()->enclosingScope()); + Rooted enclosing(context, fun->lazyScript()->enclosingScope()); Directives directives(/* strict = */ strict); FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, enclosing); if (!funbox) diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index f95e255497c..f7f864bee4d 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -290,7 +290,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext StmtInfoPC* innermostStmt() const { return stmtStack.innermost(); } StmtInfoPC* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); } StmtInfoPC* innermostNonLabelStmt() const { return stmtStack.innermostNonLabel(); } - JSObject* innermostStaticScope() const { + StaticScope* innermostStaticScope() const { if (StmtInfoPC* stmt = innermostScopeStmt()) return stmt->staticScope; return sc->staticScope(); @@ -310,9 +310,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext if (sc->staticScope()->is()) { bool bl = !stmt->enclosing; MOZ_ASSERT_IF(bl, stmt->type == StmtType::BLOCK); - MOZ_ASSERT_IF(bl, stmt->staticScope - ->template as() - .enclosingStaticScope() == sc->staticScope()); + MOZ_ASSERT_IF(bl, stmt->staticScope->enclosingScope() == sc->staticScope()); return bl; } return !stmt; @@ -507,11 +505,11 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter ObjectBox* newObjectBox(JSObject* obj); FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives directives, GeneratorKind generatorKind, - JSObject* enclosingStaticScope); + StaticScope* enclosingStaticScope); // Use when the funbox is the outermost. FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives, - GeneratorKind generatorKind, HandleObject enclosingStaticScope) + GeneratorKind generatorKind, Handle enclosingStaticScope) { return newFunctionBox(fn, fun, nullptr, directives, generatorKind, enclosingStaticScope); @@ -521,7 +519,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext* outerpc, Directives directives, GeneratorKind generatorKind) { - RootedObject enclosing(context, outerpc->innermostStaticScope()); + Rooted enclosing(context, outerpc->innermostStaticScope()); return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing); } @@ -534,7 +532,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind, HandleObject proto); - bool generateBlockId(JSObject* staticScope, uint32_t* blockIdOut) { + bool generateBlockId(StaticScope* staticScope, uint32_t* blockIdOut) { if (blockScopes.length() == StmtInfoPC::BlockIdLimit) { tokenStream.reportError(JSMSG_NEED_DIET, "program"); return false; @@ -600,7 +598,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter Node standaloneFunctionBody(HandleFunction fun, Handle formals, GeneratorKind generatorKind, Directives inheritedDirectives, Directives* newDirectives, - HandleObject enclosingStaticScope); + Handle enclosingStaticScope); // Parse a function, given only its arguments and body. Used for lazily // parsed functions. diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index fa988af8bd7..c9f9d308af4 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -229,10 +229,10 @@ class SharedContext // GlobalSharedContexts are stack allocated and thus may use RootedObject // for the static scope. FunctionBoxes are LifoAlloc'd and need to // manually trace their static scope. - virtual JSObject* staticScope() const = 0; - void computeAllowSyntax(JSObject* staticScope); - void computeInWith(JSObject* staticScope); - void computeThisBinding(JSObject* staticScope); + virtual StaticScope* staticScope() const = 0; + void computeAllowSyntax(StaticScope* staticScope); + void computeInWith(StaticScope* staticScope); + void computeThisBinding(StaticScope* staticScope); virtual ObjectBox* toObjectBox() { return nullptr; } bool isObjectBox() { return toObjectBox() != nullptr; } @@ -305,7 +305,7 @@ class MOZ_STACK_CLASS GlobalSharedContext : public SharedContext computeThisBinding(staticScope); } - JSObject* staticScope() const override { return staticScope_; } + StaticScope* staticScope() const override { return staticScope_; } }; class FunctionBox : public ObjectBox, public SharedContext @@ -338,12 +338,12 @@ class FunctionBox : public ObjectBox, public SharedContext ParseContext* pc, Directives directives, bool extraWarnings, GeneratorKind generatorKind); - bool initStaticScope(JSObject* enclosingStaticScope); + bool initStaticScope(StaticScope* enclosingStaticScope); ObjectBox* toObjectBox() override { return this; } JSFunction* function() const { return &object->as(); } - JSObject* staticScope() const override { return staticScope_; } - JSObject* enclosingStaticScope() const { return staticScope_->enclosingScope(); } + StaticFunctionScope* staticScope() const override { return staticScope_; } + StaticScope* enclosingStaticScope() const { return staticScope_->enclosingScope(); } GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); } bool isGenerator() const { return generatorKind() != NotGenerator; } @@ -429,7 +429,7 @@ class ModuleBox : public ObjectBox, public SharedContext ObjectBox* toObjectBox() override { return this; } ModuleObject* module() const { return &object->as(); } - JSObject* staticScope() const override { return module()->staticScope(); } + StaticModuleScope* staticScope() const override { return module()->staticScope(); } void trace(JSTracer* trc) override; }; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c33cce9ae00..65808e35f91 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3456,8 +3456,9 @@ CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain, staticScopeObj.set(&globalLexical->staticBlock()); if (!scopeChain.empty()) { - staticScopeObj.set(StaticNonSyntacticScope::create(cx, staticScopeObj)); - if (!staticScopeObj) + Rooted scope(cx, + StaticNonSyntacticScope::create(cx, staticScopeObj)); + if (!scope) return false; // The XPConnect subscript loader, which may pass in its own dynamic @@ -3478,10 +3479,11 @@ CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain, // TODOshu: disallow the subscript loader from using non-distinguished // objects as dynamic scopes. dynamicScopeObj.set( - cx->compartment()->getOrCreateNonSyntacticLexicalScope(cx, staticScopeObj, - dynamicScopeObj)); + cx->compartment()->getOrCreateNonSyntacticLexicalScope(cx, scope, dynamicScopeObj)); if (!dynamicScopeObj) return false; + + staticScopeObj.set(scope); } return true; @@ -3495,7 +3497,7 @@ IsFunctionCloneable(HandleFunction fun) // If a function was compiled to be lexically nested inside some other // script, we cannot clone it without breaking the compiler's assumptions. - if (JSObject* scope = fun->nonLazyScript()->enclosingStaticScope()) { + if (StaticScope* scope = fun->nonLazyScript()->enclosingStaticScope()) { // If the script is directly under the global scope, we can clone it. if (IsStaticGlobalLexicalScope(scope)) return true; @@ -3512,7 +3514,7 @@ IsFunctionCloneable(HandleFunction fun) if (block.needsClone()) return false; - JSObject* enclosing = block.enclosingStaticScope(); + StaticScope* enclosing = block.enclosingScope(); // If the script is an indirect eval that is immediately scoped // under the global, we can clone it. diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 77fb3f6a2d3..e27a274ac49 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -505,7 +505,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandle desc) ClonedBlockObject* JSCompartment::getOrCreateNonSyntacticLexicalScope(JSContext* cx, - HandleObject enclosingStatic, + Handle enclosingStatic, HandleObject enclosingScope) { if (!nonSyntacticLexicalScopes_) { diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 700d74f40f0..fb58d4b8acf 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -32,6 +32,7 @@ template class ComponentFinder; struct NativeIterator; class ClonedBlockObject; +class StaticNonSyntacticScope; /* * A single-entry cache for some base-10 double-to-string conversions. This @@ -529,9 +530,10 @@ struct JSCompartment explicit WrapperEnum(JSCompartment* c) : js::WrapperMap::Enum(c->crossCompartmentWrappers) {} }; - js::ClonedBlockObject* getOrCreateNonSyntacticLexicalScope(JSContext* cx, - js::HandleObject enclosingStatic, - js::HandleObject enclosingScope); + js::ClonedBlockObject* getOrCreateNonSyntacticLexicalScope( + JSContext* cx, + js::Handle enclosingStatic, + js::HandleObject enclosingScope); js::ClonedBlockObject* getNonSyntacticLexicalScope(JSObject* enclosingScope) const; /* diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index a1f11c4828a..d368a092dd8 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -536,8 +536,8 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) template bool -js::XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript, - MutableHandleFunction objp) +js::XDRInterpretedFunction(XDRState* xdr, Handle enclosingScope, + HandleScript enclosingScript, MutableHandleFunction objp) { enum FirstWordFlag { HasAtom = 0x1, @@ -653,10 +653,12 @@ js::XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope, Han } template bool -js::XDRInterpretedFunction(XDRState*, HandleObject, HandleScript, MutableHandleFunction); +js::XDRInterpretedFunction(XDRState*, Handle, HandleScript, + MutableHandleFunction); template bool -js::XDRInterpretedFunction(XDRState*, HandleObject, HandleScript, MutableHandleFunction); +js::XDRInterpretedFunction(XDRState*, Handle, HandleScript, + MutableHandleFunction); /* * [[HasInstance]] internal method for Function objects: fetch the .prototype @@ -1449,7 +1451,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti } if (script) { - RootedObject enclosingScope(cx, lazy->enclosingScope()); + Rooted enclosingScope(cx, lazy->enclosingScope()); RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, enclosingScope, fun, script)); if (!clonedScript) return false; @@ -2056,7 +2058,7 @@ js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject par JSFunction* js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent, - HandleObject newStaticScope, + Handle newStaticScope, gc::AllocKind allocKind /* = FUNCTION */, HandleObject proto /* = nullptr */) { diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 4b4cff9740b..dc9cfafcebe 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -728,7 +728,7 @@ CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject parent, // Functions whose scripts are cloned are always given singleton types. extern JSFunction* CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject parent, - HandleObject newStaticScope, + Handle newStaticScope, gc::AllocKind kind = gc::AllocKind::FUNCTION, HandleObject proto = nullptr); @@ -789,7 +789,7 @@ JSString* FunctionToString(JSContext* cx, HandleFunction fun, bool lambdaParen); template bool -XDRInterpretedFunction(XDRState* xdr, HandleObject enclosingScope, +XDRInterpretedFunction(XDRState* xdr, Handle enclosingScope, HandleScript enclosingScript, MutableHandleFunction objp); /* diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index b2ef7055c05..88d35534711 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -92,7 +92,7 @@ CloneFunctionObjectIfNotSingleton(JSContext* cx, HandleFunction fun, HandleObjec RootedScript script(cx, fun->getOrCreateScript(cx)); if (!script) return nullptr; - RootedObject staticScope(cx, script->enclosingStaticScope()); + Rooted staticScope(cx, script->enclosingStaticScope()); return CloneFunctionAndScript(cx, fun, parent, staticScope, kind, proto); } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 62558104204..a33dba27301 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -516,7 +516,7 @@ XDRLazyFreeVariables(XDRState* xdr, MutableHandle lazy) template static bool XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript script, - HandleObject funScope, MutableHandle lazy) + Handle funScope, MutableHandle lazy) { MOZ_ASSERT_IF(mode == XDR_ENCODE, script->isRelazifiable() && script->maybeLazyScript()); MOZ_ASSERT_IF(mode == XDR_ENCODE, !lazy->numInnerFunctions()); @@ -546,8 +546,8 @@ XDRRelazificationInfo(XDRState* xdr, HandleFunction fun, HandleScript scri return false; if (mode == XDR_DECODE) { - lazy.set(LazyScript::Create(cx, fun, script, funScope.as(), - script, packedFields, begin, end, lineno, column)); + lazy.set(LazyScript::Create(cx, fun, script, funScope, script, packedFields, + begin, end, lineno, column)); // As opposed to XDRLazyScript, we need to restore the runtime bits // of the script, as we are trying to match the fact this function @@ -592,8 +592,8 @@ enum XDRClassKind { template bool -js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript enclosingScript, - HandleFunction fun, MutableHandleScript scriptp) +js::XDRScript(XDRState* xdr, Handle enclosingScopeArg, + HandleScript enclosingScript, HandleFunction fun, MutableHandleScript scriptp) { /* NB: Keep this in sync with CopyScript. */ @@ -637,7 +637,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript JSContext* cx = xdr->cx(); RootedScript script(cx); - RootedObject enclosingScope(cx, enclosingScopeArg); + Rooted enclosingScope(cx, enclosingScopeArg); natoms = nsrcnotes = 0; nconsts = nobjects = nregexps = ntrynotes = nblockscopes = nyieldoffsets = 0; @@ -850,8 +850,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript } if (fun) { - enclosingScope = StaticFunctionScope::create(cx, fun, - enclosingScope.as()); + enclosingScope = StaticFunctionScope::create(cx, fun, enclosingScope); if (!enclosingScope) return false; } @@ -1052,11 +1051,12 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript } if (!xdr->codeUint32(&enclosingStaticScopeIndex)) return false; - Rooted enclosingStaticScope(cx); + Rooted enclosingStaticScope(cx); if (mode == XDR_DECODE) { if (enclosingStaticScopeIndex != UINT32_MAX) { MOZ_ASSERT(enclosingStaticScopeIndex < i); - enclosingStaticScope = script->objects()->vector[enclosingStaticScopeIndex]; + enclosingStaticScope = &script->objects()->vector[enclosingStaticScopeIndex] + ->as(); } else { // This is not ternary because MSVC can't typecheck the // ternary. @@ -1068,12 +1068,16 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript } if (classk == CK_BlockObject) { - Rooted tmp(cx, static_cast(objp->get())); + Rooted tmp(cx); + if (mode == XDR_ENCODE) + tmp = &(*objp)->as(); if (!XDRStaticBlockScope(xdr, enclosingStaticScope, &tmp)) return false; *objp = tmp; } else { - Rooted tmp(cx, static_cast(objp->get())); + Rooted tmp(cx); + if (mode == XDR_ENCODE) + tmp = &(*objp)->as(); if (!XDRStaticWithScope(xdr, enclosingStaticScope, &tmp)) return false; *objp = tmp; @@ -1084,7 +1088,7 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript case CK_JSFunction: { /* Code the nested function's enclosing scope. */ uint32_t funEnclosingScopeIndex = 0; - RootedObject funEnclosingScope(cx); + Rooted funEnclosingScope(cx); if (mode == XDR_ENCODE) { RootedFunction function(cx, &(*objp)->as()); @@ -1136,7 +1140,8 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript funEnclosingScope = enclosingScope; } else { MOZ_ASSERT(funEnclosingScopeIndex < i); - funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex]; + funEnclosingScope = &script->objects()->vector[funEnclosingScopeIndex] + .get()->as(); } } @@ -1213,7 +1218,10 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript if (mode == XDR_ENCODE) lazy = script->maybeLazyScript(); - if (!XDRRelazificationInfo(xdr, fun, script, enclosingScope, &lazy)) + Rooted lazyScope(cx, mode == XDR_DECODE + ? &enclosingScope->as() + : nullptr); + if (!XDRRelazificationInfo(xdr, fun, script, lazyScope, &lazy)) return false; if (mode == XDR_DECODE) @@ -1232,17 +1240,18 @@ js::XDRScript(XDRState* xdr, HandleObject enclosingScopeArg, HandleScript } template bool -js::XDRScript(XDRState*, HandleObject, HandleScript, HandleFunction, +js::XDRScript(XDRState*, Handle, HandleScript, HandleFunction, MutableHandleScript); template bool -js::XDRScript(XDRState*, HandleObject, HandleScript, HandleFunction, +js::XDRScript(XDRState*, Handle, HandleScript, HandleFunction, MutableHandleScript); template bool -js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript, - HandleFunction fun, MutableHandle lazy) +js::XDRLazyScript(XDRState* xdr, Handle enclosingScope, + HandleScript enclosingScript, HandleFunction fun, + MutableHandle lazy) { JSContext* cx = xdr->cx(); @@ -1275,9 +1284,8 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript } if (mode == XDR_DECODE) { - Rooted enclosingStaticScope(cx, &enclosingScope->as()); Rooted funScope(cx, - StaticFunctionScope::create(cx, fun, enclosingStaticScope)); + StaticFunctionScope::create(cx, fun, enclosingScope)); if (!funScope) return false; lazy.set(LazyScript::Create(cx, fun, nullptr, funScope, enclosingScript, @@ -1314,11 +1322,11 @@ js::XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript } template bool -js::XDRLazyScript(XDRState*, HandleObject, HandleScript, +js::XDRLazyScript(XDRState*, Handle, HandleScript, HandleFunction, MutableHandle); template bool -js::XDRLazyScript(XDRState*, HandleObject, HandleScript, +js::XDRLazyScript(XDRState*, Handle, HandleScript, HandleFunction, MutableHandle); void @@ -2760,7 +2768,7 @@ JSScript::initCompartment(ExclusiveContext* cx) } /* static */ JSScript* -JSScript::Create(ExclusiveContext* cx, HandleObject staticScope, bool savedCallerFun, +JSScript::Create(ExclusiveContext* cx, Handle staticScope, bool savedCallerFun, const ReadOnlyCompileOptions& options, HandleObject sourceObject, uint32_t bufStart, uint32_t bufEnd) { @@ -2773,7 +2781,7 @@ JSScript::Create(ExclusiveContext* cx, HandleObject staticScope, bool savedCalle PodZero(script.get()); new (&script->bindings) Bindings; - script->staticScope_ = staticScope ? &staticScope->as() : nullptr; + script->staticScope_ = staticScope; script->savedCallerFun_ = savedCallerFun; script->initCompartment(cx); @@ -2784,9 +2792,9 @@ JSScript::Create(ExclusiveContext* cx, HandleObject staticScope, bool savedCalle // Compute whether this script is under a non-syntactic scope, passing // staticScope->enclosingScope() in a case where staticScope itself is not // a non-syntactic scope and may not be fully initialized yet. - RootedObject enclosingScope(cx, staticScope); + Rooted enclosingScope(cx, staticScope); if (staticScope && staticScope->is()) - enclosingScope = staticScope->as().enclosingScope(); + enclosingScope = staticScope->enclosingScope(); script->hasNonSyntacticScope_ = HasNonSyntacticStaticScopeChain(enclosingScope); script->version = options.version; @@ -3429,7 +3437,8 @@ Rebase(JSScript* dst, JSScript* src, T* srcp) } static JSObject* -CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction srcFun) +CloneInnerInterpretedFunction(JSContext* cx, Handle enclosingScope, + HandleFunction srcFun) { /* NB: Keep this in sync with XDRInterpretedFunction. */ RootedObject cloneProto(cx); @@ -3469,7 +3478,7 @@ CloneInnerInterpretedFunction(JSContext* cx, HandleObject enclosingScope, Handle } bool -js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, +js::detail::CopyScript(JSContext* cx, Handle scriptStaticScope, HandleScript src, HandleScript dst) { if (src->treatAsRunOnce() && !src->functionNonDelazifying()) { @@ -3516,14 +3525,15 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri if (obj->is()) { Rooted innerBlock(cx, &obj->as()); - RootedObject enclosingScope(cx); + Rooted enclosingScope(cx); if (NestedStaticScope* enclosingBlock = innerBlock->enclosingNestedScope()) { if (IsStaticGlobalLexicalScope(enclosingBlock)) { MOZ_ASSERT(IsStaticGlobalLexicalScope(scriptStaticScope) || scriptStaticScope->is()); enclosingScope = scriptStaticScope; } else { - enclosingScope = objects[FindScopeObjectIndex(src, *enclosingBlock)]; + enclosingScope = &objects[FindScopeObjectIndex(src, *enclosingBlock)] + .get()->as(); } } else { enclosingScope = scriptStaticScope; @@ -3545,9 +3555,10 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri if (!innerFun->getOrCreateScript(cx)) return false; } - RootedObject staticScope(cx, innerFun->nonLazyScript()->enclosingStaticScope()); + Rooted staticScope(cx, innerFun->nonLazyScript() + ->enclosingStaticScope()); StaticScopeIter ssi(cx, staticScope); - RootedObject enclosingScope(cx); + Rooted enclosingScope(cx); if (ssi.done() || ssi.type() == StaticScopeIter::NonSyntactic) { enclosingScope = scriptStaticScope; } else if (ssi.type() == StaticScopeIter::Function) { @@ -3559,10 +3570,12 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri scriptStaticScope->is()); enclosingScope = scriptStaticScope; } else { - enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())]; + enclosingScope = &objects[FindScopeObjectIndex(src, ssi.block())] + .get()->as(); } } else { - enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())]; + enclosingScope = &objects[FindScopeObjectIndex(src, ssi.staticWith())] + .get()->as(); } clone = CloneInnerInterpretedFunction(cx, enclosingScope, innerFun); @@ -3676,7 +3689,7 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri } static JSScript* -CreateEmptyScriptForClone(JSContext* cx, HandleObject enclosingScope, HandleScript src) +CreateEmptyScriptForClone(JSContext* cx, Handle enclosingScope, HandleScript src) { /* * Wrap the script source object as needed. Self-hosted scripts may be @@ -3728,13 +3741,13 @@ js::CloneGlobalScript(JSContext* cx, Handle enclosingScope, Handle } JSScript* -js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, +js::CloneScriptIntoFunction(JSContext* cx, Handle enclosingScope, HandleFunction fun, HandleScript src) { MOZ_ASSERT(fun->isInterpreted()); - Rooted enclosing(cx, &enclosingScope->as()); - Rooted funScope(cx, StaticFunctionScope::create(cx, fun, enclosing)); + Rooted funScope(cx, StaticFunctionScope::create(cx, fun, + enclosingScope)); if (!funScope) return nullptr; @@ -4108,18 +4121,18 @@ JSScript::getStaticBlockScope(jsbytecode* pc) return blockChain; } -JSObject* +StaticScope* JSScript::innermostStaticScopeInScript(jsbytecode* pc) { - if (JSObject* scope = getStaticBlockScope(pc)) + if (NestedStaticScope* scope = getStaticBlockScope(pc)) return scope; return staticScope_; } -JSObject* +StaticScope* JSScript::innermostStaticScope(jsbytecode* pc) { - if (JSObject* scope = innermostStaticScopeInScript(pc)) + if (StaticScope* scope = innermostStaticScopeInScript(pc)) return scope; return enclosingStaticScope(); } @@ -4164,8 +4177,13 @@ js::SetFrameArgumentsObject(JSContext* cx, AbstractFramePtr frame, // Note that here and below, it is insufficient to only check for // JS_OPTIMIZED_ARGUMENTS, as Ion could have optimized out the // arguments slot. - if (IsOptimizedPlaceholderMagicValue(frame.callObj().as().aliasedVar(ScopeCoordinate(pc)))) - frame.callObj().as().setAliasedVar(cx, ScopeCoordinate(pc), cx->names().arguments, ObjectValue(*argsobj)); + if (IsOptimizedPlaceholderMagicValue(frame.callObj().as() + .aliasedVar(ScopeCoordinate(pc)))) + { + frame.callObj().as().setAliasedVar(cx, ScopeCoordinate(pc), + cx->names().arguments, + ObjectValue(*argsobj)); + } } else { if (IsOptimizedPlaceholderMagicValue(frame.unaliasedLocal(bi.frameIndex()))) frame.unaliasedLocal(bi.frameIndex()) = ObjectValue(*argsobj); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 037f81d413e..c9e419079b7 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -67,7 +67,8 @@ namespace detail { // Do not call this directly! It is exposed for the friend declarations in // this file. bool -CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, HandleScript dst); +CopyScript(JSContext* cx, Handle scriptStaticScope, HandleScript src, + HandleScript dst); } // namespace detail @@ -147,7 +148,7 @@ struct BlockScopeArray { class YieldOffsetArray { friend bool - detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScript src, + detail::CopyScript(JSContext* cx, Handle scriptStaticScope, HandleScript src, HandleScript dst); uint32_t* vector_; // Array of bytecode offsets. @@ -921,20 +922,20 @@ GeneratorKindFromBits(unsigned val) { * subsequent set-up of owning function or script object and then call * CallNewScriptHook. */ -template +template bool -XDRScript(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript, - HandleFunction fun, MutableHandleScript scriptp); +XDRScript(XDRState* xdr, Handle enclosingScope, + HandleScript enclosingScript, HandleFunction fun, MutableHandleScript scriptp); -template +template bool -XDRLazyScript(XDRState* xdr, HandleObject enclosingScope, HandleScript enclosingScript, - HandleFunction fun, MutableHandle lazy); +XDRLazyScript(XDRState* xdr, Handle enclosingScope, + HandleScript enclosingScript, HandleFunction fun, MutableHandle lazy); /* * Code any constant value. */ -template +template bool XDRScriptConst(XDRState* xdr, MutableHandleValue vp); @@ -945,13 +946,13 @@ class JSScript : public js::gc::TenuredCell template friend bool - js::XDRScript(js::XDRState* xdr, js::HandleObject enclosingScope, + js::XDRScript(js::XDRState* xdr, js::Handle enclosingScope, js::HandleScript enclosingScript, js::HandleFunction fun, js::MutableHandleScript scriptp); friend bool - js::detail::CopyScript(JSContext* cx, js::HandleObject scriptStaticScope, js::HandleScript src, - js::HandleScript dst); + js::detail::CopyScript(JSContext* cx, js::Handle scriptStaticScope, + js::HandleScript src, js::HandleScript dst); public: // @@ -1229,7 +1230,7 @@ class JSScript : public js::gc::TenuredCell public: static JSScript* Create(js::ExclusiveContext* cx, - js::HandleObject staticScope, bool savedCallerFun, + js::Handle staticScope, bool savedCallerFun, const JS::ReadOnlyCompileOptions& options, js::HandleObject sourceObject, uint32_t sourceStart, uint32_t sourceEnd); @@ -1720,7 +1721,7 @@ class JSScript : public js::gc::TenuredCell * The static scope this script runs in, skipping the StaticFunctionScope * if this is a non-eval function script. */ - inline JSObject* enclosingStaticScope() const; + inline js::StaticScope* enclosingStaticScope() const; // Switch the script over from the off-thread compartment's static // global lexical scope to the main thread compartment's. @@ -1891,13 +1892,13 @@ class JSScript : public js::gc::TenuredCell // Returns the innermost static scope at pc if it falls within the extent // of the script. Returns nullptr otherwise. - JSObject* innermostStaticScopeInScript(jsbytecode* pc); + js::StaticScope* innermostStaticScopeInScript(jsbytecode* pc); // As innermostStaticScopeInScript, but returns the enclosing static scope // if the innermost static scope falls without the extent of the script. - JSObject* innermostStaticScope(jsbytecode* pc); + js::StaticScope* innermostStaticScope(jsbytecode* pc); - JSObject* innermostStaticScope() { return innermostStaticScope(main()); } + js::StaticScope* innermostStaticScope() { return innermostStaticScope(main()); } /* * The isEmpty method tells whether this script has code that computes any @@ -2271,7 +2272,7 @@ class LazyScript : public gc::TenuredCell } StaticFunctionScope* staticScope() const { return staticScope_; } - JSObject* enclosingScope() const; + StaticScope* enclosingScope() const; // Switch the script over from the off-thread compartment's static // global lexical scope to the main thread compartment's. @@ -2550,7 +2551,7 @@ DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript maybeScr LineOption opt = NOT_CALLED_FROM_JSOP_EVAL); JSScript* -CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFunction fun, +CloneScriptIntoFunction(JSContext* cx, Handle enclosingScope, HandleFunction fun, HandleScript src); JSScript* @@ -2562,7 +2563,7 @@ CloneGlobalScript(JSContext* cx, Handle enclosingScope, HandleScri // with no associated compartment. namespace JS { namespace ubi { -template<> +template <> struct Concrete : TracerConcrete { CoarseType coarseType() const final { return CoarseType::Script; } Size size(mozilla::MallocSizeOf mallocSizeOf) const override; diff --git a/js/src/jsscriptinlines.h b/js/src/jsscriptinlines.h index eadd8ebe01a..e1ebacd8c71 100644 --- a/js/src/jsscriptinlines.h +++ b/js/src/jsscriptinlines.h @@ -92,7 +92,7 @@ LazyScript::functionDelazifying(JSContext* cx) const return function_; } -inline JSObject* +inline StaticScope* LazyScript::enclosingScope() const { return staticScope_->enclosingScope(); @@ -100,7 +100,7 @@ LazyScript::enclosingScope() const } // namespace js -inline JSObject* +inline js::StaticScope* JSScript::enclosingStaticScope() const { // The static scope of a function script is the function scope (which diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index f2f77499519..8ee25af3c2f 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -927,9 +927,8 @@ js::TypeOfValue(const Value& v) */ bool js::EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val, - HandleObject staticWith) + Handle staticWith) { - MOZ_ASSERT(staticWith->is()); RootedObject obj(cx); if (val.isObject()) { obj = &val.toObject(); @@ -1494,6 +1493,9 @@ class ReservedRooted : public ReservedRootedBase operator Rooted&() { return *savedRoot; } MutableHandle operator&() { return &*savedRoot; } + template + Handle as() { return savedRoot->template as(); } + DECLARE_NONPOINTER_ACCESSOR_METHODS(savedRoot->get()) DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(savedRoot->get()) DECLARE_POINTER_CONSTREF_OPS(T) @@ -1873,7 +1875,7 @@ CASE(JSOP_ENTERWITH) REGS.sp--; ReservedRooted staticWith(&rootObject0, script->getObject(REGS.pc)); - if (!EnterWithOperation(cx, REGS.fp(), val, staticWith)) + if (!EnterWithOperation(cx, REGS.fp(), val, staticWith.as())) goto error; } END_CASE(JSOP_ENTERWITH) diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 7fef263104f..8185d160f19 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -21,6 +21,7 @@ namespace js { class ScopeIter; +class StaticWithScope; /* * For a given |call|, convert null/undefined |this| into the global object for @@ -428,8 +429,8 @@ unsigned GetInitDataPropAttrs(JSOp op); bool -EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val, HandleObject staticWith); - +EnterWithOperation(JSContext* cx, AbstractFramePtr frame, HandleValue val, + Handle staticWith); bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, HandleValue idval, diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 8ae890c24ce..1160622a4cd 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -84,45 +84,39 @@ template inline void StaticScopeIter::operator++(int) { - if (obj->template is()) { - obj = obj->template as().enclosingScope(); - } else if (obj->template is()) { - obj = obj->template as().enclosingScope(); - } else if (obj->template is()) { - obj = obj->template as().enclosingScope(); - } else if (obj->template is()) { - obj = obj->template as().enclosingScope(); - } else if (onNamedLambda || !obj->template as().isNamedLambda()) { + if (!scope->template is()) { + scope = scope->enclosingScope(); + } else if (onNamedLambda || !scope->template as().isNamedLambda()) { onNamedLambda = false; - obj = obj->template as().enclosingScope(); + scope = scope->enclosingScope(); } else { onNamedLambda = true; } - MOZ_ASSERT_IF(obj, IsStaticScope(obj)); - MOZ_ASSERT_IF(onNamedLambda, obj->template is()); + MOZ_ASSERT_IF(scope, IsStaticScope(scope)); + MOZ_ASSERT_IF(onNamedLambda, scope->template is()); } template inline bool StaticScopeIter::hasSyntacticDynamicScopeObject() const { - if (obj->template is()) { - JSFunction& fun = obj->template as().function(); + if (scope->template is()) { + JSFunction& fun = scope->template as().function(); if (fun.isBeingParsed()) return fun.functionBox()->needsCallObject(); return fun.needsCallObject(); } - if (obj->template is()) + if (scope->template is()) return true; - if (obj->template is()) { - return obj->template as().needsClone() || - obj->template as().isGlobal(); + if (scope->template is()) { + return scope->template as().needsClone() || + scope->template as().isGlobal(); } - if (obj->template is()) + if (scope->template is()) return true; - if (obj->template is()) - return obj->template as().isStrict(); - MOZ_ASSERT(obj->template is()); + if (scope->template is()) + return scope->template as().isStrict(); + MOZ_ASSERT(scope->template is()); return false; } @@ -145,17 +139,17 @@ StaticScopeIter::type() const { if (onNamedLambda) return NamedLambda; - if (obj->template is()) + if (scope->template is()) return Block; - if (obj->template is()) + if (scope->template is()) return Module; - if (obj->template is()) + if (scope->template is()) return With; - if (obj->template is()) + if (scope->template is()) return Eval; - if (obj->template is()) + if (scope->template is()) return NonSyntactic; - MOZ_ASSERT(obj->template is()); + MOZ_ASSERT(scope->template is()); return Function; } @@ -164,7 +158,7 @@ inline StaticBlockScope& StaticScopeIter::block() const { MOZ_ASSERT(type() == Block); - return obj->template as(); + return scope->template as(); } template @@ -172,7 +166,7 @@ inline StaticWithScope& StaticScopeIter::staticWith() const { MOZ_ASSERT(type() == With); - return obj->template as(); + return scope->template as(); } template @@ -180,7 +174,7 @@ inline StaticEvalScope& StaticScopeIter::eval() const { MOZ_ASSERT(type() == Eval); - return obj->template as(); + return scope->template as(); } template @@ -188,7 +182,7 @@ inline StaticNonSyntacticScope& StaticScopeIter::nonSyntactic() const { MOZ_ASSERT(type() == NonSyntactic); - return obj->template as(); + return scope->template as(); } template @@ -196,7 +190,7 @@ inline JSScript* StaticScopeIter::funScript() const { MOZ_ASSERT(type() == Function); - return obj->template as().function().nonLazyScript(); + return scope->template as().function().nonLazyScript(); } template @@ -204,7 +198,7 @@ inline StaticFunctionScope& StaticScopeIter::fun() const { MOZ_ASSERT(type() == Function); - return obj->template as(); + return scope->template as(); } template @@ -222,7 +216,7 @@ inline StaticModuleScope& StaticScopeIter::module() const { MOZ_ASSERT(type() == Module); - return obj->template as(); + return scope->template as(); } } /* namespace js */ diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index ca0d60743ed..06e38cf0a0b 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -189,7 +189,7 @@ StaticWithScope::create(ExclusiveContext* cx) template bool -js::XDRStaticWithScope(XDRState* xdr, HandleObject enclosingScope, +js::XDRStaticWithScope(XDRState* xdr, Handle enclosingScope, MutableHandle objp) { if (mode == XDR_DECODE) { @@ -208,10 +208,12 @@ js::XDRStaticWithScope(XDRState* xdr, HandleObject enclosingScope, } template bool -js::XDRStaticWithScope(XDRState*, HandleObject, MutableHandle); +js::XDRStaticWithScope(XDRState*, Handle, + MutableHandle); template bool -js::XDRStaticWithScope(XDRState*, HandleObject, MutableHandle); +js::XDRStaticWithScope(XDRState*, Handle, + MutableHandle); /*****************************************************************************/ @@ -775,8 +777,9 @@ DeclEnvObject::create(JSContext* cx, HandleObject enclosing, HandleFunction call return obj; } -static JSObject* -CloneStaticWithScope(JSContext* cx, HandleObject enclosingScope, Handle srcWith) +static StaticWithScope* +CloneStaticWithScope(JSContext* cx, Handle enclosingScope, + Handle srcWith) { Rooted clone(cx, StaticWithScope::create(cx)); if (!clone) @@ -789,10 +792,8 @@ CloneStaticWithScope(JSContext* cx, HandleObject enclosingScope, Handle staticWith, WithKind kind) { - MOZ_ASSERT(staticWith->is()); - Rooted proto(cx, TaggedProto(staticWith)); Rooted obj(cx); obj = NewObjectWithGivenTaggedProto(cx, proto, GenericObject, @@ -1048,10 +1049,10 @@ ClonedBlockObject::createGlobal(JSContext* cx, Handle global) } /* static */ ClonedBlockObject* -ClonedBlockObject::createNonSyntactic(JSContext* cx, HandleObject enclosingStatic, +ClonedBlockObject::createNonSyntactic(JSContext* cx, + Handle enclosingStatic, HandleObject enclosingScope) { - MOZ_ASSERT(enclosingStatic->is()); MOZ_ASSERT(!IsSyntacticScope(enclosingScope)); Rooted staticLexical(cx, StaticBlockScope::create(cx)); @@ -1170,7 +1171,7 @@ const Class ClonedBlockObject::class_ = { template bool -js::XDRStaticBlockScope(XDRState* xdr, HandleObject enclosingScope, +js::XDRStaticBlockScope(XDRState* xdr, Handle enclosingScope, MutableHandle objp) { /* NB: Keep this in sync with CloneStaticBlockScope. */ @@ -1276,13 +1277,16 @@ js::XDRStaticBlockScope(XDRState* xdr, HandleObject enclosingScope, } template bool -js::XDRStaticBlockScope(XDRState*, HandleObject, MutableHandle); +js::XDRStaticBlockScope(XDRState*, Handle, + MutableHandle); template bool -js::XDRStaticBlockScope(XDRState*, HandleObject, MutableHandle); +js::XDRStaticBlockScope(XDRState*, Handle, + MutableHandle); -static JSObject* -CloneStaticBlockScope(JSContext* cx, HandleObject enclosingScope, Handle srcBlock) +static StaticBlockScope* +CloneStaticBlockScope(JSContext* cx, Handle enclosingScope, + Handle srcBlock) { /* NB: Keep this in sync with XDRStaticBlockScope. */ @@ -1323,16 +1327,16 @@ CloneStaticBlockScope(JSContext* cx, HandleObject enclosingScope, Handle enclosingScope, Handle srcBlock) { if (srcBlock->is()) { - Rooted blockScope(cx, &srcBlock->as()); - return CloneStaticBlockScope(cx, enclosingScope, blockScope); + return CloneStaticBlockScope(cx, enclosingScope, + HandleObject(srcBlock).as()); } else { - Rooted withScope(cx, &srcBlock->as()); - return CloneStaticWithScope(cx, enclosingScope, withScope); + return CloneStaticWithScope(cx, enclosingScope, + HandleObject(srcBlock).as()); } } @@ -1458,7 +1462,7 @@ ScopeIter::ScopeIter(JSContext* cx, const ScopeIter& si MOZ_GUARD_OBJECT_NOTIFIER_INIT; } -ScopeIter::ScopeIter(JSContext* cx, JSObject* scope, JSObject* staticScope +ScopeIter::ScopeIter(JSContext* cx, JSObject* scope, StaticScope* staticScope MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) : ssi_(cx, staticScope), scope_(cx, scope), @@ -1614,7 +1618,7 @@ ScopeIter::scope() const return scope_->as(); } -JSObject* +StaticScope* ScopeIter::maybeStaticScope() const { if (ssi_.done()) @@ -1622,17 +1626,12 @@ ScopeIter::maybeStaticScope() const switch (ssi_.type()) { case StaticScopeIter::Function: - return &fun(); case StaticScopeIter::Module: - return &module(); case StaticScopeIter::Block: - return &staticBlock(); case StaticScopeIter::With: - return &staticWith(); case StaticScopeIter::Eval: - return &staticEval(); case StaticScopeIter::NonSyntactic: - return &staticNonSyntactic(); + return ssi_.staticScope(); case StaticScopeIter::NamedLambda: MOZ_CRASH("named lambda static scopes should have been skipped"); default: @@ -3161,7 +3160,7 @@ js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain, // Construct With object wrappers for the things on this scope // chain and use the result as the thing to scope the function to. Rooted staticWith(cx); - RootedObject staticEnclosingScope(cx); + Rooted staticEnclosingScope(cx); Rooted dynamicWith(cx); RootedObject dynamicEnclosingScope(cx, dynamicTerminatingScope); for (size_t i = scopeChain.length(); i > 0; ) { @@ -3183,7 +3182,7 @@ js::CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain, } bool -js::HasNonSyntacticStaticScopeChain(JSObject* staticScope) +js::HasNonSyntacticStaticScopeChain(StaticScope* staticScope) { for (StaticScopeIter ssi(staticScope); !ssi.done(); ssi++) { // If we hit a function scope, we can short circuit the logic, as @@ -3197,7 +3196,7 @@ js::HasNonSyntacticStaticScopeChain(JSObject* staticScope) } uint32_t -js::StaticScopeChainLength(JSObject* staticScope) +js::StaticScopeChainLength(StaticScope* staticScope) { uint32_t length = 0; for (StaticScopeIter ssi(staticScope); !ssi.done(); ssi++) @@ -3418,7 +3417,7 @@ js::DumpStaticScopeChain(JSScript* script) } void -js::DumpStaticScopeChain(JSObject* staticScope) +js::DumpStaticScopeChain(StaticScope* staticScope) { for (StaticScopeIter ssi(staticScope); !ssi.done(); ssi++) { switch (ssi.type()) { diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 256d212d5d6..8ea78d5f373 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -82,13 +82,11 @@ class StaticScope : public NativeObject static const uint32_t ENCLOSING_SCOPE_SLOT = 0; static const unsigned RESERVED_SLOTS = ENCLOSING_SCOPE_SLOT + 1; - inline JSObject* enclosingScope() const { - return getFixedSlot(ENCLOSING_SCOPE_SLOT).toObjectOrNull(); - } + inline StaticScope* enclosingScope() const; - void initEnclosingScope(JSObject* obj) { + void initEnclosingScope(StaticScope* scope) { MOZ_ASSERT(getReservedSlot(ENCLOSING_SCOPE_SLOT).isUndefined()); - setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(obj)); + setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(scope)); } void setEnclosingScope(JSObject* obj); @@ -109,7 +107,7 @@ class NestedStaticScope : public StaticScope * called separately in the emitter. 'reset' is just for asserting * stackiness. */ - void initEnclosingScopeFromParser(JSObject* prev) { + void initEnclosingScopeFromParser(StaticScope* prev) { setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(prev)); } @@ -163,11 +161,6 @@ class StaticBlockScope : public NestedStaticScope */ bool isExtensible() const; - /* See StaticScopeIter comment. */ - JSObject* enclosingStaticScope() const { - return getFixedSlot(ENCLOSING_SCOPE_SLOT).toObjectOrNull(); - } - /* * Return the index (in the range [0, numVariables()) corresponding to the * given shape of a block object. @@ -353,7 +346,7 @@ class StaticWithScope : public NestedStaticScope template bool -XDRStaticWithScope(XDRState* xdr, HandleObject enclosingScope, +XDRStaticWithScope(XDRState* xdr, Handle enclosingScope, MutableHandle objp); /* @@ -371,10 +364,6 @@ class StaticEvalScope : public StaticScope static StaticEvalScope* create(JSContext* cx, HandleObject enclosing); - JSObject* enclosingScopeForStaticScopeIter() { - return getReservedSlot(ENCLOSING_SCOPE_SLOT).toObjectOrNull(); - } - void setStrict() { setReservedSlot(STRICT_SLOT, BooleanValue(true)); } @@ -500,16 +489,12 @@ class StaticNonSyntacticScope : public StaticScope static const Class class_; static StaticNonSyntacticScope* create(JSContext* cx, HandleObject enclosing); - - JSObject* enclosingScopeForStaticScopeIter() { - return getReservedSlot(ENCLOSING_SCOPE_SLOT).toObjectOrNull(); - } }; template class StaticScopeIter { - typename MaybeRooted::RootType obj; + typename MaybeRooted::RootType scope; bool onNamedLambda; static bool IsStaticScope(JSObject* obj) { @@ -522,42 +507,42 @@ class StaticScopeIter } public: - StaticScopeIter(ExclusiveContext* cx, JSObject* obj) - : obj(cx, obj), onNamedLambda(false) + StaticScopeIter(ExclusiveContext* cx, StaticScope* scope) + : scope(cx, scope), onNamedLambda(false) { static_assert(allowGC == CanGC, "the context-accepting constructor should only be used " "in CanGC code"); - MOZ_ASSERT_IF(obj, IsStaticScope(obj)); + MOZ_ASSERT_IF(scope, IsStaticScope(scope)); } StaticScopeIter(ExclusiveContext* cx, const StaticScopeIter& ssi) - : obj(cx, ssi.obj), onNamedLambda(ssi.onNamedLambda) + : scope(cx, ssi.scope), onNamedLambda(ssi.onNamedLambda) { JS_STATIC_ASSERT(allowGC == CanGC); } - explicit StaticScopeIter(JSObject* obj) - : obj((ExclusiveContext*) nullptr, obj), onNamedLambda(false) + explicit StaticScopeIter(StaticScope* scope) + : scope((ExclusiveContext*) nullptr, scope), onNamedLambda(false) { static_assert(allowGC == NoGC, "the constructor not taking a context should only be " "used in NoGC code"); - MOZ_ASSERT_IF(obj, IsStaticScope(obj)); + MOZ_ASSERT_IF(scope, IsStaticScope(scope)); } explicit StaticScopeIter(const StaticScopeIter& ssi) - : obj((ExclusiveContext*) nullptr, ssi.obj), onNamedLambda(ssi.onNamedLambda) + : scope((ExclusiveContext*) nullptr, ssi.scope), onNamedLambda(ssi.onNamedLambda) { static_assert(allowGC == NoGC, "the constructor not taking a context should only be " "used in NoGC code"); } - bool done() const { return !obj; } + bool done() const { return !scope; } void operator++(int); - JSObject* staticScope() const { MOZ_ASSERT(!done()); return obj; } + StaticScope* staticScope() const { MOZ_ASSERT(!done()); return scope; } // Return whether this static scope will have a syntactic scope (i.e. a // ScopeObject that isn't a non-syntactic With or @@ -921,8 +906,8 @@ class DynamicWithObject : public NestedScopeObject }; static DynamicWithObject* - create(JSContext* cx, HandleObject object, HandleObject enclosing, HandleObject staticWith, - WithKind kind = SyntacticWith); + create(JSContext* cx, HandleObject object, HandleObject enclosing, + Handle staticWith, WithKind kind = SyntacticWith); StaticWithScope& staticWith() const { return getProto()->as(); @@ -975,7 +960,8 @@ class ClonedBlockObject : public NestedScopeObject static ClonedBlockObject* createGlobal(JSContext* cx, Handle global); - static ClonedBlockObject* createNonSyntactic(JSContext* cx, HandleObject enclosingStatic, + static ClonedBlockObject* createNonSyntactic(JSContext* cx, + Handle enclosingStatic, HandleObject enclosingScope); static ClonedBlockObject* createHollowForDebug(JSContext* cx, @@ -1082,11 +1068,11 @@ class RuntimeLexicalErrorObject : public ScopeObject template bool -XDRStaticBlockScope(XDRState* xdr, HandleObject enclosingScope, +XDRStaticBlockScope(XDRState* xdr, Handle enclosingScope, MutableHandle objp); -extern JSObject* -CloneNestedScopeObject(JSContext* cx, HandleObject enclosingScope, +extern NestedStaticScope* +CloneNestedScopeObject(JSContext* cx, Handle enclosingScope, Handle src); @@ -1117,7 +1103,7 @@ class MOZ_RAII ScopeIter // Constructing from a dynamic scope, static scope pair. All scopes are // considered not to be withinInitialFrame, since no frame is given. - ScopeIter(JSContext* cx, JSObject* scope, JSObject* staticScope + ScopeIter(JSContext* cx, JSObject* scope, StaticScope* staticScope MOZ_GUARD_OBJECT_NOTIFIER_PARAM); // Constructing from a frame. Places the ScopeIter on the innermost scope @@ -1141,7 +1127,7 @@ class MOZ_RAII ScopeIter inline bool canHaveSyntacticScopeObject() const; ScopeObject& scope() const; - JSObject* maybeStaticScope() const; + StaticScope* maybeStaticScope() const; StaticBlockScope& staticBlock() const { return ssi_.block(); } StaticModuleScope& module() const { return ssi_.module(); } StaticWithScope& staticWith() const { return ssi_.staticWith(); } @@ -1173,7 +1159,7 @@ class MissingScopeKey friend class LiveScopeVal; AbstractFramePtr frame_; - JSObject* staticScope_; + StaticScope* staticScope_; public: explicit MissingScopeKey(const ScopeIter& si) @@ -1182,9 +1168,9 @@ class MissingScopeKey { } AbstractFramePtr frame() const { return frame_; } - JSObject* staticScope() const { return staticScope_; } + StaticScope* staticScope() const { return staticScope_; } - void updateStaticScope(JSObject* obj) { staticScope_ = obj; } + void updateStaticScope(StaticScope* scope) { staticScope_ = scope; } void updateFrame(AbstractFramePtr frame) { frame_ = frame; } // For use as hash policy. @@ -1206,7 +1192,7 @@ class LiveScopeVal friend class MissingScopeKey; AbstractFramePtr frame_; - RelocatablePtrObject staticScope_; + RelocatablePtr staticScope_; static void staticAsserts(); @@ -1217,7 +1203,7 @@ class LiveScopeVal { } AbstractFramePtr frame() const { return frame_; } - JSObject* staticScope() const { return staticScope_; } + StaticScope* staticScope() const { return staticScope_; } void updateFrame(AbstractFramePtr frame) { frame_ = frame; } @@ -1492,6 +1478,13 @@ IsGlobalLexicalScope(JSObject* scope) return scope->is() && scope->as().isGlobal(); } +inline js::StaticScope* +js::StaticScope::enclosingScope() const +{ + JSObject *obj = getFixedSlot(ENCLOSING_SCOPE_SLOT).toObjectOrNull(); + return obj ? &obj->as() : nullptr; +} + inline NestedStaticScope* NestedStaticScope::enclosingNestedScope() const { @@ -1608,8 +1601,8 @@ CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain, HandleObject dynamicTerminatingScope, MutableHandleObject dynamicScopeObj); -bool HasNonSyntacticStaticScopeChain(JSObject* staticScope); -uint32_t StaticScopeChainLength(JSObject* staticScope); +bool HasNonSyntacticStaticScopeChain(StaticScope* staticScope); +uint32_t StaticScopeChainLength(StaticScope* staticScope); ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script); @@ -1631,7 +1624,7 @@ bool CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script, #ifdef DEBUG void DumpStaticScopeChain(JSScript* script); -void DumpStaticScopeChain(JSObject* staticScope); +void DumpStaticScopeChain(StaticScope* staticScope); bool AnalyzeEntrainedVariables(JSContext* cx, HandleScript script); #endif diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 4d0acb9d5ae..a353a124c63 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2225,9 +2225,10 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject) : selfHostedFunction->getAllocKind(); MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, cx->global())); Rooted globalLexical(cx, &cx->global()->lexicalScope()); - RootedObject staticGlobalLexical(cx, &globalLexical->staticBlock()); + Rooted staticGlobalLexical(cx, &globalLexical->staticBlock()); clone = CloneFunctionAndScript(cx, selfHostedFunction, globalLexical, staticGlobalLexical, kind); + // To be able to re-lazify the cloned function, its name in the // self-hosting compartment has to be stored on the clone. if (clone && hasName) { diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 76fc0217c86..5209fe71acd 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -105,7 +105,7 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject* { #ifdef DEBUG RootedObject originalScope(cx, scope); - RootedObject enclosingScope(cx, script->enclosingStaticScope()); + Rooted enclosingScope(cx, script->enclosingStaticScope()); for (StaticScopeIter i(enclosingScope); !i.done(); i++) { if (i.type() == StaticScopeIter::NonSyntactic) { while (scope->is() || diff --git a/js/src/vm/Xdr.cpp b/js/src/vm/Xdr.cpp index f648c4318d5..bb49a5420fd 100644 --- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -118,7 +118,7 @@ XDRState::codeFunction(MutableHandleFunction objp) if (!VersionCheck(this)) return false; - RootedObject staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock()); + Rooted staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock()); return XDRInterpretedFunction(this, staticLexical, nullptr, objp); } @@ -132,7 +132,7 @@ XDRState::codeScript(MutableHandleScript scriptp) if (!VersionCheck(this)) return false; - RootedObject staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock()); + Rooted staticLexical(cx(), &cx()->global()->lexicalScope().staticBlock()); if (!XDRScript(this, staticLexical, nullptr, nullptr, scriptp)) return false; From 10b7f8f1c8f5554bd1ffbe4e78a24becf42a398c Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 13 Nov 2015 07:14:10 -0600 Subject: [PATCH 133/160] Bug 1221144 - Part 9: A few more JSObject* -> StaticScope* changes. r=shu. --- js/src/builtin/Eval.cpp | 4 ++-- js/src/jsgc.cpp | 2 +- js/src/vm/ScopeObject.cpp | 18 +++++++++--------- js/src/vm/ScopeObject.h | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp index 5cc0983e6f1..b84a9aee4b0 100644 --- a/js/src/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -288,7 +288,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame if (maybeScript && maybeScript->scriptSource()->introducerFilename()) introducerFilename = maybeScript->scriptSource()->introducerFilename(); - RootedObject enclosing(cx); + Rooted enclosing(cx); if (evalType == DIRECT_EVAL) enclosing = callerScript->innermostStaticScope(pc); else @@ -374,7 +374,7 @@ js::DirectEvalStringFromIon(JSContext* cx, if (maybeScript && maybeScript->scriptSource()->introducerFilename()) introducerFilename = maybeScript->scriptSource()->introducerFilename(); - RootedObject enclosing(cx, callerScript->innermostStaticScope(pc)); + Rooted enclosing(cx, callerScript->innermostStaticScope(pc)); Rooted staticScope(cx, StaticEvalScope::create(cx, enclosing)); if (!staticScope) return false; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 19add8094e3..d8c26b313ca 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -6832,7 +6832,7 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target) // Get the static global lexical scope of the target compartment. Static // scopes need to be fixed up below. - RootedObject targetStaticGlobalLexicalScope(rt); + Rooted targetStaticGlobalLexicalScope(rt); targetStaticGlobalLexicalScope = &target->maybeGlobal()->lexicalScope().staticBlock(); for (ZoneCellIter iter(source->zone(), AllocKind::SCRIPT); !iter.done(); iter.next()) { diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 06e38cf0a0b..2b0fc61648d 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -39,10 +39,10 @@ typedef MutableHandle MutableHandleArgumentsObject; /*** Static scope objects ************************************************************************/ void -StaticScope::setEnclosingScope(JSObject* obj) +StaticScope::setEnclosingScope(StaticScope* scope) { - MOZ_ASSERT_IF(obj->is(), obj->isDelegate()); - setFixedSlot(ENCLOSING_SCOPE_SLOT, ObjectValue(*obj)); + MOZ_ASSERT_IF(scope->is(), scope->isDelegate()); + setFixedSlot(ENCLOSING_SCOPE_SLOT, ObjectValue(*scope)); } bool @@ -916,16 +916,16 @@ const Class DynamicWithObject::class_ = { }; /* static */ StaticEvalScope* -StaticEvalScope::create(JSContext* cx, HandleObject enclosing) +StaticEvalScope::create(JSContext* cx, Handle enclosing) { - StaticEvalScope* obj = + StaticEvalScope* scope = NewObjectWithNullTaggedProto(cx, TenuredObject, BaseShape::DELEGATE); - if (!obj) + if (!scope) return nullptr; - obj->setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(enclosing)); - obj->setReservedSlot(STRICT_SLOT, BooleanValue(false)); - return obj; + scope->initEnclosingScope(enclosing); + scope->setReservedSlot(STRICT_SLOT, BooleanValue(false)); + return scope; } const Class StaticEvalScope::class_ = { diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 8ea78d5f373..27fd8fd1f2e 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -89,7 +89,7 @@ class StaticScope : public NativeObject setReservedSlot(ENCLOSING_SCOPE_SLOT, ObjectOrNullValue(scope)); } - void setEnclosingScope(JSObject* obj); + void setEnclosingScope(StaticScope* obj); }; class NestedStaticScope : public StaticScope @@ -362,7 +362,7 @@ class StaticEvalScope : public StaticScope public: static const Class class_; - static StaticEvalScope* create(JSContext* cx, HandleObject enclosing); + static StaticEvalScope* create(JSContext* cx, Handle enclosing); void setStrict() { setReservedSlot(STRICT_SLOT, BooleanValue(true)); From 03db686e20c9a13ced9b55a277f2c66174b76789 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 12 Nov 2015 14:17:18 -0600 Subject: [PATCH 134/160] Bug 1221144 - Part 10: Delete an obsolete comment. r=shu. --- js/src/frontend/BytecodeEmitter.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 1fd782b8ab9..d6f472e43cc 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -6438,8 +6438,6 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto) insideNonGlobalEval, lineNum, emitterMode); if (!bce2.init()) return false; - - /* We measured the max scope depth when we parsed the function. */ if (!bce2.emitFunctionScript(pn->pn_body)) return false; From f56e8cc8ea61f5cc9106297d5d84b22e6633f236 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 12 Nov 2015 15:29:38 -0600 Subject: [PATCH 135/160] Bug 1221144 - Part 12: Remove StaticScopeIter<>::IsStaticScope. r=shu. (Jeff beat me to the code cleanup that was part 11.) JSObject::is() now means the same thing. We retain a few assertions that were using IsStaticScope(), even though the work in this bug makes it unlikely these assertions will ever fail again. --- js/src/vm/ScopeObject-inl.h | 2 +- js/src/vm/ScopeObject.h | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/js/src/vm/ScopeObject-inl.h b/js/src/vm/ScopeObject-inl.h index 1160622a4cd..3b523db45fa 100644 --- a/js/src/vm/ScopeObject-inl.h +++ b/js/src/vm/ScopeObject-inl.h @@ -92,7 +92,7 @@ StaticScopeIter::operator++(int) } else { onNamedLambda = true; } - MOZ_ASSERT_IF(scope, IsStaticScope(scope)); + MOZ_ASSERT_IF(scope, scope->template is()); MOZ_ASSERT_IF(onNamedLambda, scope->template is()); } diff --git a/js/src/vm/ScopeObject.h b/js/src/vm/ScopeObject.h index 27fd8fd1f2e..0de7f2f0c14 100644 --- a/js/src/vm/ScopeObject.h +++ b/js/src/vm/ScopeObject.h @@ -497,15 +497,6 @@ class StaticScopeIter typename MaybeRooted::RootType scope; bool onNamedLambda; - static bool IsStaticScope(JSObject* obj) { - return obj->is() || - obj->is() || - obj->is() || - obj->is() || - obj->is() || - obj->is(); - } - public: StaticScopeIter(ExclusiveContext* cx, StaticScope* scope) : scope(cx, scope), onNamedLambda(false) @@ -513,7 +504,7 @@ class StaticScopeIter static_assert(allowGC == CanGC, "the context-accepting constructor should only be used " "in CanGC code"); - MOZ_ASSERT_IF(scope, IsStaticScope(scope)); + MOZ_ASSERT_IF(scope, scope->is()); } StaticScopeIter(ExclusiveContext* cx, const StaticScopeIter& ssi) @@ -528,7 +519,7 @@ class StaticScopeIter static_assert(allowGC == NoGC, "the constructor not taking a context should only be " "used in NoGC code"); - MOZ_ASSERT_IF(scope, IsStaticScope(scope)); + MOZ_ASSERT_IF(scope, scope->is()); } explicit StaticScopeIter(const StaticScopeIter& ssi) From 73a31f9606bd038bf6b380750cd1b151b507490d Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 12 Nov 2015 15:31:54 -0600 Subject: [PATCH 136/160] Bug 1221144 - Part 13: Change DumpStaticScopeChain to include a function scope when available, on the theory that more information is better. r=shu. --- js/src/shell/js.cpp | 2 ++ js/src/vm/ScopeObject.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 23ec93cd058..475bd9ae024 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4669,6 +4669,8 @@ DumpStaticScopeChain(JSContext* cx, unsigned argc, Value* vp) return false; } script = fun->getOrCreateScript(cx); + if (!script) + return false; } else { script = obj->as().script(); } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 2b0fc61648d..4ae250452ab 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -3413,7 +3413,7 @@ js::CheckEvalDeclarationConflicts(JSContext* cx, HandleScript script, void js::DumpStaticScopeChain(JSScript* script) { - DumpStaticScopeChain(script->enclosingStaticScope()); + DumpStaticScopeChain(script->staticScope()); } void From 23dddeef62fd79b46f188e0b5eafc2b8337c3db1 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 12 Nov 2015 15:42:31 -0600 Subject: [PATCH 137/160] Bug 1221144 - Part 14: Handlify scope arguments to methods around FunctionBox creation. r=shu. --- js/src/frontend/Parser.cpp | 7 +++---- js/src/frontend/Parser.h | 2 +- js/src/frontend/SharedContext.h | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 650b9aba335..93d1dccf781 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -784,11 +784,10 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct } bool -FunctionBox::initStaticScope(StaticScope* enclosingStaticScope) +FunctionBox::initStaticScope(Handle enclosingScope) { RootedFunction fun(context, function()); - Rooted enclosing(context, enclosingStaticScope); - staticScope_ = StaticFunctionScope::create(context, fun, enclosing); + staticScope_ = StaticFunctionScope::create(context, fun, enclosingScope); return staticScope_ != nullptr; } @@ -798,7 +797,7 @@ Parser::newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives inheritedDirectives, GeneratorKind generatorKind, - StaticScope* enclosingStaticScope) + Handle enclosingStaticScope) { MOZ_ASSERT_IF(outerpc, enclosingStaticScope == outerpc->innermostStaticScope()); MOZ_ASSERT(fun); diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index f7f864bee4d..abfad067a28 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -505,7 +505,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter ObjectBox* newObjectBox(JSObject* obj); FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext* outerpc, Directives directives, GeneratorKind generatorKind, - StaticScope* enclosingStaticScope); + Handle enclosingStaticScope); // Use when the funbox is the outermost. FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives, diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index c9f9d308af4..dd2ad6dcd9a 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -338,7 +338,7 @@ class FunctionBox : public ObjectBox, public SharedContext ParseContext* pc, Directives directives, bool extraWarnings, GeneratorKind generatorKind); - bool initStaticScope(StaticScope* enclosingStaticScope); + bool initStaticScope(Handle enclosingScope); ObjectBox* toObjectBox() override { return this; } JSFunction* function() const { return &object->as(); } From c3e167698511335130ae03e945b92ecf2a7d41f3 Mon Sep 17 00:00:00 2001 From: Randall Barker Date: Wed, 3 Feb 2016 11:54:43 -0800 Subject: [PATCH 138/160] Bug 1245285 - part 1, Remove unused mRepaintInterval from AsyncPanZoomAnimation r=botond --- gfx/layers/apz/src/AsyncPanZoomAnimation.h | 10 +--------- gfx/layers/apz/src/AsyncPanZoomController.cpp | 13 ++++--------- gfx/layers/apz/src/WheelScrollAnimation.cpp | 3 +-- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomAnimation.h b/gfx/layers/apz/src/AsyncPanZoomAnimation.h index 33e7d1b10d1..9b0221ceb26 100644 --- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h +++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h @@ -23,8 +23,7 @@ class AsyncPanZoomAnimation { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation) public: - explicit AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval) - : mRepaintInterval(aRepaintInterval) + explicit AsyncPanZoomAnimation() { } virtual bool DoSample(FrameMetrics& aFrameMetrics, @@ -50,13 +49,6 @@ public: return Move(mDeferredTasks); } - /** - * Specifies how frequently (at most) we want to do repaints during the - * animation sequence. TimeDuration::Forever() will cause it to only repaint - * at the end of the animation. - */ - TimeDuration mRepaintInterval; - public: virtual WheelScrollAnimation* AsWheelScrollAnimation() { return nullptr; diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 9bcc9473f5b..ff3c93d3c18 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -443,8 +443,7 @@ public: const RefPtr& aOverscrollHandoffChain, bool aApplyAcceleration, const RefPtr& aScrolledApzc) - : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval())) - , mApzc(aApzc) + : mApzc(aApzc) , mOverscrollHandoffChain(aOverscrollHandoffChain) , mScrolledApzc(aScrolledApzc) { @@ -611,8 +610,7 @@ class ZoomAnimation: public AsyncPanZoomAnimation { public: ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale2D aStartZoom, CSSPoint aEndOffset, CSSToParentLayerScale2D aEndZoom) - : AsyncPanZoomAnimation(TimeDuration::Forever()) - , mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) + : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) , mStartOffset(aStartOffset) , mStartZoom(aStartZoom) , mEndOffset(aEndOffset) @@ -670,8 +668,7 @@ private: class OverscrollAnimation: public AsyncPanZoomAnimation { public: explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) - : AsyncPanZoomAnimation(TimeDuration::Forever()) - , mApzc(aApzc) + : mApzc(aApzc) { mApzc.mX.StartOverscrollAnimation(aVelocity.x); mApzc.mY.StartOverscrollAnimation(aVelocity.y); @@ -713,9 +710,7 @@ public: const nsPoint &aInitialVelocity, const nsPoint& aDestination, double aSpringConstant, double aDampingRatio) - : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds( - gfxPrefs::APZSmoothScrollRepaintInterval())) - , mApzc(aApzc) + : mApzc(aApzc) , mXAxisModel(aInitialPosition.x, aDestination.x, aInitialVelocity.x, aSpringConstant, aDampingRatio) , mYAxisModel(aInitialPosition.y, aDestination.y, aInitialVelocity.y, diff --git a/gfx/layers/apz/src/WheelScrollAnimation.cpp b/gfx/layers/apz/src/WheelScrollAnimation.cpp index d4f857dc779..355536b8d18 100644 --- a/gfx/layers/apz/src/WheelScrollAnimation.cpp +++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp @@ -14,8 +14,7 @@ namespace mozilla { namespace layers { WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition) - : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZSmoothScrollRepaintInterval())) - , AsyncScrollBase(aInitialPosition) + : AsyncScrollBase(aInitialPosition) , mApzc(aApzc) , mFinalDestination(aInitialPosition) { From 1c0a14cf2b7d004ee0105556b3735ac7342bf6ab Mon Sep 17 00:00:00 2001 From: Randall Barker Date: Wed, 3 Feb 2016 12:30:55 -0800 Subject: [PATCH 139/160] Bug 1245285 - part 2, Prevent Zoom and Overscroll animations from repainting durring animation r=botond --- gfx/layers/apz/src/AsyncPanZoomAnimation.h | 5 ++++- gfx/layers/apz/src/AsyncPanZoomController.cpp | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomAnimation.h b/gfx/layers/apz/src/AsyncPanZoomAnimation.h index 9b0221ceb26..a2eebb68ac2 100644 --- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h +++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h @@ -49,11 +49,14 @@ public: return Move(mDeferredTasks); } -public: virtual WheelScrollAnimation* AsWheelScrollAnimation() { return nullptr; } + virtual bool WantsRepaints() { + return true; + } + protected: // Protected destructor, to discourage deletion outside of Release(): virtual ~AsyncPanZoomAnimation() diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index ff3c93d3c18..1f44da531df 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -647,6 +647,11 @@ public: return true; } + virtual bool WantsRepaints() override + { + return false; + } + private: TimeDuration mDuration; const TimeDuration mTotalDuration; @@ -698,6 +703,12 @@ public: } return true; } + + virtual bool WantsRepaints() override + { + return false; + } + private: AsyncPanZoomController& mApzc; }; @@ -2940,12 +2951,15 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, if (mAnimation) { bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta); + bool wantsRepaints = mAnimation->WantsRepaints(); *aOutDeferredTasks = mAnimation->TakeDeferredTasks(); if (!continueAnimation) { mAnimation = nullptr; SetState(NOTHING); } - RequestContentRepaint(); + if (wantsRepaints) { + RequestContentRepaint(); + } UpdateSharedCompositorFrameMetrics(); return true; } From d3c2e68d83a70d8dfd23bdf650f618d676e7e21c Mon Sep 17 00:00:00 2001 From: Randall Barker Date: Wed, 3 Feb 2016 13:47:47 -0800 Subject: [PATCH 140/160] Bug 1245285 - part 3, Remove unused repaint_interval prefs r=botond --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 14 -------------- gfx/thebes/gfxPrefs.h | 3 --- modules/libpref/init/all.js | 5 ----- 3 files changed, 22 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 1f44da531df..fb723fce17d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -214,11 +214,6 @@ using mozilla::gfx::PointTyped; * value of this pref, and (t1 - t0) is the amount of time, in milliseconds, * that has elapsed between the two samples. * - * \li\b apz.fling_repaint_interval - * Maximum amount of time flinging before sending a viewport change. This will - * asynchronously repaint the page.\n - * Units: milliseconds - * * \li\b apz.fling_stop_on_tap_threshold * When flinging, if the velocity is above this number, then a tap on the * screen will stop the fling without dispatching a tap to content. If the @@ -282,18 +277,9 @@ using mozilla::gfx::PointTyped; * Units: screen pixels (for distance) * screen pixels per millisecond (for velocity) * - * \li\b apz.pan_repaint_interval - * Maximum amount of time while panning before sending a viewport change. This - * will asynchronously repaint the page. It is also forced when panning stops. - * * \li\b apz.record_checkerboarding * Whether or not to record detailed info on checkerboarding events. * - * \li\b apz.smooth_scroll_repaint_interval - * Maximum amount of time doing a smooth scroll before sending a viewport - * change. This will asynchronously repaint the page.\n - * Units: milliseconds - * * \li\b apz.test.logging_enabled * Enable logging of APZ test data (see bug 961289). * diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 95af19c2485..a3f096fe76d 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -160,7 +160,6 @@ private: DECL_GFX_PREF(Once, "apz.fling_curve_function_y2", APZCurveFunctionY2, float, 1.0f); DECL_GFX_PREF(Live, "apz.fling_curve_threshold_inches_per_ms", APZCurveThreshold, float, -1.0f); DECL_GFX_PREF(Live, "apz.fling_friction", APZFlingFriction, float, 0.002f); - DECL_GFX_PREF(Live, "apz.fling_repaint_interval", APZFlingRepaintInterval, int32_t, 75); DECL_GFX_PREF(Live, "apz.fling_stop_on_tap_threshold", APZFlingStopOnTapThreshold, float, 0.05f); DECL_GFX_PREF(Live, "apz.fling_stopped_threshold", APZFlingStoppedThreshold, float, 0.01f); DECL_GFX_PREF(Live, "apz.highlight_checkerboarded_areas", APZHighlightCheckerboardedAreas, bool, false); @@ -175,10 +174,8 @@ private: DECL_GFX_PREF(Live, "apz.overscroll.stop_distance_threshold", APZOverscrollStopDistanceThreshold, float, 5.0f); DECL_GFX_PREF(Live, "apz.overscroll.stop_velocity_threshold", APZOverscrollStopVelocityThreshold, float, 0.01f); DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f); - DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250); DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false); DECL_GFX_PREF(Live, "apz.record_checkerboarding", APZRecordCheckerboarding, bool, false); - DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75); DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false); DECL_GFX_PREF(Live, "apz.touch_move_tolerance", APZTouchMoveTolerance, float, 0.0); DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index af4a08fe0ea..116ab8d811e 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -578,7 +578,6 @@ pref("apz.fling_curve_function_x2", "1.0"); pref("apz.fling_curve_function_y2", "1.0"); pref("apz.fling_curve_threshold_inches_per_ms", "-1.0"); pref("apz.fling_friction", "0.002"); -pref("apz.fling_repaint_interval", 16); pref("apz.fling_stop_on_tap_threshold", "0.05"); pref("apz.fling_stopped_threshold", "0.01"); pref("apz.highlight_checkerboarded_areas", false); @@ -593,7 +592,6 @@ pref("apz.overscroll.spring_stiffness", "0.0018"); pref("apz.overscroll.stop_distance_threshold", "5.0"); pref("apz.overscroll.stop_velocity_threshold", "0.01"); pref("apz.overscroll.stretch_factor", "0.35"); -pref("apz.pan_repaint_interval", 16); // Whether to print the APZC tree for debugging pref("apz.printtree", false); @@ -603,7 +601,6 @@ pref("apz.record_checkerboarding", true); #else pref("apz.record_checkerboarding", false); #endif -pref("apz.smooth_scroll_repaint_interval", 16); pref("apz.test.logging_enabled", false); pref("apz.touch_start_tolerance", "0.1"); pref("apz.touch_move_tolerance", "0.03"); @@ -621,8 +618,6 @@ pref("apz.zoom_animation_duration_ms", 250); // Mobile prefs pref("apz.allow_zooming", true); pref("apz.enlarge_displayport_when_clipped", true); -pref("apz.fling_repaint_interval", 75); -pref("apz.smooth_scroll_repaint_interval", 75); pref("apz.x_skate_size_multiplier", "1.25"); pref("apz.y_skate_size_multiplier", "1.5"); pref("apz.x_stationary_size_multiplier", "1.5"); From 3b6e1cd6a42487a2c44e444777d411e67b3d49e3 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Wed, 3 Feb 2016 17:38:12 -0800 Subject: [PATCH 141/160] Backed out 3 changesets (bug 1231784) for breaking 10.10 opt jetpack tests Backed out changeset 653df21ca861 (bug 1231784) Backed out changeset 0aac20bc3619 (bug 1231784) Backed out changeset edcbd7c0aa36 (bug 1231784) --- build/mobile/remoteautomation.py | 3 +- .../driver/marionette_driver/marionette.py | 5 +- .../{start_b2g.js => b2g_start_script.js} | 0 testing/mochitest/bootstrap.js | 84 ----------- testing/mochitest/browser-harness.xul | 2 +- testing/mochitest/browser-test-overlay.xul | 2 +- testing/mochitest/browser-test.js | 89 +++++++----- testing/mochitest/install.rdf | 6 +- testing/mochitest/jetpack-addon-harness.js | 9 +- testing/mochitest/jetpack-package-harness.js | 9 +- testing/mochitest/mochitest_options.py | 16 +-- testing/mochitest/moz.build | 7 +- testing/mochitest/runtests.py | 136 ++++++++---------- testing/mochitest/runtestsb2g.py | 22 ++- testing/mochitest/runtestsremote.py | 19 +-- testing/mochitest/start_desktop.js | 15 -- testing/profiles/prefs_general.js | 3 - .../test/browser/browser_select_confirm.js | 20 ++- toolkit/mozapps/update/tests/chrome/utils.js | 7 +- 19 files changed, 162 insertions(+), 292 deletions(-) rename testing/mochitest/{start_b2g.js => b2g_start_script.js} (100%) delete mode 100644 testing/mochitest/bootstrap.js delete mode 100644 testing/mochitest/start_desktop.js diff --git a/build/mobile/remoteautomation.py b/build/mobile/remoteautomation.py index b8940c02954..c402031b3ae 100644 --- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -7,7 +7,6 @@ import glob import time import re import os -import posixpath import tempfile import shutil import subprocess @@ -215,7 +214,7 @@ class RemoteAutomation(Automation): try: dumpDir = tempfile.mkdtemp() - remoteCrashDir = posixpath.join(self._remoteProfile, 'minidumps') + remoteCrashDir = self._remoteProfile + '/minidumps/' if not self._devicemanager.dirExists(remoteCrashDir): # If crash reporting is enabled (MOZ_CRASHREPORTER=1), the # minidumps directory is automatically created when Fennec diff --git a/testing/marionette/driver/marionette_driver/marionette.py b/testing/marionette/driver/marionette_driver/marionette.py index 0c7f66e94a6..3b60feb380f 100644 --- a/testing/marionette/driver/marionette_driver/marionette.py +++ b/testing/marionette/driver/marionette_driver/marionette.py @@ -1149,11 +1149,8 @@ class Marionette(object): self.host, self.port, self.socket_timeout) - - # Call wait_for_port() before attempting to connect in - # the event gecko hasn't started yet. - self.wait_for_port(timeout=timeout) self.protocol, _ = self.client.connect() + self.wait_for_port(timeout=timeout) body = {"capabilities": desired_capabilities, "sessionId": session_id} resp = self._send_message("newSession", body) diff --git a/testing/mochitest/start_b2g.js b/testing/mochitest/b2g_start_script.js similarity index 100% rename from testing/mochitest/start_b2g.js rename to testing/mochitest/b2g_start_script.js diff --git a/testing/mochitest/bootstrap.js b/testing/mochitest/bootstrap.js deleted file mode 100644 index b6111232cf2..00000000000 --- a/testing/mochitest/bootstrap.js +++ /dev/null @@ -1,84 +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/. */ - -const { utils: Cu, interfaces: Ci, classes: Cc } = Components; - -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -var WindowListener = { - // browser-test.js is only loaded into the first window. Setup that - // needs to happen in all navigator:browser windows should go here. - setupWindow: function(win) { - win.nativeConsole = win.console; - XPCOMUtils.defineLazyModuleGetter(win, "console", - "resource://gre/modules/Console.jsm"); - }, - - tearDownWindow: function(win) { - if (win.nativeConsole) { - win.console = win.nativeConsole; - win.nativeConsole = undefined; - } - }, - - onOpenWindow: function (win) { - win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); - - win.addEventListener("load", function listener() { - win.removeEventListener("load", listener, false); - if (win.document.documentElement.getAttribute("windowtype") == "navigator:browser") { - WindowListener.setupWindow(win); - } - }, false); - } -} - -function loadMochitest(e) { - let flavor = e.detail[0]; - let url = e.detail[1]; - - let win = Services.wm.getMostRecentWindow("navigator:browser"); - win.removeEventListener('mochitest-load', loadMochitest); - - // for mochitest-plain, navigating to the url is all we need - win.loadURI(url); - if (flavor == "mochitest") { - return; - } - - WindowListener.setupWindow(win); - Services.wm.addListener(WindowListener); - - let overlay; - if (flavor == "jetpack-addon") { - overlay = "chrome://mochikit/content/jetpack-addon-overlay.xul"; - } else if (flavor == "jetpack-package") { - overlay = "chrome://mochikit/content/jetpack-package-overlay.xul"; - } else { - overlay = "chrome://mochikit/content/browser-test-overlay.xul"; - } - - win.document.loadOverlay(overlay, null); -} - -function startup(data, reason) { - let win = Services.wm.getMostRecentWindow("navigator:browser"); - // wait for event fired from start_desktop.js containing the - // suite and url to load - win.addEventListener('mochitest-load', loadMochitest); -} - -function shutdown(data, reason) { - let windows = Services.wm.getEnumerator("navigator:browser"); - while (windows.hasMoreElements()) { - let win = windows.getNext().QueryInterface(Ci.nsIDOMWindow); - WindowListener.tearDownWindow(win); - } - - Services.wm.removeListener(WindowListener); -} - -function install(data, reason) {} -function uninstall(data, reason) {} diff --git a/testing/mochitest/browser-harness.xul b/testing/mochitest/browser-harness.xul index 53edaa552e6..a513b66cf09 100644 --- a/testing/mochitest/browser-harness.xul +++ b/testing/mochitest/browser-harness.xul @@ -251,7 +251,7 @@ waitForFocus(() => { // Focus the test window and start tests. waitForFocus(() => { - var Tester = new testWin.Tester(links, gDumper.structuredLogger, testsFinished); + var Tester = new testWin.Tester(links, gDumper, testsFinished); Tester.start(); }, testWin); }, window); diff --git a/testing/mochitest/browser-test-overlay.xul b/testing/mochitest/browser-test-overlay.xul index 2aaaf247f1b..4c5b71bdd40 100644 --- a/testing/mochitest/browser-test-overlay.xul +++ b/testing/mochitest/browser-test-overlay.xul @@ -7,7 +7,7 @@ + + + + + + +

    + +
    + + + +
    + + From e0559feff1df33d1f34afe13800d9f1054afde9c Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Wed, 3 Feb 2016 21:46:11 -0800 Subject: [PATCH 158/160] Back out 3 changesets (bug 1245285) for e10s failures in test_layerization.html Backed out changeset e0c8fb70a095 (bug 1245285) Backed out changeset a211643de3b6 (bug 1245285) Backed out changeset 41ea5de656a9 (bug 1245285) --- gfx/layers/apz/src/AsyncPanZoomAnimation.h | 15 ++++--- gfx/layers/apz/src/AsyncPanZoomController.cpp | 43 +++++++++++-------- gfx/layers/apz/src/WheelScrollAnimation.cpp | 3 +- gfx/thebes/gfxPrefs.h | 3 ++ modules/libpref/init/all.js | 5 +++ 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomAnimation.h b/gfx/layers/apz/src/AsyncPanZoomAnimation.h index a2eebb68ac2..33e7d1b10d1 100644 --- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h +++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h @@ -23,7 +23,8 @@ class AsyncPanZoomAnimation { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation) public: - explicit AsyncPanZoomAnimation() + explicit AsyncPanZoomAnimation(const TimeDuration& aRepaintInterval) + : mRepaintInterval(aRepaintInterval) { } virtual bool DoSample(FrameMetrics& aFrameMetrics, @@ -49,14 +50,18 @@ public: return Move(mDeferredTasks); } + /** + * Specifies how frequently (at most) we want to do repaints during the + * animation sequence. TimeDuration::Forever() will cause it to only repaint + * at the end of the animation. + */ + TimeDuration mRepaintInterval; + +public: virtual WheelScrollAnimation* AsWheelScrollAnimation() { return nullptr; } - virtual bool WantsRepaints() { - return true; - } - protected: // Protected destructor, to discourage deletion outside of Release(): virtual ~AsyncPanZoomAnimation() diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index fb723fce17d..9bcc9473f5b 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -214,6 +214,11 @@ using mozilla::gfx::PointTyped; * value of this pref, and (t1 - t0) is the amount of time, in milliseconds, * that has elapsed between the two samples. * + * \li\b apz.fling_repaint_interval + * Maximum amount of time flinging before sending a viewport change. This will + * asynchronously repaint the page.\n + * Units: milliseconds + * * \li\b apz.fling_stop_on_tap_threshold * When flinging, if the velocity is above this number, then a tap on the * screen will stop the fling without dispatching a tap to content. If the @@ -277,9 +282,18 @@ using mozilla::gfx::PointTyped; * Units: screen pixels (for distance) * screen pixels per millisecond (for velocity) * + * \li\b apz.pan_repaint_interval + * Maximum amount of time while panning before sending a viewport change. This + * will asynchronously repaint the page. It is also forced when panning stops. + * * \li\b apz.record_checkerboarding * Whether or not to record detailed info on checkerboarding events. * + * \li\b apz.smooth_scroll_repaint_interval + * Maximum amount of time doing a smooth scroll before sending a viewport + * change. This will asynchronously repaint the page.\n + * Units: milliseconds + * * \li\b apz.test.logging_enabled * Enable logging of APZ test data (see bug 961289). * @@ -429,7 +443,8 @@ public: const RefPtr& aOverscrollHandoffChain, bool aApplyAcceleration, const RefPtr& aScrolledApzc) - : mApzc(aApzc) + : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZFlingRepaintInterval())) + , mApzc(aApzc) , mOverscrollHandoffChain(aOverscrollHandoffChain) , mScrolledApzc(aScrolledApzc) { @@ -596,7 +611,8 @@ class ZoomAnimation: public AsyncPanZoomAnimation { public: ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale2D aStartZoom, CSSPoint aEndOffset, CSSToParentLayerScale2D aEndZoom) - : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) + : AsyncPanZoomAnimation(TimeDuration::Forever()) + , mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) , mStartOffset(aStartOffset) , mStartZoom(aStartZoom) , mEndOffset(aEndOffset) @@ -633,11 +649,6 @@ public: return true; } - virtual bool WantsRepaints() override - { - return false; - } - private: TimeDuration mDuration; const TimeDuration mTotalDuration; @@ -659,7 +670,8 @@ private: class OverscrollAnimation: public AsyncPanZoomAnimation { public: explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) - : mApzc(aApzc) + : AsyncPanZoomAnimation(TimeDuration::Forever()) + , mApzc(aApzc) { mApzc.mX.StartOverscrollAnimation(aVelocity.x); mApzc.mY.StartOverscrollAnimation(aVelocity.y); @@ -689,12 +701,6 @@ public: } return true; } - - virtual bool WantsRepaints() override - { - return false; - } - private: AsyncPanZoomController& mApzc; }; @@ -707,7 +713,9 @@ public: const nsPoint &aInitialVelocity, const nsPoint& aDestination, double aSpringConstant, double aDampingRatio) - : mApzc(aApzc) + : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds( + gfxPrefs::APZSmoothScrollRepaintInterval())) + , mApzc(aApzc) , mXAxisModel(aInitialPosition.x, aDestination.x, aInitialVelocity.x, aSpringConstant, aDampingRatio) , mYAxisModel(aInitialPosition.y, aDestination.y, aInitialVelocity.y, @@ -2937,15 +2945,12 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, if (mAnimation) { bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta); - bool wantsRepaints = mAnimation->WantsRepaints(); *aOutDeferredTasks = mAnimation->TakeDeferredTasks(); if (!continueAnimation) { mAnimation = nullptr; SetState(NOTHING); } - if (wantsRepaints) { - RequestContentRepaint(); - } + RequestContentRepaint(); UpdateSharedCompositorFrameMetrics(); return true; } diff --git a/gfx/layers/apz/src/WheelScrollAnimation.cpp b/gfx/layers/apz/src/WheelScrollAnimation.cpp index 355536b8d18..d4f857dc779 100644 --- a/gfx/layers/apz/src/WheelScrollAnimation.cpp +++ b/gfx/layers/apz/src/WheelScrollAnimation.cpp @@ -14,7 +14,8 @@ namespace mozilla { namespace layers { WheelScrollAnimation::WheelScrollAnimation(AsyncPanZoomController& aApzc, const nsPoint& aInitialPosition) - : AsyncScrollBase(aInitialPosition) + : AsyncPanZoomAnimation(TimeDuration::FromMilliseconds(gfxPrefs::APZSmoothScrollRepaintInterval())) + , AsyncScrollBase(aInitialPosition) , mApzc(aApzc) , mFinalDestination(aInitialPosition) { diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index a3f096fe76d..95af19c2485 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -160,6 +160,7 @@ private: DECL_GFX_PREF(Once, "apz.fling_curve_function_y2", APZCurveFunctionY2, float, 1.0f); DECL_GFX_PREF(Live, "apz.fling_curve_threshold_inches_per_ms", APZCurveThreshold, float, -1.0f); DECL_GFX_PREF(Live, "apz.fling_friction", APZFlingFriction, float, 0.002f); + DECL_GFX_PREF(Live, "apz.fling_repaint_interval", APZFlingRepaintInterval, int32_t, 75); DECL_GFX_PREF(Live, "apz.fling_stop_on_tap_threshold", APZFlingStopOnTapThreshold, float, 0.05f); DECL_GFX_PREF(Live, "apz.fling_stopped_threshold", APZFlingStoppedThreshold, float, 0.01f); DECL_GFX_PREF(Live, "apz.highlight_checkerboarded_areas", APZHighlightCheckerboardedAreas, bool, false); @@ -174,8 +175,10 @@ private: DECL_GFX_PREF(Live, "apz.overscroll.stop_distance_threshold", APZOverscrollStopDistanceThreshold, float, 5.0f); DECL_GFX_PREF(Live, "apz.overscroll.stop_velocity_threshold", APZOverscrollStopVelocityThreshold, float, 0.01f); DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f); + DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250); DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false); DECL_GFX_PREF(Live, "apz.record_checkerboarding", APZRecordCheckerboarding, bool, false); + DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75); DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false); DECL_GFX_PREF(Live, "apz.touch_move_tolerance", APZTouchMoveTolerance, float, 0.0); DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 116ab8d811e..af4a08fe0ea 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -578,6 +578,7 @@ pref("apz.fling_curve_function_x2", "1.0"); pref("apz.fling_curve_function_y2", "1.0"); pref("apz.fling_curve_threshold_inches_per_ms", "-1.0"); pref("apz.fling_friction", "0.002"); +pref("apz.fling_repaint_interval", 16); pref("apz.fling_stop_on_tap_threshold", "0.05"); pref("apz.fling_stopped_threshold", "0.01"); pref("apz.highlight_checkerboarded_areas", false); @@ -592,6 +593,7 @@ pref("apz.overscroll.spring_stiffness", "0.0018"); pref("apz.overscroll.stop_distance_threshold", "5.0"); pref("apz.overscroll.stop_velocity_threshold", "0.01"); pref("apz.overscroll.stretch_factor", "0.35"); +pref("apz.pan_repaint_interval", 16); // Whether to print the APZC tree for debugging pref("apz.printtree", false); @@ -601,6 +603,7 @@ pref("apz.record_checkerboarding", true); #else pref("apz.record_checkerboarding", false); #endif +pref("apz.smooth_scroll_repaint_interval", 16); pref("apz.test.logging_enabled", false); pref("apz.touch_start_tolerance", "0.1"); pref("apz.touch_move_tolerance", "0.03"); @@ -618,6 +621,8 @@ pref("apz.zoom_animation_duration_ms", 250); // Mobile prefs pref("apz.allow_zooming", true); pref("apz.enlarge_displayport_when_clipped", true); +pref("apz.fling_repaint_interval", 75); +pref("apz.smooth_scroll_repaint_interval", 75); pref("apz.x_skate_size_multiplier", "1.25"); pref("apz.y_skate_size_multiplier", "1.5"); pref("apz.x_stationary_size_multiplier", "1.5"); From 1360e68dd1c817c6167ce6bb9a364f10a05f9020 Mon Sep 17 00:00:00 2001 From: CJKu Date: Thu, 4 Feb 2016 13:58:44 +0800 Subject: [PATCH 159/160] Bug 1244598 - Move resource files of w3c-css/masking into ./support subdir. r=dbaron --- .../submitted/masking/mask-composite-1-ref.html | 4 ++-- .../submitted/masking/mask-composite-1a.html | 4 ++-- .../submitted/masking/mask-composite-1b.html | 4 ++-- .../submitted/masking/mask-composite-2-ref.html | 2 +- .../submitted/masking/mask-composite-2a.html | 4 ++-- .../submitted/masking/mask-composite-2b.html | 4 ++-- .../blue-100x50-transparent-100x50.png} | Bin .../blue-100x50-transparent-100x50.svg} | 0 .../transparent-100x50-blue-100x50.png} | Bin .../transparent-100x50-blue-100x50.svg} | 0 10 files changed, 11 insertions(+), 11 deletions(-) rename layout/reftests/w3c-css/submitted/masking/{blue-100x50-transparent-100X50.png => support/blue-100x50-transparent-100x50.png} (100%) rename layout/reftests/w3c-css/submitted/masking/{blue-100x50-transparent-100X50.svg => support/blue-100x50-transparent-100x50.svg} (100%) rename layout/reftests/w3c-css/submitted/masking/{transparent-100x50-blue-100X50.png => support/transparent-100x50-blue-100x50.png} (100%) rename layout/reftests/w3c-css/submitted/masking/{transparent-100x50-blue-100X50.svg => support/transparent-100x50-blue-100x50.svg} (100%) diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-1-ref.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-1-ref.html index 4419f7b7d81..9249622cc46 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-1-ref.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-1-ref.html @@ -17,12 +17,12 @@ div.add { left: 10px; - background-image: url(blue-100x50-transparent-100X50.svg); + background-image: url(support/blue-100x50-transparent-100x50.svg); } div.intersect { left: 230px; - background-image: url(blue-100x50-transparent-100X50.svg); + background-image: url(support/blue-100x50-transparent-100x50.svg); } diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-1a.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-1a.html index 86c1e036a2c..bc640777e2a 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-1a.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-1a.html @@ -17,8 +17,8 @@ width: 100px; height: 100px; top:10px; - mask-image: url(blue-100x50-transparent-100X50.svg), - url(blue-100x50-transparent-100X50.svg); + mask-image: url(support/blue-100x50-transparent-100x50.svg), + url(support/blue-100x50-transparent-100x50.svg); } div.add { diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-1b.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-1b.html index dd3e1e5e495..e11c28f52e4 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-1b.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-1b.html @@ -17,8 +17,8 @@ width: 100px; height: 100px; top:10px; - mask-image: url(blue-100x50-transparent-100X50.png), - url(blue-100x50-transparent-100X50.png); + mask-image: url(support/blue-100x50-transparent-100x50.png), + url(support/blue-100x50-transparent-100x50.png); } div.add { diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-2-ref.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-2-ref.html index be1fc6d99b4..b9c1ca50464 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-2-ref.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-2-ref.html @@ -22,7 +22,7 @@ div.substract { left: 120px; - background-image: url(blue-100x50-transparent-100X50.svg); + background-image: url(support/blue-100x50-transparent-100x50.svg); } div.exclude { diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-2a.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-2a.html index 9c81a433221..b624178f425 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-2a.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-2a.html @@ -17,8 +17,8 @@ width: 100px; height: 100px; top:10px; - mask-image: url(blue-100x50-transparent-100X50.svg), - url(transparent-100x50-blue-100X50.svg); + mask-image: url(support/blue-100x50-transparent-100x50.svg), + url(support/transparent-100x50-blue-100x50.svg); } div.add { diff --git a/layout/reftests/w3c-css/submitted/masking/mask-composite-2b.html b/layout/reftests/w3c-css/submitted/masking/mask-composite-2b.html index 9092c1e7f04..2c6e8f41fdd 100644 --- a/layout/reftests/w3c-css/submitted/masking/mask-composite-2b.html +++ b/layout/reftests/w3c-css/submitted/masking/mask-composite-2b.html @@ -17,8 +17,8 @@ width: 100px; height: 100px; top:10px; - mask-image: url(blue-100x50-transparent-100X50.png), - url(transparent-100x50-blue-100X50.png); + mask-image: url(support/blue-100x50-transparent-100x50.png), + url(support/transparent-100x50-blue-100x50.png); } div.add { diff --git a/layout/reftests/w3c-css/submitted/masking/blue-100x50-transparent-100X50.png b/layout/reftests/w3c-css/submitted/masking/support/blue-100x50-transparent-100x50.png similarity index 100% rename from layout/reftests/w3c-css/submitted/masking/blue-100x50-transparent-100X50.png rename to layout/reftests/w3c-css/submitted/masking/support/blue-100x50-transparent-100x50.png diff --git a/layout/reftests/w3c-css/submitted/masking/blue-100x50-transparent-100X50.svg b/layout/reftests/w3c-css/submitted/masking/support/blue-100x50-transparent-100x50.svg similarity index 100% rename from layout/reftests/w3c-css/submitted/masking/blue-100x50-transparent-100X50.svg rename to layout/reftests/w3c-css/submitted/masking/support/blue-100x50-transparent-100x50.svg diff --git a/layout/reftests/w3c-css/submitted/masking/transparent-100x50-blue-100X50.png b/layout/reftests/w3c-css/submitted/masking/support/transparent-100x50-blue-100x50.png similarity index 100% rename from layout/reftests/w3c-css/submitted/masking/transparent-100x50-blue-100X50.png rename to layout/reftests/w3c-css/submitted/masking/support/transparent-100x50-blue-100x50.png diff --git a/layout/reftests/w3c-css/submitted/masking/transparent-100x50-blue-100X50.svg b/layout/reftests/w3c-css/submitted/masking/support/transparent-100x50-blue-100x50.svg similarity index 100% rename from layout/reftests/w3c-css/submitted/masking/transparent-100x50-blue-100X50.svg rename to layout/reftests/w3c-css/submitted/masking/support/transparent-100x50-blue-100x50.svg From a0ef27d251dd88dddbf4b779ca20aae609dff0f3 Mon Sep 17 00:00:00 2001 From: CJKu Date: Thu, 4 Feb 2016 14:11:35 +0800 Subject: [PATCH 160/160] Bug 1244628: compare nsStyleImageLayers::mAttachmentCount in nsStyleImageLayers::CalcDifference. r=dbaron. --- layout/style/nsStyleStruct.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index c0cdab7efca..26d23e5c558 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2321,7 +2321,8 @@ nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aOther) const return hint; } - if (mBlendModeCount != aOther.mBlendModeCount || + if (mAttachmentCount != aOther.mAttachmentCount || + mBlendModeCount != aOther.mBlendModeCount || mClipCount != aOther.mClipCount || mCompositeCount != aOther.mCompositeCount || mMaskModeCount != aOther.mMaskModeCount ||