diff --git a/browser/base/content/test/general/browser_audioTabIcon.js b/browser/base/content/test/general/browser_audioTabIcon.js index 95314ba0d65..5b3e2d30e96 100644 --- a/browser/base/content/test/general/browser_audioTabIcon.js +++ b/browser/base/content/test/general/browser_audioTabIcon.js @@ -115,12 +115,28 @@ function* test_swapped_browser(oldTab, newBrowser, isPlaying) { return (event.detail.changed.indexOf("soundplaying") >= 0 || !isPlaying) && event.detail.changed.indexOf("muted") >= 0; }); + let AudioPlaybackPromise = new Promise(resolve => { + let observer = (subject, topic, data) => { + ok(false, "Should not see an audio-playback notification"); + }; + Services.obs.addObserver(observer, "audio-playback", false); + setTimeout(() => { + Services.obs.removeObserver(observer, "audio-playback"); + resolve(); + }, 100); + }); gBrowser.swapBrowsersAndCloseOther(newTab, oldTab); yield AttrChangePromise; ok(newTab.hasAttribute("muted"), "Expected the correct muted attribute on the new tab"); is(newTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the new tab"); + + // Wait to see if an audio-playback event is dispatched. This should not happen! + yield AudioPlaybackPromise; + + ok(newTab.hasAttribute("muted"), "Expected the correct muted attribute on the new tab"); + is(newTab.hasAttribute("soundplaying"), isPlaying, "Expected the correct soundplaying attribute on the new tab"); } function* test_browser_swapping(tab, browser) { diff --git a/build/pgo/server-locations.txt b/build/pgo/server-locations.txt index a0f6802d882..9151151e470 100644 --- a/build/pgo/server-locations.txt +++ b/build/pgo/server-locations.txt @@ -171,6 +171,8 @@ http://malware.example.com:80 http://tracking.example.com:80 http://not-tracking.example.com:80 http://tracking.example.org:80 +http://itisatracker.org:80 +http://trackertest.org:80 https://malware.example.com:443 https://tracking.example.com:443 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index fd28d102e92..9b1bafc3c8a 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -900,6 +900,7 @@ nsDocShell::nsDocShell() , mUseRemoteTabs(false) , mDeviceSizeIsPageSize(false) , mWindowDraggingAllowed(false) + , mInFrameSwap(false) , mCanExecuteScripts(false) , mFiredUnloadEvent(false) , mEODForCurrentDocument(false) @@ -14074,3 +14075,16 @@ nsDocShell::GetPaymentRequestId(nsAString& aPaymentRequestId) aPaymentRequestId = GetInheritedPaymentRequestId(); return NS_OK; } + +bool +nsDocShell::InFrameSwap() +{ + nsRefPtr shell = this; + do { + if (shell->mInFrameSwap) { + return true; + } + shell = shell->GetParentDocshell(); + } while (shell); + return false; +} diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 52395e25cad..ba23b371d66 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -258,6 +258,12 @@ public: // is no longer applied void NotifyAsyncPanZoomStopped(); + void SetInFrameSwap(bool aInSwap) + { + mInFrameSwap = aInSwap; + } + bool InFrameSwap(); + private: // An observed docshell wrapper is created when recording markers is enabled. mozilla::UniquePtr mObserved; @@ -900,6 +906,7 @@ protected: bool mUseRemoteTabs; bool mDeviceSizeIsPageSize; bool mWindowDraggingAllowed; + bool mInFrameSwap; // Because scriptability depends on the mAllowJavascript values of our // ancestors, we cache the effective scriptability and recompute it when diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 4e5e40fc8ea..aa037e2bace 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -951,6 +951,60 @@ nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther, return NS_OK; } +class MOZ_STACK_CLASS AutoResetInFrameSwap final +{ +public: + AutoResetInFrameSwap(nsFrameLoader* aThisFrameLoader, + nsFrameLoader* aOtherFrameLoader, + nsDocShell* aThisDocShell, + nsDocShell* aOtherDocShell, + EventTarget* aThisEventTarget, + EventTarget* aOtherEventTarget + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : mThisFrameLoader(aThisFrameLoader) + , mOtherFrameLoader(aOtherFrameLoader) + , mThisDocShell(aThisDocShell) + , mOtherDocShell(aOtherDocShell) + , mThisEventTarget(aThisEventTarget) + , mOtherEventTarget(aOtherEventTarget) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + + mThisFrameLoader->mInSwap = true; + mOtherFrameLoader->mInSwap = true; + mThisDocShell->SetInFrameSwap(true); + mOtherDocShell->SetInFrameSwap(true); + + // Fire pageshow events on still-loading pages, and then fire pagehide + // events. Note that we do NOT fire these in the normal way, but just fire + // them on the chrome event handlers. + nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, false); + nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, false); + nsContentUtils::FirePageHideEvent(mThisDocShell, mThisEventTarget); + nsContentUtils::FirePageHideEvent(mOtherDocShell, mOtherEventTarget); + } + + ~AutoResetInFrameSwap() + { + nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, true); + nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, true); + + mThisFrameLoader->mInSwap = false; + mOtherFrameLoader->mInSwap = false; + mThisDocShell->SetInFrameSwap(false); + mOtherDocShell->SetInFrameSwap(false); + } + +private: + nsRefPtr mThisFrameLoader; + nsRefPtr mOtherFrameLoader; + nsRefPtr mThisDocShell; + nsRefPtr mOtherDocShell; + nsCOMPtr mThisEventTarget; + nsCOMPtr mOtherEventTarget; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + nsresult nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, nsRefPtr& aFirstToSwap, @@ -987,8 +1041,8 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, return NS_ERROR_DOM_SECURITY_ERR; } - nsCOMPtr ourDocshell = GetExistingDocShell(); - nsCOMPtr otherDocshell = aOther->GetExistingDocShell(); + nsRefPtr ourDocshell = static_cast(GetExistingDocShell()); + nsRefPtr otherDocshell = static_cast(aOther->GetExistingDocShell()); if (!ourDocshell || !otherDocshell) { // How odd return NS_ERROR_NOT_IMPLEMENTED; @@ -1119,39 +1173,23 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, if (mInSwap || aOther->mInSwap) { return NS_ERROR_NOT_IMPLEMENTED; } - mInSwap = aOther->mInSwap = true; + AutoResetInFrameSwap autoFrameSwap(this, aOther, ourDocshell, otherDocshell, + ourEventTarget, otherEventTarget); - // Fire pageshow events on still-loading pages, and then fire pagehide - // events. Note that we do NOT fire these in the normal way, but just fire - // them on the chrome event handlers. - nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, false); - nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, false); - nsContentUtils::FirePageHideEvent(ourDocshell, ourEventTarget); - nsContentUtils::FirePageHideEvent(otherDocshell, otherEventTarget); - nsIFrame* ourFrame = ourContent->GetPrimaryFrame(); nsIFrame* otherFrame = otherContent->GetPrimaryFrame(); if (!ourFrame || !otherFrame) { - mInSwap = aOther->mInSwap = false; - nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true); - nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true); return NS_ERROR_NOT_IMPLEMENTED; } nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame); if (!ourFrameFrame) { - mInSwap = aOther->mInSwap = false; - nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true); - nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true); return NS_ERROR_NOT_IMPLEMENTED; } // OK. First begin to swap the docshells in the two nsIFrames rv = ourFrameFrame->BeginSwapDocShells(otherFrame); if (NS_FAILED(rv)) { - mInSwap = aOther->mInSwap = false; - nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true); - nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true); return rv; } @@ -1254,10 +1292,6 @@ nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther, ourParentDocument->FlushPendingNotifications(Flush_Layout); otherParentDocument->FlushPendingNotifications(Flush_Layout); - nsContentUtils::FirePageShowEvent(ourDocshell, ourEventTarget, true); - nsContentUtils::FirePageShowEvent(otherDocshell, otherEventTarget, true); - - mInSwap = aOther->mInSwap = false; return NS_OK; } diff --git a/dom/base/nsFrameLoader.h b/dom/base/nsFrameLoader.h index 281628797f0..6515d40bd9c 100644 --- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -31,6 +31,7 @@ class nsSubDocumentFrame; class nsView; class nsIInProcessContentFrameMessageManager; class AutoResetInShow; +class AutoResetInFrameSwap; class nsITabParent; class nsIDocShellTreeItem; class nsIDocShellTreeOwner; @@ -59,6 +60,7 @@ class nsFrameLoader final : public nsIFrameLoader, public mozilla::dom::ipc::MessageManagerCallback { friend class AutoResetInShow; + friend class AutoResetInFrameSwap; typedef mozilla::dom::PBrowserParent PBrowserParent; typedef mozilla::dom::TabParent TabParent; typedef mozilla::layout::RenderFrameParent RenderFrameParent; diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 578dadcc5c4..ca36ecf9304 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -103,6 +103,7 @@ static PRLogModuleInfo* gMediaElementEventsLog; #include "nsIPermissionManager.h" #include "nsContentTypeParser.h" +#include "nsDocShell.h" #include "mozilla/EventStateManager.h" @@ -4013,7 +4014,14 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged() if (pauseElement && mAudioChannelAgent) { // If the element is being paused since we are navigating away from the // document, notify the audio channel agent. - NotifyAudioChannelAgent(false); + // Be careful to ignore this event during a docshell frame swap. + auto docShell = static_cast(OwnerDoc()->GetDocShell()); + if (!docShell) { + return; + } + if (!docShell->InFrameSwap()) { + NotifyAudioChannelAgent(false); + } } } diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 0590c822378..2e08dbf6501 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2392,11 +2392,18 @@ TabChild::RecvSwappedWithOtherRemoteLoader() return true; } + nsRefPtr docShell = static_cast(ourDocShell.get()); + nsCOMPtr ourEventTarget = ourWindow->GetParentTarget(); + docShell->SetInFrameSwap(true); + nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, false); nsContentUtils::FirePageHideEvent(ourDocShell, ourEventTarget); nsContentUtils::FirePageShowEvent(ourDocShell, ourEventTarget, true); + + docShell->SetInFrameSwap(false); + return true; } diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index c72a1a34032..73f35cdf96f 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -278,7 +278,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) */ const char kTexYUVPlanarBlit_FragShaderSource[] = "\ #ifdef GL_ES \n\ - precision mediump float \n\ + precision mediump float; \n\ #endif \n\ varying vec2 vTexCoord; \n\ uniform sampler2D uYTexture; \n\ @@ -288,9 +288,9 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) uniform vec2 uCbCrTexScale; \n\ void main() \n\ { \n\ - float y = texture2D(uYTexture, vTexCoord * uYTexScale).r; \n\ - float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r; \n\ - float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r; \n\ + float y = texture2D(uYTexture, vTexCoord * uYTexScale).a; \n\ + float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).a; \n\ + float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).a; \n\ y = (y - 0.06275) * 1.16438; \n\ cb = cb - 0.50196; \n\ cr = cr - 0.50196; \n\ @@ -641,7 +641,7 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which, GLuint& tex = *srcTexArr[which]; if (!tex) { MOZ_ASSERT(needsAllocation); - tex = CreateTexture(mGL, LOCAL_GL_LUMINANCE, LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE, + tex = CreateTexture(mGL, LOCAL_GL_ALPHA, LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE, gfx::IntSize(width, height), false); } mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + which); @@ -654,17 +654,17 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which, 0, width, height, - LOCAL_GL_LUMINANCE, + LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE, data); } else { mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, - LOCAL_GL_LUMINANCE, + LOCAL_GL_ALPHA, width, height, 0, - LOCAL_GL_LUMINANCE, + LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE, data); } diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 800e270d652..ebc31e61f7d 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -453,6 +453,9 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds) mUnusedApzTransformWarning = false; SetDebugOverlayWantsNextFrame(true); } + + // Each frame is invalidate by the previous frame for simplicity + AddInvalidRegion(nsIntRect(0, 0, 256, 256)); } else { mFPS = nullptr; } @@ -467,6 +470,9 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds) effects, 1.0, gfx::Matrix4x4()); + + // Each frame is invalidate by the previous frame for simplicity + AddInvalidRegion(nsIntRect(0, 0, sideRect.width, sideRect.height)); } #ifdef MOZ_PROFILING @@ -509,6 +515,9 @@ LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds) } } } + + // Each frame is invalidate by the previous frame for simplicity + AddInvalidRegion(nsIntRect(0, 0, 256, 256)); } #endif diff --git a/js/src/Makefile.in b/js/src/Makefile.in index 7fa03c65e11..33da1555bc3 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -97,10 +97,13 @@ JITTEST_VALGRIND_FLAG = --valgrind endif endif -ifdef MOZ_ASAN ifneq ($(LLVM_SYMBOLIZER),) -# Use the LLVM symbolizer when running jit-tests under ASan, if available -JITTEST_ASAN_ENV=ASAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)' +# Use the LLVM symbolizer when running jit-tests under ASan and TSan, if available +ifdef MOZ_ASAN +JITTEST_SANITIZER_ENV=ASAN_SYMBOLIZER_PATH='$(LLVM_SYMBOLIZER)' +endif +ifdef MOZ_TSAN +JITTEST_SANITIZER_ENV=TSAN_OPTIONS='external_symbolizer_path=$(LLVM_SYMBOLIZER)' endif endif @@ -111,11 +114,11 @@ check-masm:: (cd $(srcdir) && $(PYTHON) $(topsrcdir)/config/check_macroassembler_style.py); check-jit-test:: - $(JITTEST_ASAN_ENV) $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \ + $(JITTEST_SANITIZER_ENV) $(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/jit-test/jit_test.py \ --no-slow --no-progress --format=automation --jitflags=all \ $(JITTEST_VALGRIND_FLAG) \ $(JITTEST_EXTRA_ARGS) \ - $(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX) + $(DIST)/bin/$(JS_SHELL_NAME)$(BIN_SUFFIX) $(JITTEST_TEST_ARGS) check:: check-style check-masm diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index a6abca3d010..b0e2e2a5b6f 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -267,10 +267,9 @@ InitClass(JSContext* cx, Handle global, const Class* clasp, JSPro const JSPropertySpec* properties, const JSFunctionSpec* methods, const JSPropertySpec* staticProperties) { - RootedNativeObject proto(cx, global->createBlankPrototype(cx, clasp)); + RootedPlainObject proto(cx, NewBuiltinClassInstance(cx)); if (!proto) return nullptr; - proto->setPrivate(nullptr); Rooted ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0)); if (!ctor || diff --git a/js/src/jit-test/tests/collections/Map-surfaces-1.js b/js/src/jit-test/tests/collections/Map-surfaces-1.js index 827dd7b1ef7..9a4f20b9f2b 100644 --- a/js/src/jit-test/tests/collections/Map-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Map-surfaces-1.js @@ -13,7 +13,11 @@ assertEq(Map.length, 0); assertEq(Map.name, "Map"); assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype); -assertEq(Object.prototype.toString.call(Map.prototype), "[object Map]"); +assertEq("toStringTag" in Symbol, false, + "if this fails, congratulations! implement " + + "Map.prototype[Symbol.toStringTag] = 'Map' in SpiderMonkey and make " + + "the next test check for '[object Map]' again"); +assertEq(Object.prototype.toString.call(Map.prototype), "[object Object]"); assertEq(Object.prototype.toString.call(new Map()), "[object Map]"); assertEq(Object.keys(Map.prototype).join(), ""); assertEq(Map.prototype.constructor, Map); diff --git a/js/src/jit-test/tests/collections/Set-surfaces-1.js b/js/src/jit-test/tests/collections/Set-surfaces-1.js index cd8573868c9..88fcb340467 100644 --- a/js/src/jit-test/tests/collections/Set-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Set-surfaces-1.js @@ -13,7 +13,11 @@ assertEq(Set.length, 0); assertEq(Set.name, "Set"); assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype); -assertEq(Object.prototype.toString.call(Set.prototype), "[object Set]"); +assertEq("toStringTag" in Symbol, false, + "if this fails, congratulations! implement " + + "Set.prototype[Symbol.toStringTag] = 'Set' in SpiderMonkey and make " + + "the next test check for '[object Set]' again"); +assertEq(Object.prototype.toString.call(Set.prototype), "[object Object]"); assertEq(Object.prototype.toString.call(new Set()), "[object Set]"); assertEq(Object.keys(Set.prototype).join(), ""); assertEq(Set.prototype.constructor, Set); diff --git a/layout/base/MobileViewportManager.cpp b/layout/base/MobileViewportManager.cpp index fbb129a2f13..fc5a69791fb 100644 --- a/layout/base/MobileViewportManager.cpp +++ b/layout/base/MobileViewportManager.cpp @@ -190,11 +190,14 @@ MobileViewportManager::UpdateSPCSPS(const ScreenIntSize& aDisplaySize, { ScreenSize compositionSize(aDisplaySize); ScreenMargin scrollbars = - CSSMargin::FromAppUnits( + LayoutDeviceMargin::FromAppUnits( nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor( - mPresShell->GetRootScrollFrame())) - * CSSToScreenScale(1.0f); // Scrollbars are not subject to scaling, so - // CSS pixels = layer pixels for them (modulo bug 1168487). + mPresShell->GetRootScrollFrame()), + mPresShell->GetPresContext()->AppUnitsPerDevPixel()) + // Scrollbars are not subject to resolution scaling, so LD pixels = + // Screen pixels for them. + * LayoutDeviceToScreenScale(1.0f); + compositionSize.width -= scrollbars.LeftRight(); compositionSize.height -= scrollbars.TopBottom(); CSSSize compSize = compositionSize / aZoom; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1be0b53d366..39ea099bfa0 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1077,6 +1077,10 @@ nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent, return false; } + if (currentData && currentData->mMargins == aMargins) { + return true; + } + aContent->SetProperty(nsGkAtoms::DisplayPortMargins, new DisplayPortMarginsPropertyData( aMargins, aPriority), diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 3947b3459a1..3ba73e377af 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -2226,7 +2226,7 @@ void ScrollFrameHelper::MarkRecentlyScrolled() } } -void ScrollFrameHelper::ScrollVisual(nsPoint aOldScrolledFramePos) +void ScrollFrameHelper::ScrollVisual() { // Mark this frame as having been scrolled. If this is the root // scroll frame of a content document, then IsAlwaysActive() @@ -2245,7 +2245,6 @@ void ScrollFrameHelper::ScrollVisual(nsPoint aOldScrolledFramePos) MarkRecentlyScrolled(); } - mOuter->SchedulePaint(); } /** @@ -2419,15 +2418,35 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri mListeners[i]->ScrollPositionWillChange(pt.x, pt.y); } - nsPoint oldScrollFramePos = mScrolledFrame->GetPosition(); + nsRect oldDisplayPort; + nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &oldDisplayPort); + oldDisplayPort.MoveBy(-mScrolledFrame->GetPosition()); + // Update frame position for scrolling mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt); mLastScrollOrigin = aOrigin; mLastSmoothScrollOrigin = nullptr; mScrollGeneration = ++sScrollGenerationCounter; - // We pass in the amount to move visually - ScrollVisual(oldScrollFramePos); + ScrollVisual(); + + if (LastScrollOrigin() == nsGkAtoms::apz) { + // If this was an apz scroll and the displayport (relative to the + // scrolled frame) hasn't changed, then this won't trigger + // any painting, so no need to schedule one. + nsRect displayPort; + DebugOnly usingDisplayPort = + nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort); + NS_ASSERTION(usingDisplayPort, "Must have a displayport for apz scrolls!"); + + displayPort.MoveBy(-mScrolledFrame->GetPosition()); + + if (!displayPort.IsEqualEdges(oldDisplayPort)) { + mOuter->SchedulePaint(); + } + } else { + mOuter->SchedulePaint(); + } if (mOuter->ChildrenHavePerspective()) { // The overflow areas of descendants may depend on the scroll position, diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index d7b06b89500..da35f5e2b45 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -222,7 +222,7 @@ public: * @note This method might destroy the frame, pres shell and other objects. */ void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange, nsIAtom* aOrigin = nullptr); - void ScrollVisual(nsPoint aOldScrolledFramePosition); + void ScrollVisual(); /** * @note This method might destroy the frame, pres shell and other objects. */ diff --git a/layout/reftests/w3c-css/submitted/check-for-references.sh b/layout/reftests/w3c-css/submitted/check-for-references.sh new file mode 100755 index 00000000000..977cee3f487 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/check-for-references.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +cd "$(dirname "$0")" +find . -name reftest.list | sed 's,/reftest.list$,,' | while read DIRNAME +do + cat "$DIRNAME/reftest.list" | grep -v "^\(include\|default-preferences\)" | sed 's/ #.*//;s/^#.*//;s/.* == /== /;s/.* != /!= /' | grep -v "^ *$" | while read TYPE TEST REF + do + REFTYPE="" + if [ "$TYPE" == "==" ] + then + REFTYPE="match" + elif [ "$TYPE" == "!=" ] + then + REFTYPE="mismatch" + else + echo "Unexpected type $TYPE for $DIRNAME/$TEST" + fi + if grep "rel=\"$REFTYPE\"" "$DIRNAME/$TEST" | head -1 | grep -q "href=\"$REF\"" + then + #echo "Good link for $DIRNAME/$TEST" + echo -n + else + echo "Missing link for $DIRNAME/$TEST" + #echo "" >> "$DIRNAME/$TEST" + fi + done +done diff --git a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html index e9976a86eb7..530a353c789 100644 --- a/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html +++ b/layout/reftests/w3c-css/submitted/css21/pagination/moz-css21-block-page-break-inside-avoid-1.html @@ -4,6 +4,7 @@ CSS Test: CSS 2.1 page-break-inside:avoid + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht index 57bdeb25246..3118bc40b54 100644 --- a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht @@ -4,6 +4,7 @@ CSS Test: Box Sizing - Border-Box with specified width +