From 59203c63bb777a3bacec32fb8830fba33540e809 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:29 +0200 Subject: Adding upstream version 127.0. Signed-off-by: Daniel Baumann --- dom/base/AbstractRange.cpp | 8 ++ dom/base/BodyConsumer.cpp | 25 ++--- dom/base/ContentIterator.cpp | 2 +- dom/base/CrossShadowBoundaryRange.cpp | 115 +++++++++++++++++++++ dom/base/CrossShadowBoundaryRange.h | 89 ++++++++++++++++ dom/base/DOMIntersectionObserver.cpp | 3 +- dom/base/Document.cpp | 70 +++++++------ dom/base/Document.h | 5 +- dom/base/Element.cpp | 4 +- dom/base/EventSource.cpp | 6 +- dom/base/FocusModel.h | 41 ++++++++ dom/base/FragmentOrElement.cpp | 14 ++- dom/base/Highlight.cpp | 40 ++++--- dom/base/HighlightRegistry.cpp | 22 ++-- dom/base/MimeType.cpp | 14 +-- dom/base/RadioGroupContainer.cpp | 8 +- dom/base/ResizeObserver.h | 1 - dom/base/Selection.h | 24 +++++ dom/base/StaticRange.h | 12 +-- dom/base/crashtests/1419902.html | 24 +---- dom/base/crashtests/1741957.html | 22 ++++ dom/base/crashtests/crashtests.list | 3 +- dom/base/fragmentdirectives/lib.rs | 4 +- dom/base/fragmentdirectives/test.rs | 20 ++-- dom/base/moz.build | 3 + dom/base/nsAttrValue.cpp | 32 +++--- dom/base/nsAttrValue.h | 4 +- dom/base/nsContentAreaDragDrop.cpp | 2 +- dom/base/nsContentUtils.cpp | 81 ++++++--------- dom/base/nsContentUtils.h | 22 ++-- dom/base/nsCopySupport.cpp | 26 +++-- dom/base/nsCopySupport.h | 4 +- dom/base/nsDOMWindowUtils.cpp | 8 +- dom/base/nsFocusManager.cpp | 70 +++++++------ dom/base/nsGlobalWindowInner.cpp | 33 +++--- dom/base/nsGlobalWindowInner.h | 8 ++ dom/base/nsIContent.h | 23 +---- dom/base/nsJSEnvironment.cpp | 5 + dom/base/nsRange.cpp | 46 +++++++-- dom/base/nsRange.h | 17 ++- dom/base/nsTextFragment.cpp | 40 +++---- dom/base/nsTextFragment.h | 17 +-- dom/base/test/browser_page_load_event_telemetry.js | 10 ++ dom/base/test/chrome/bug418986-1.js | 2 +- dom/base/test/fullscreen/browser.toml | 3 + .../jsmodules/importmaps/bug_1893164_module_1.mjs | 3 + .../jsmodules/importmaps/bug_1893164_module_2.mjs | 5 + .../jsmodules/importmaps/bug_1893164_module_3.mjs | 1 + .../jsmodules/importmaps/bug_1894631_module_1.mjs | 5 + .../jsmodules/importmaps/bug_1894631_module_2.mjs | 3 + .../jsmodules/importmaps/bug_1894631_module_3.mjs | 1 + .../jsmodules/importmaps/bug_1894631_module_4.mjs | 1 + dom/base/test/jsmodules/importmaps/mochitest.toml | 10 ++ .../jsmodules/importmaps/test_bug_1893164.html | 20 ++++ .../test_shared_submodules_with_modulepreload.html | 30 ++++++ .../test/test_anchor_target_blank_referrer.html | 3 + dom/base/test/test_focus_radio.html | 69 ++++++++++++- 57 files changed, 833 insertions(+), 350 deletions(-) create mode 100644 dom/base/CrossShadowBoundaryRange.cpp create mode 100644 dom/base/CrossShadowBoundaryRange.h create mode 100644 dom/base/FocusModel.h create mode 100644 dom/base/crashtests/1741957.html create mode 100644 dom/base/test/jsmodules/importmaps/bug_1893164_module_1.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1893164_module_2.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1893164_module_3.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1894631_module_1.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1894631_module_2.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1894631_module_3.mjs create mode 100644 dom/base/test/jsmodules/importmaps/bug_1894631_module_4.mjs create mode 100644 dom/base/test/jsmodules/importmaps/test_bug_1893164.html create mode 100644 dom/base/test/jsmodules/importmaps/test_shared_submodules_with_modulepreload.html (limited to 'dom/base') diff --git a/dom/base/AbstractRange.cpp b/dom/base/AbstractRange.cpp index c9138a19d2..f5d584599b 100644 --- a/dom/base/AbstractRange.cpp +++ b/dom/base/AbstractRange.cpp @@ -49,6 +49,8 @@ template nsresult AbstractRange::SetStartAndEndInternal( const RawRangeBoundary& aEndBoundary, StaticRange* aRange); template bool AbstractRange::MaybeCacheToReuse(nsRange& aInstance); template bool AbstractRange::MaybeCacheToReuse(StaticRange& aInstance); +template bool AbstractRange::MaybeCacheToReuse( + CrossShadowBoundaryRange& aInstance); bool AbstractRange::sHasShutDown = false; @@ -209,6 +211,12 @@ void AbstractRange::Shutdown() { cachedRanges->Clear(); delete cachedRanges; } + if (nsTArray>* cachedRanges = + CrossShadowBoundaryRange::sCachedRanges) { + CrossShadowBoundaryRange::sCachedRanges = nullptr; + cachedRanges->Clear(); + delete cachedRanges; + } } // static diff --git a/dom/base/BodyConsumer.cpp b/dom/base/BodyConsumer.cpp index 754586a08b..81c9bb113d 100644 --- a/dom/base/BodyConsumer.cpp +++ b/dom/base/BodyConsumer.cpp @@ -74,7 +74,7 @@ class ContinueConsumeBodyRunnable final : public MainThreadWorkerRunnable { ContinueConsumeBodyRunnable(BodyConsumer* aBodyConsumer, WorkerPrivate* aWorkerPrivate, nsresult aStatus, uint32_t aLength, uint8_t* aResult) - : MainThreadWorkerRunnable(aWorkerPrivate, "ContinueConsumeBodyRunnable"), + : MainThreadWorkerRunnable("ContinueConsumeBodyRunnable"), mBodyConsumer(aBodyConsumer), mStatus(aStatus), mLength(aLength), @@ -97,7 +97,7 @@ class AbortConsumeBodyControlRunnable final public: AbortConsumeBodyControlRunnable(BodyConsumer* aBodyConsumer, WorkerPrivate* aWorkerPrivate) - : MainThreadWorkerControlRunnable(aWorkerPrivate), + : MainThreadWorkerControlRunnable("AbortConsumeBodyControlRunnable"), mBodyConsumer(aBodyConsumer) { MOZ_ASSERT(NS_IsMainThread()); } @@ -131,7 +131,7 @@ class MOZ_STACK_CLASS AutoFailConsumeBody final { RefPtr r = new AbortConsumeBodyControlRunnable(mBodyConsumer, mWorkerRef->Private()); - if (!r->Dispatch()) { + if (!r->Dispatch(mWorkerRef->Private())) { MOZ_CRASH("We are going to leak"); } return; @@ -159,8 +159,7 @@ class ContinueConsumeBlobBodyRunnable final : public MainThreadWorkerRunnable { ContinueConsumeBlobBodyRunnable(BodyConsumer* aBodyConsumer, WorkerPrivate* aWorkerPrivate, BlobImpl* aBlobImpl) - : MainThreadWorkerRunnable(aWorkerPrivate, - "ContinueConsumeBlobBodyRunnable"), + : MainThreadWorkerRunnable("ContinueConsumeBlobBodyRunnable"), mBodyConsumer(aBodyConsumer), mBlobImpl(aBlobImpl) { MOZ_ASSERT(NS_IsMainThread()); @@ -182,7 +181,7 @@ class AbortConsumeBlobBodyControlRunnable final public: AbortConsumeBlobBodyControlRunnable(BodyConsumer* aBodyConsumer, WorkerPrivate* aWorkerPrivate) - : MainThreadWorkerControlRunnable(aWorkerPrivate), + : MainThreadWorkerControlRunnable("AbortConsumeBlobBodyControlRunnable"), mBodyConsumer(aBodyConsumer) { MOZ_ASSERT(NS_IsMainThread()); } @@ -227,7 +226,7 @@ class ConsumeBodyDoneObserver final : public nsIStreamLoaderObserver, RefPtr r = new ContinueConsumeBodyRunnable( mBodyConsumer, mWorkerRef->Private(), aStatus, aResultLength, nonconstResult); - if (r->Dispatch()) { + if (r->Dispatch(mWorkerRef->Private())) { // The caller is responsible for data. return NS_SUCCESS_ADOPTED_DATA; } @@ -239,7 +238,7 @@ class ConsumeBodyDoneObserver final : public nsIStreamLoaderObserver, RefPtr r = new AbortConsumeBodyControlRunnable(mBodyConsumer, mWorkerRef->Private()); - if (NS_WARN_IF(!r->Dispatch())) { + if (NS_WARN_IF(!r->Dispatch(mWorkerRef->Private()))) { return NS_ERROR_FAILURE; } @@ -620,14 +619,14 @@ void BodyConsumer::DispatchContinueConsumeBlobBody( new ContinueConsumeBlobBodyRunnable(this, aWorkerRef->Private(), aBlobImpl); - if (r->Dispatch()) { + if (r->Dispatch(aWorkerRef->Private())) { return; } } else { RefPtr r = new ContinueConsumeBodyRunnable( this, aWorkerRef->Private(), NS_ERROR_DOM_ABORT_ERR, 0, nullptr); - if (r->Dispatch()) { + if (r->Dispatch(aWorkerRef->Private())) { return; } } @@ -638,7 +637,7 @@ void BodyConsumer::DispatchContinueConsumeBlobBody( RefPtr r = new AbortConsumeBlobBodyControlRunnable(this, aWorkerRef->Private()); - Unused << NS_WARN_IF(!r->Dispatch()); + Unused << NS_WARN_IF(!r->Dispatch(aWorkerRef->Private())); } /* @@ -673,12 +672,14 @@ void BodyConsumer::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength, if (NS_WARN_IF(NS_FAILED(aStatus))) { // Per - // https://fetch.spec.whatwg.org/#concept-read-all-bytes-from-readablestream + // https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes // Decoding errors should reject with a TypeError if (aStatus == NS_ERROR_INVALID_CONTENT_ENCODING) { localPromise->MaybeRejectWithTypeError(); } else if (aStatus == NS_ERROR_DOM_WRONG_TYPE_ERR) { localPromise->MaybeRejectWithTypeError(); + } else if (aStatus == NS_ERROR_NET_PARTIAL_TRANSFER) { + localPromise->MaybeRejectWithTypeError(); } else { localPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); } diff --git a/dom/base/ContentIterator.cpp b/dom/base/ContentIterator.cpp index 0b405f0348..80c795d137 100644 --- a/dom/base/ContentIterator.cpp +++ b/dom/base/ContentIterator.cpp @@ -715,7 +715,7 @@ nsIContent* ContentIteratorBase::GetNextSibling( // For shadow root, instead of getting to the sibling of the parent // directly, we need to get into the light tree of the parent to handle // slotted contents. - if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) { + if (aNode->IsShadowRoot()) { if (nsIContent* child = parent->GetFirstChild()) { return child; } diff --git a/dom/base/CrossShadowBoundaryRange.cpp b/dom/base/CrossShadowBoundaryRange.cpp new file mode 100644 index 0000000000..33fa9760e6 --- /dev/null +++ b/dom/base/CrossShadowBoundaryRange.cpp @@ -0,0 +1,115 @@ +/* -*- 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 "mozilla/dom/CrossShadowBoundaryRange.h" +#include "nsContentUtils.h" +#include "nsINode.h" + +namespace mozilla::dom { +template already_AddRefed +CrossShadowBoundaryRange::Create(const RangeBoundary& aStartBoundary, + const RangeBoundary& aEndBoundary); +template already_AddRefed +CrossShadowBoundaryRange::Create(const RangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary); +template already_AddRefed +CrossShadowBoundaryRange::Create(const RawRangeBoundary& aStartBoundary, + const RangeBoundary& aEndBoundary); +template already_AddRefed +CrossShadowBoundaryRange::Create(const RawRangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary); + +template void CrossShadowBoundaryRange::DoSetRange( + const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + nsINode* aRootNode); +template void CrossShadowBoundaryRange::DoSetRange( + const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary, + nsINode* aRootNode); +template void CrossShadowBoundaryRange::DoSetRange( + const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary, + nsINode* aRootNode); +template void CrossShadowBoundaryRange::DoSetRange( + const RawRangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary, nsINode* aRootNode); + +template nsresult CrossShadowBoundaryRange::SetStartAndEnd( + const RangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary); +template nsresult CrossShadowBoundaryRange::SetStartAndEnd( + const RangeBoundary& aStartBoundary, const RawRangeBoundary& aEndBoundary); +template nsresult CrossShadowBoundaryRange::SetStartAndEnd( + const RawRangeBoundary& aStartBoundary, const RangeBoundary& aEndBoundary); +template nsresult CrossShadowBoundaryRange::SetStartAndEnd( + const RawRangeBoundary& aStartBoundary, + const RawRangeBoundary& aEndBoundary); + +nsTArray>* + CrossShadowBoundaryRange::sCachedRanges = nullptr; + +NS_IMPL_CYCLE_COLLECTING_ADDREF(CrossShadowBoundaryRange) + +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_INTERRUPTABLE_LAST_RELEASE( + CrossShadowBoundaryRange, + DoSetRange(RawRangeBoundary(), RawRangeBoundary(), nullptr), + AbstractRange::MaybeCacheToReuse(*this)) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CrossShadowBoundaryRange) +NS_INTERFACE_MAP_END_INHERITING(CrossShadowBoundaryRange) + +NS_IMPL_CYCLE_COLLECTION_CLASS(CrossShadowBoundaryRange) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CrossShadowBoundaryRange, + StaticRange) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommonAncestor) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CrossShadowBoundaryRange, + StaticRange) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCommonAncestor) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(CrossShadowBoundaryRange, + StaticRange) +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +/* static */ +template +already_AddRefed CrossShadowBoundaryRange::Create( + const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary) { + RefPtr range; + if (!sCachedRanges || sCachedRanges->IsEmpty()) { + range = new CrossShadowBoundaryRange(aStartBoundary.Container()); + } else { + range = sCachedRanges->PopLastElement().forget(); + } + + range->Init(aStartBoundary.Container()); + range->DoSetRange(aStartBoundary, aEndBoundary, nullptr); + return range.forget(); +} + +template +void CrossShadowBoundaryRange::DoSetRange( + const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary, nsINode* aRootNode) { + // aRootNode is useless to CrossShadowBoundaryRange because aStartBoundary + // and aEndBoundary could have different roots. + StaticRange::DoSetRange(aStartBoundary, aEndBoundary, nullptr); + + nsINode* startRoot = RangeUtils::ComputeRootNode(mStart.Container()); + nsINode* endRoot = RangeUtils::ComputeRootNode(mEnd.Container()); + + if (startRoot == endRoot) { + // This should be the case when Release() is called. + MOZ_ASSERT(!startRoot && !endRoot); + mCommonAncestor = startRoot; + } else { + mCommonAncestor = + nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor( + mStart.Container(), mEnd.Container()); + } +} +} // namespace mozilla::dom diff --git a/dom/base/CrossShadowBoundaryRange.h b/dom/base/CrossShadowBoundaryRange.h new file mode 100644 index 0000000000..3ad4fa1793 --- /dev/null +++ b/dom/base/CrossShadowBoundaryRange.h @@ -0,0 +1,89 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_CrossShadowBoundaryRange_h +#define mozilla_dom_CrossShadowBoundaryRange_h + +#include "mozilla/RangeBoundary.h" +#include "mozilla/RangeUtils.h" +#include "mozilla/dom/AbstractRange.h" +#include "mozilla/dom/StaticRange.h" +#include "nsTArray.h" + +namespace mozilla { +class ErrorResult; + +namespace dom { + +class CrossShadowBoundaryRange final : public StaticRange { + public: + NS_DECL_ISUPPORTS_INHERITED + NS_IMETHODIMP_(void) DeleteCycleCollectable(void) override; + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( + CrossShadowBoundaryRange, StaticRange) + + CrossShadowBoundaryRange() = delete; + explicit CrossShadowBoundaryRange(const StaticRange& aOther) = delete; + + template + static already_AddRefed Create( + const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary); + + void NotifyNodeBecomesShadowHost(nsINode* aNode) { + if (aNode == mStart.Container()) { + mStart.NotifyParentBecomesShadowHost(); + } + + if (aNode == mEnd.Container()) { + mEnd.NotifyParentBecomesShadowHost(); + } + } + + nsINode* GetCommonAncestor() const { return mCommonAncestor; } + + // CrossShadowBoundaryRange should have a very limited usage. + nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset, + nsINode* aEndContainer, uint32_t aEndOffset) = delete; + + template + nsresult SetStartAndEnd(const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary) { + return StaticRange::SetStartAndEnd(aStartBoundary, aEndBoundary); + } + + private: + explicit CrossShadowBoundaryRange(nsINode* aNode) : StaticRange(aNode) {} + virtual ~CrossShadowBoundaryRange() = default; + + /** + * DoSetRange() is called when `AbstractRange::SetStartAndEndInternal()` sets + * mStart and mEnd. + * + * @param aStartBoundary Computed start point. This must equals or be before + * aEndBoundary in the DOM tree order. + * @param aEndBoundary Computed end point. + * @param aRootNode The root node of aStartBoundary or aEndBoundary. + * It's useless to CrossShadowBoundaryRange. + */ + template + void DoSetRange(const RangeBoundaryBase& aStartBoundary, + const RangeBoundaryBase& aEndBoundary, + nsINode* aRootNode); + + // This is either NULL if this CrossShadowBoundaryRange has been + // reset by Release() or the closest common shadow-including ancestor + // of mStart and mEnd. + nsCOMPtr mCommonAncestor; + + static nsTArray>* sCachedRanges; + + friend class AbstractRange; +}; +} // namespace dom +} // namespace mozilla + +#endif // #ifndef mozilla_dom_CrossShadowBoundaryRange_h diff --git a/dom/base/DOMIntersectionObserver.cpp b/dom/base/DOMIntersectionObserver.cpp index 12f7ee3029..37d17ddcd3 100644 --- a/dom/base/DOMIntersectionObserver.cpp +++ b/dom/base/DOMIntersectionObserver.cpp @@ -323,7 +323,8 @@ static Maybe ComputeTheIntersection( // // `intersectionRect` is kept relative to `target` during the loop. auto inflowRect = nsLayoutUtils::GetAllInFlowRectsUnion( - target, target, nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS); + target, target, + nsLayoutUtils::GetAllInFlowRectsFlag::AccountForTransforms); // For content-visibility, we need to observe the overflow clip edge, // https://drafts.csswg.org/css-contain-2/#close-to-the-viewport if (aIsForProximityToViewport == diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 8cbf8b8075..68e4100540 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -16423,47 +16423,33 @@ WindowContext* Document::GetWindowContextForPageUseCounters() const { return wc; } -void Document::UpdateIntersectionObservations(TimeStamp aNowTime) { - if (mIntersectionObservers.IsEmpty()) { - return; - } - - DOMHighResTimeStamp time = 0; - if (nsPIDOMWindowInner* win = GetInnerWindow()) { - if (Performance* perf = win->GetPerformance()) { - time = perf->TimeStampToDOMHighResForRendering(aNowTime); +void Document::UpdateIntersections(TimeStamp aNowTime) { + if (!mIntersectionObservers.IsEmpty()) { + DOMHighResTimeStamp time = 0; + if (nsPIDOMWindowInner* win = GetInnerWindow()) { + if (Performance* perf = win->GetPerformance()) { + time = perf->TimeStampToDOMHighResForRendering(aNowTime); + } } - } - - const auto observers = ToTArray>>( - mIntersectionObservers); - for (const auto& observer : observers) { - if (observer) { + for (DOMIntersectionObserver* observer : mIntersectionObservers) { observer->Update(*this, time); } + Dispatch(NewRunnableMethod("Document::NotifyIntersectionObservers", this, + &Document::NotifyIntersectionObservers)); } -} - -void Document::ScheduleIntersectionObserverNotification() { - if (mIntersectionObservers.IsEmpty()) { - return; - } - MOZ_RELEASE_ASSERT(NS_IsMainThread()); - nsCOMPtr notification = - NewRunnableMethod("Document::NotifyIntersectionObservers", this, - &Document::NotifyIntersectionObservers); - Dispatch(notification.forget()); + EnumerateSubDocuments([aNowTime](Document& aDoc) { + aDoc.UpdateIntersections(aNowTime); + return CallState::Continue; + }); } void Document::NotifyIntersectionObservers() { const auto observers = ToTArray>>( mIntersectionObservers); for (const auto& observer : observers) { - if (observer) { - // MOZ_KnownLive because the 'observers' array guarantees to keep it - // alive. - MOZ_KnownLive(observer)->Notify(); - } + // MOZ_KnownLive because the 'observers' array guarantees to keep it + // alive. + MOZ_KnownLive(observer)->Notify(); } } @@ -18647,6 +18633,13 @@ nsICookieJarSettings* Document::CookieJarSettings() { if (!mCookieJarSettings) { Document* inProcessParent = GetInProcessParentDocument(); + auto shouldInheritFrom = [this](Document* aDoc) { + return aDoc && (this->NodePrincipal()->Equals(aDoc->NodePrincipal()) || + this->NodePrincipal()->GetIsNullPrincipal()); + }; + RefPtr opener = + GetBrowsingContext() ? GetBrowsingContext()->GetOpener() : nullptr; + if (inProcessParent) { mCookieJarSettings = net::CookieJarSettings::Create( inProcessParent->CookieJarSettings()->GetCookieBehavior(), @@ -18674,6 +18667,18 @@ nsICookieJarSettings* Document::CookieJarSettings() { ->SetTopLevelWindowContextId( net::CookieJarSettings::Cast(inProcessParent->CookieJarSettings()) ->GetTopLevelWindowContextId()); + } else if (opener && shouldInheritFrom(opener->GetDocument())) { + mCookieJarSettings = net::CookieJarSettings::Create(NodePrincipal()); + + nsTArray randomKey; + nsresult rv = opener->GetDocument() + ->CookieJarSettings() + ->GetFingerprintingRandomizationKey(randomKey); + + if (NS_SUCCEEDED(rv)) { + net::CookieJarSettings::Cast(mCookieJarSettings) + ->SetFingerprintingRandomizationKey(randomKey); + } } else { mCookieJarSettings = net::CookieJarSettings::Create(NodePrincipal()); @@ -18933,8 +18938,7 @@ void Document::AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement, } bool Document::ShouldAvoidNativeTheme() const { - return StaticPrefs::widget_non_native_theme_enabled() && - (!IsInChromeDocShell() || XRE_IsContentProcess()); + return !IsInChromeDocShell() || XRE_IsContentProcess(); } bool Document::UseRegularPrincipal() const { diff --git a/dom/base/Document.h b/dom/base/Document.h index 0b0d0ca3d0..e919f19be0 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -3709,8 +3709,9 @@ class Document : public nsINode, return !mIntersectionObservers.IsEmpty(); } - void UpdateIntersectionObservations(TimeStamp aNowTime); - void ScheduleIntersectionObserverNotification(); + // Update intersection observers in this document and all + // same-process subdocuments. + void UpdateIntersections(TimeStamp aNowTime); MOZ_CAN_RUN_SCRIPT void NotifyIntersectionObservers(); DOMIntersectionObserver* GetLazyLoadObserver() { return mLazyLoadObserver; } diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index b6f5d5c3be..758134990b 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -1088,7 +1088,7 @@ already_AddRefed Element::GetClientRects() { nsLayoutUtils::RectListBuilder builder(rectList); nsLayoutUtils::GetAllInFlowRects( frame, nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder, - nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS); + nsLayoutUtils::GetAllInFlowRectsFlag::AccountForTransforms); return rectList.forget(); } @@ -1353,7 +1353,7 @@ already_AddRefed Element::AttachShadowWithoutNameChecks( for (const AbstractRange* range : *ranges) { if (range->MayCrossShadowBoundary()) { MOZ_ASSERT(range->IsDynamicRange()); - StaticRange* crossBoundaryRange = + CrossShadowBoundaryRange* crossBoundaryRange = range->AsDynamicRange()->GetCrossShadowBoundaryRange(); MOZ_ASSERT(crossBoundaryRange); // We may have previously selected this node before it diff --git a/dom/base/EventSource.cpp b/dom/base/EventSource.cpp index def3c90ec0..9e73f31fc6 100644 --- a/dom/base/EventSource.cpp +++ b/dom/base/EventSource.cpp @@ -1827,14 +1827,14 @@ nsresult EventSourceImpl::ParseCharacter(char16_t aChr) { namespace { -class WorkerRunnableDispatcher final : public WorkerRunnable { +class WorkerRunnableDispatcher final : public WorkerThreadRunnable { RefPtr mEventSourceImpl; public: WorkerRunnableDispatcher(RefPtr&& aImpl, WorkerPrivate* aWorkerPrivate, already_AddRefed aEvent) - : WorkerRunnable(aWorkerPrivate, "WorkerRunnableDispatcher"), + : WorkerThreadRunnable("WorkerRunnableDispatcher"), mEventSourceImpl(std::move(aImpl)), mEvent(std::move(aEvent)) {} @@ -1928,7 +1928,7 @@ EventSourceImpl::Dispatch(already_AddRefed aEvent, RefPtr event = new WorkerRunnableDispatcher( this, mWorkerRef->Private(), event_ref.forget()); - if (!event->Dispatch()) { + if (!event->Dispatch(mWorkerRef->Private())) { return NS_ERROR_FAILURE; } return NS_OK; diff --git a/dom/base/FocusModel.h b/dom/base/FocusModel.h new file mode 100644 index 0000000000..588c0503a2 --- /dev/null +++ b/dom/base/FocusModel.h @@ -0,0 +1,41 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_FocusModel_h +#define mozilla_FocusModel_h + +#include "mozilla/StaticPrefs_accessibility.h" +#include "mozilla/TypedEnumBits.h" + +namespace mozilla { + +enum class IsFocusableFlags : uint8_t { + WithMouse = 1 << 0, + // Whether to treat an invisible frame as not focusable + IgnoreVisibility = 1 << 1, +}; + +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(IsFocusableFlags); + +enum class TabFocusableType : uint8_t { + TextControls = 1, // Textboxes and lists always tabbable + FormElements = 1 << 1, // Non-text form elements + Links = 1 << 2, // Links + Any = TextControls | FormElements | Links, +}; + +class FocusModel final { + public: + static bool AppliesToXUL() { + return StaticPrefs::accessibility_tabfocus_applies_to_xul(); + } + + static bool IsTabFocusable(TabFocusableType aType) { + return StaticPrefs::accessibility_tabfocus() & int32_t(aType); + } +}; + +} // namespace mozilla + +#endif diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 87fd81bfa3..8338fc6b9e 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -105,8 +105,6 @@ using namespace mozilla; using namespace mozilla::dom; -int32_t nsIContent::sTabFocusModel = eTabFocus_any; -bool nsIContent::sTabFocusModelAppliesToXUL = false; uint64_t nsMutationGuard::sGeneration = 0; NS_IMPL_CYCLE_COLLECTION_CLASS(nsIContent) @@ -1022,7 +1020,7 @@ void nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) { } } -Element* nsIContent::GetAutofocusDelegate(bool aWithMouse) const { +Element* nsIContent::GetAutofocusDelegate(IsFocusableFlags aFlags) const { for (nsINode* node = GetFirstChild(); node; node = node->GetNextNode(this)) { auto* descendant = Element::FromNode(*node); if (!descendant || !descendant->GetBoolAttr(nsGkAtoms::autofocus)) { @@ -1030,14 +1028,14 @@ Element* nsIContent::GetAutofocusDelegate(bool aWithMouse) const { } nsIFrame* frame = descendant->GetPrimaryFrame(); - if (frame && frame->IsFocusable(aWithMouse)) { + if (frame && frame->IsFocusable(aFlags)) { return descendant; } } return nullptr; } -Element* nsIContent::GetFocusDelegate(bool aWithMouse) const { +Element* nsIContent::GetFocusDelegate(IsFocusableFlags aFlags) const { const nsIContent* whereToLook = this; if (ShadowRoot* root = GetShadowRoot()) { if (!root->DelegatesFocus()) { @@ -1055,7 +1053,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const { return {}; } - return frame->IsFocusable(aWithMouse); + return frame->IsFocusable(aFlags); }; Element* potentialFocus = nullptr; @@ -1097,7 +1095,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const { if (auto* shadow = el->GetShadowRoot()) { if (shadow->DelegatesFocus()) { - if (Element* delegatedFocus = shadow->GetFocusDelegate(aWithMouse)) { + if (Element* delegatedFocus = shadow->GetFocusDelegate(aFlags)) { if (autofocus) { // This element has autofocus and we found an focus delegates // in its descendants, so use the focus delegates @@ -1114,7 +1112,7 @@ Element* nsIContent::GetFocusDelegate(bool aWithMouse) const { return potentialFocus; } -Focusable nsIContent::IsFocusableWithoutStyle(bool aWithMouse) { +Focusable nsIContent::IsFocusableWithoutStyle(IsFocusableFlags) { // Default, not tabbable return {}; } diff --git a/dom/base/Highlight.cpp b/dom/base/Highlight.cpp index cd0efccce5..0bac8193d7 100644 --- a/dom/base/Highlight.cpp +++ b/dom/base/Highlight.cpp @@ -101,24 +101,36 @@ already_AddRefed Highlight::CreateHighlightSelection( } void Highlight::Add(AbstractRange& aRange, ErrorResult& aRv) { + // Manually check if the range `aKey` is already present in this highlight, + // because `SetlikeHelpers::Add()` doesn't indicate this. + // To keep the setlike and the mirrored array in sync, the range must not + // be added to `mRanges` if it was already present. + // `SetlikeHelpers::Has()` is much faster in checking this than + // `nsTArray<>::Contains()`. + if (Highlight_Binding::SetlikeHelpers::Has(this, aRange, aRv) || + aRv.Failed()) { + return; + } Highlight_Binding::SetlikeHelpers::Add(this, aRange, aRv); if (aRv.Failed()) { return; } - if (!mRanges.Contains(&aRange)) { - mRanges.AppendElement(&aRange); - AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__, - mHighlightRegistries.Count()); - for (const RefPtr& registry : - mHighlightRegistries.Keys()) { - auto frameSelection = registry->GetFrameSelection(); - selectionBatcher.AddFrameSelection(frameSelection); - // since this is run in a context guarded by a selection batcher, - // no strong reference is needed to keep `registry` alive. - MOZ_KnownLive(registry)->MaybeAddRangeToHighlightSelection(aRange, *this); - if (aRv.Failed()) { - return; - } + + MOZ_ASSERT(!mRanges.Contains(&aRange), + "setlike and DOM mirror are not in sync"); + + mRanges.AppendElement(&aRange); + AutoFrameSelectionBatcher selectionBatcher(__FUNCTION__, + mHighlightRegistries.Count()); + for (const RefPtr& registry : + mHighlightRegistries.Keys()) { + auto frameSelection = registry->GetFrameSelection(); + selectionBatcher.AddFrameSelection(frameSelection); + // since this is run in a context guarded by a selection batcher, + // no strong reference is needed to keep `registry` alive. + MOZ_KnownLive(registry)->MaybeAddRangeToHighlightSelection(aRange, *this); + if (aRv.Failed()) { + return; } } } diff --git a/dom/base/HighlightRegistry.cpp b/dom/base/HighlightRegistry.cpp index 035aadb78a..755977286f 100644 --- a/dom/base/HighlightRegistry.cpp +++ b/dom/base/HighlightRegistry.cpp @@ -133,18 +133,28 @@ void HighlightRegistry::AddHighlightSelectionsToFrameSelection() { void HighlightRegistry::Set(const nsAString& aKey, Highlight& aValue, ErrorResult& aRv) { + // manually check if the highlight `aKey` is already registered to be able to + // provide a fast path later that avoids calling `std::find_if()`. + const bool highlightAlreadyPresent = + HighlightRegistry_Binding::MaplikeHelpers::Has(this, aKey, aRv); + if (aRv.Failed()) { + return; + } HighlightRegistry_Binding::MaplikeHelpers::Set(this, aKey, aValue, aRv); if (aRv.Failed()) { return; } RefPtr frameSelection = GetFrameSelection(); RefPtr highlightNameAtom = NS_AtomizeMainThread(aKey); - auto foundIter = - std::find_if(mHighlightsOrdered.begin(), mHighlightsOrdered.end(), - [&highlightNameAtom](auto const& aElm) { - return aElm.first() == highlightNameAtom; - }); - if (foundIter != mHighlightsOrdered.end()) { + if (highlightAlreadyPresent) { + // If the highlight named `aKey` was present before, replace its value. + auto foundIter = + std::find_if(mHighlightsOrdered.begin(), mHighlightsOrdered.end(), + [&highlightNameAtom](auto const& aElm) { + return aElm.first() == highlightNameAtom; + }); + MOZ_ASSERT(foundIter != mHighlightsOrdered.end(), + "webIDL maplike and DOM mirror are not in sync"); foundIter->second()->RemoveFromHighlightRegistry(*this, *highlightNameAtom); if (frameSelection) { frameSelection->RemoveHighlightSelection(highlightNameAtom); diff --git a/dom/base/MimeType.cpp b/dom/base/MimeType.cpp index da61489c1f..1e6d6a7cd4 100644 --- a/dom/base/MimeType.cpp +++ b/dom/base/MimeType.cpp @@ -328,13 +328,13 @@ template template void TMimeType::Serialize(nsTSubstring& aOutput) const { aOutput.Assign(mType); - aOutput.AppendLiteral("/"); + aOutput.Append('/'); aOutput.Append(mSubtype); for (uint32_t i = 0; i < mParameterNames.Length(); i++) { auto name = mParameterNames[i]; - aOutput.AppendLiteral(";"); + aOutput.Append(';'); aOutput.Append(name); - aOutput.AppendLiteral("="); + aOutput.Append('='); GetParameterValue(name, aOutput, true); } } @@ -342,7 +342,7 @@ void TMimeType::Serialize(nsTSubstring& aOutput) const { template void TMimeType::GetEssence(nsTSubstring& aOutput) const { aOutput.Assign(mType); - aOutput.AppendLiteral("/"); + aOutput.Append('/'); aOutput.Append(mSubtype); } @@ -366,17 +366,17 @@ bool TMimeType::GetParameterValue( } if (aWithQuotes && (value.mRequiresQuoting || value.IsEmpty())) { - aOutput.AppendLiteral("\""); + aOutput.Append('"'); const char_type* vcur = value.BeginReading(); const char_type* vend = value.EndReading(); while (vcur < vend) { if (*vcur == '"' || *vcur == '\\') { - aOutput.AppendLiteral("\\"); + aOutput.Append('\\'); } aOutput.Append(*vcur); vcur++; } - aOutput.AppendLiteral("\""); + aOutput.Append('"'); } else { aOutput.Append(value); } diff --git a/dom/base/RadioGroupContainer.cpp b/dom/base/RadioGroupContainer.cpp index 3bb4d7da20..988c8186f9 100644 --- a/dom/base/RadioGroupContainer.cpp +++ b/dom/base/RadioGroupContainer.cpp @@ -8,6 +8,7 @@ #include "mozilla/dom/RadioGroupContainer.h" #include "mozilla/dom/TreeOrderedArrayInlines.h" #include "mozilla/Assertions.h" +#include "nsIFrame.h" #include "nsIRadioVisitor.h" #include "nsRadioVisitor.h" @@ -125,7 +126,9 @@ nsresult RadioGroupContainer::GetNextRadioButton( index = 0; } radio = radioGroup->mRadioButtons->ElementAt(index); - } while (radio->Disabled() && radio != currentRadio); + } while ((radio->Disabled() || !radio->GetPrimaryFrame() || + !radio->GetPrimaryFrame()->IsVisibleConsideringAncestors()) && + radio != currentRadio); radio.forget(aRadioOut); return NS_OK; @@ -135,7 +138,8 @@ HTMLInputElement* RadioGroupContainer::GetFirstRadioButton( const nsAString& aName) { nsRadioGroupStruct* radioGroup = GetOrCreateRadioGroup(aName); for (HTMLInputElement* radio : radioGroup->mRadioButtons.AsList()) { - if (!radio->Disabled()) { + if (!radio->Disabled() && radio->GetPrimaryFrame() && + radio->GetPrimaryFrame()->IsVisibleConsideringAncestors()) { return radio; } } diff --git a/dom/base/ResizeObserver.h b/dom/base/ResizeObserver.h index eaa0e1726d..2fd630c66c 100644 --- a/dom/base/ResizeObserver.h +++ b/dom/base/ResizeObserver.h @@ -121,7 +121,6 @@ class ResizeObservation final : public LinkedListElement { * https://drafts.csswg.org/resize-observer/#api */ class ResizeObserver final : public nsISupports, public nsWrapperCache { - public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(ResizeObserver) diff --git a/dom/base/Selection.h b/dom/base/Selection.h index 08563993ac..101bada49f 100644 --- a/dom/base/Selection.h +++ b/dom/base/Selection.h @@ -386,6 +386,30 @@ class Selection final : public nsSupportsWeakReference, return mStyledRanges.mRanges[0].mRange->Collapsed(); } + // Returns whether both normal range and cross-shadow-boundary + // range are collapsed. + // + // If StaticPrefs::dom_shadowdom_selection_across_boundary_enabled is + // disabled, this method always returns result as nsRange::IsCollapsed. + bool AreNormalAndCrossShadowBoundaryRangesCollapsed() const { + if (!IsCollapsed()) { + return false; + } + + size_t cnt = mStyledRanges.Length(); + if (cnt == 0) { + return true; + } + + AbstractRange* range = mStyledRanges.mRanges[0].mRange; + MOZ_ASSERT_IF( + range->MayCrossShadowBoundary(), + !range->AsDynamicRange()->CrossShadowBoundaryRangeCollapsed()); + // Returns false if nsRange::mCrossBoundaryRange exists, + // true otherwise. + return !range->MayCrossShadowBoundary(); + } + // *JS() methods are mapped to Selection.*(). // They may move focus only when the range represents normal selection. // These methods shouldn't be used by non-JS callers. diff --git a/dom/base/StaticRange.h b/dom/base/StaticRange.h index af7054f843..249c938b2f 100644 --- a/dom/base/StaticRange.h +++ b/dom/base/StaticRange.h @@ -19,7 +19,7 @@ class ErrorResult; namespace dom { -class StaticRange final : public AbstractRange { +class StaticRange : public AbstractRange { public: StaticRange() = delete; explicit StaticRange(const StaticRange& aOther) = delete; @@ -71,16 +71,6 @@ class StaticRange final : public AbstractRange { */ bool IsValid() const; - void NotifyNodeBecomesShadowHost(nsINode* aNode) { - if (aNode == mStart.Container()) { - mStart.NotifyParentBecomesShadowHost(); - } - - if (aNode == mEnd.Container()) { - mEnd.NotifyParentBecomesShadowHost(); - } - } - private: // Whether the start and end points are in the same tree. // They could be in different trees, i.e, cross shadow boundaries. diff --git a/dom/base/crashtests/1419902.html b/dom/base/crashtests/1419902.html index b0742b5be0..a0aa1b0698 100644 --- a/dom/base/crashtests/1419902.html +++ b/dom/base/crashtests/1419902.html @@ -1,23 +1 @@ - - - - - + diff --git a/dom/base/crashtests/1741957.html b/dom/base/crashtests/1741957.html new file mode 100644 index 0000000000..56b695052e --- /dev/null +++ b/dom/base/crashtests/1741957.html @@ -0,0 +1,22 @@ + + + + + + +
diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list index 22aaf50e6b..7aa5e6a92a 100644 --- a/dom/base/crashtests/crashtests.list +++ b/dom/base/crashtests/crashtests.list @@ -220,7 +220,7 @@ load 1406109-1.html load 1411473.html load 1413815.html load 1419799.html -skip-if(geckoview) skip-if(geckoview&&isDebugBuild) skip-if(AddressSanitizer) skip-if(ThreadSanitizer) pref(dom.disable_open_during_load,false) load 1419902.html # skip Bug 1419902. Bug 1563013 for GV+WR. Bug 1524493 GV+debug. Bug 1573281 asan +# load 1419902.html # this test is run at the very end in testing/crashtest/final/crashtests.list load 1422883.html load 1428053.html load 1441029.html @@ -265,6 +265,7 @@ load 1757923.html load 1766472.html pref(dom.enable_web_task_scheduling,true) load 1780790.html load 1700237.html +load 1741957.html load 1811939.html load 1822717.html load 1835886.html diff --git a/dom/base/fragmentdirectives/lib.rs b/dom/base/fragmentdirectives/lib.rs index 0003849eb7..5f9d5ebdd8 100644 --- a/dom/base/fragmentdirectives/lib.rs +++ b/dom/base/fragmentdirectives/lib.rs @@ -96,9 +96,7 @@ pub extern "C" fn parse_fragment_directive( &url_as_rust_string, ) { - result - .url_without_fragment_directive - .assign(&stripped_url); + result.url_without_fragment_directive.assign(&stripped_url); result.fragment_directive.assign(&fragment_directive); result.text_directives.extend( text_directives diff --git a/dom/base/fragmentdirectives/test.rs b/dom/base/fragmentdirectives/test.rs index d4509cb033..e5479d8022 100644 --- a/dom/base/fragmentdirectives/test.rs +++ b/dom/base/fragmentdirectives/test.rs @@ -145,13 +145,16 @@ mod test { ), ( "http://example.com/page.html?query=irrelevant:~:#bar:~:text=foo", - "http://example.com/page.html?query=irrelevant:~:#bar" - ) + "http://example.com/page.html?query=irrelevant:~:#bar", + ), ] { let (stripped_url, fragment_directive, _) = parse_fragment_directive_and_remove_it_from_hash(&url) .expect("The parser must find a result"); - assert_eq!(stripped_url, stripped_url_ref, "The stripped url is not correct."); + assert_eq!( + stripped_url, stripped_url_ref, + "The stripped url is not correct." + ); assert_eq!(fragment_directive, "text=foo"); } } @@ -195,9 +198,8 @@ mod test { #[test] fn test_parse_multiple_text_fragments() { let url = "#:~:text=prefix-,start,-suffix&text=foo&text=bar,-suffix"; - let (_, _, text_directives) = - parse_fragment_directive_and_remove_it_from_hash(&url) - .expect("The parser must find a result."); + let (_, _, text_directives) = parse_fragment_directive_and_remove_it_from_hash(&url) + .expect("The parser must find a result."); assert_eq!( text_directives.len(), 3, @@ -339,8 +341,7 @@ mod test { "text=prefix-,start", "#:~:text=foo-,bar,-baz:~:text=foo", ] { - let text_directives = - parse_fragment_directive_and_remove_it_from_hash(&url); + let text_directives = parse_fragment_directive_and_remove_it_from_hash(&url); assert!( text_directives.is_none(), "The fragment `{}` does not contain a valid or known fragment directive.", @@ -369,8 +370,7 @@ mod test { "#:~:text=,prefix,start", "#:~:text=", ] { - let text_directives = - parse_fragment_directive_and_remove_it_from_hash(&url); + let text_directives = parse_fragment_directive_and_remove_it_from_hash(&url); assert!( text_directives.is_none(), "The fragment directive `{}` does not contain a valid text directive.", diff --git a/dom/base/moz.build b/dom/base/moz.build index ffcfb0aaf6..e2cf2dfb78 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -126,6 +126,7 @@ EXPORTS.mozilla += [ "ContentIterator.h", "CORSMode.h", "FlushType.h", + "FocusModel.h", "FullscreenChange.h", "GlobalTeardownObserver.h", "IdentifierMapEntry.h", @@ -166,6 +167,7 @@ EXPORTS.mozilla.dom += [ "CompressionStream.h", "ContentFrameMessageManager.h", "ContentProcessMessageManager.h", + "CrossShadowBoundaryRange.h", "CustomElementRegistry.h", "DecompressionStream.h", "DirectionalityUtils.h", @@ -336,6 +338,7 @@ UNIFIED_SOURCES += [ "ContentFrameMessageManager.cpp", "ContentIterator.cpp", "ContentProcessMessageManager.cpp", + "CrossShadowBoundaryRange.cpp", "Crypto.cpp", "CustomElementRegistry.cpp", "DirectionalityUtils.cpp", diff --git a/dom/base/nsAttrValue.cpp b/dom/base/nsAttrValue.cpp index 01efef2eb9..e4bf977f56 100644 --- a/dom/base/nsAttrValue.cpp +++ b/dom/base/nsAttrValue.cpp @@ -141,7 +141,7 @@ bool MiscContainer::GetString(nsAString& aString) const { } if (isString) { auto* buffer = static_cast(ptr); - buffer->ToString(buffer->StorageSize() / sizeof(char16_t) - 1, aString); + aString.Assign(buffer, buffer->StorageSize() / sizeof(char16_t) - 1); } else { static_cast(ptr)->ToString(aString); } @@ -280,11 +280,9 @@ void nsAttrValue::Shutdown() { void nsAttrValue::Reset() { switch (BaseType()) { case eStringBase: { - nsStringBuffer* str = static_cast(GetPtr()); - if (str) { + if (auto* str = static_cast(GetPtr())) { str->Release(); } - break; } case eOtherBase: { @@ -320,8 +318,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) { switch (aOther.BaseType()) { case eStringBase: { ResetIfSet(); - nsStringBuffer* str = static_cast(aOther.GetPtr()); - if (str) { + if (auto* str = static_cast(aOther.GetPtr())) { str->AddRef(); SetPtrValueAndType(str, eStringBase); } @@ -623,18 +620,16 @@ void nsAttrValue::ToString(nsAString& aResult) const { switch (Type()) { case eString: { - nsStringBuffer* str = static_cast(GetPtr()); - if (str) { - str->ToString(str->StorageSize() / sizeof(char16_t) - 1, aResult); + if (auto* str = static_cast(GetPtr())) { + aResult.Assign(str, str->StorageSize() / sizeof(char16_t) - 1); } else { aResult.Truncate(); } break; } case eAtom: { - nsAtom* atom = static_cast(GetPtr()); + auto* atom = static_cast(GetPtr()); atom->ToString(aResult); - break; } case eInteger: { @@ -895,8 +890,7 @@ nsAtom* nsAttrValue::AtomAt(int32_t aIndex) const { uint32_t nsAttrValue::HashValue() const { switch (BaseType()) { case eStringBase: { - nsStringBuffer* str = static_cast(GetPtr()); - if (str) { + if (auto* str = static_cast(GetPtr())) { uint32_t len = str->StorageSize() / sizeof(char16_t) - 1; return HashString(static_cast(str->Data()), len); } @@ -1208,8 +1202,7 @@ bool nsAttrValue::SubstringCheck(const nsAString& aValue, nsCaseTreatment aCaseSensitive) const { switch (BaseType()) { case eStringBase: { - auto str = static_cast(GetPtr()); - if (str) { + if (auto* str = static_cast(GetPtr())) { return F::Check(static_cast(str->Data()), str->StorageSize() / sizeof(char16_t) - 1, aValue, aCaseSensitive); @@ -1217,7 +1210,7 @@ bool nsAttrValue::SubstringCheck(const nsAString& aValue, return aValue.IsEmpty(); } case eAtomBase: { - auto atom = static_cast(GetPtr()); + auto* atom = static_cast(GetPtr()); return F::Check(atom->GetUTF16String(), atom->GetLength(), aValue, aCaseSensitive); } @@ -2107,12 +2100,11 @@ already_AddRefed nsAttrValue::GetStringBuffer( if (!len) { return nullptr; } - - RefPtr buf = nsStringBuffer::FromString(aValue); - if (buf && (buf->StorageSize() / sizeof(char16_t) - 1) == len) { + if (nsStringBuffer* buf = aValue.GetStringBuffer(); + buf && (buf->StorageSize() / sizeof(char16_t) - 1) == len) { // We can only reuse the buffer if it's exactly sized, since we rely on // StorageSize() to get the string length in ToString(). - return buf.forget(); + return do_AddRef(buf); } return nsStringBuffer::Create(aValue.Data(), aValue.Length()); } diff --git a/dom/base/nsAttrValue.h b/dom/base/nsAttrValue.h index 4ef63c287f..b32dfc98fb 100644 --- a/dom/base/nsAttrValue.h +++ b/dom/base/nsAttrValue.h @@ -108,7 +108,9 @@ const uintptr_t NS_ATTRVALUE_BASETYPE_MASK = 3; class nsCheapString : public nsString { public: explicit nsCheapString(nsStringBuffer* aBuf) { - if (aBuf) aBuf->ToString(aBuf->StorageSize() / sizeof(char16_t) - 1, *this); + if (aBuf) { + Assign(aBuf, aBuf->StorageSize() / sizeof(char16_t) - 1); + } } }; diff --git a/dom/base/nsContentAreaDragDrop.cpp b/dom/base/nsContentAreaDragDrop.cpp index 3ca21e725a..b2ccc8cb1c 100644 --- a/dom/base/nsContentAreaDragDrop.cpp +++ b/dom/base/nsContentAreaDragDrop.cpp @@ -295,7 +295,7 @@ nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable* aTransferable, bool isPrivate = aTransferable->GetIsPrivateData(); - nsCOMPtr principal = aTransferable->GetRequestingPrincipal(); + nsCOMPtr principal = aTransferable->GetDataPrincipal(); nsContentPolicyType contentPolicyType = aTransferable->GetContentPolicyType(); nsCOMPtr cookieJarSettings = diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index d2c863bd65..e4f4fadf9c 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3010,6 +3010,18 @@ nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1, aNode1, aNode2, [](nsINode* aNode) { return aNode->GetParentNode(); }); } +/* static */ +nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor( + nsINode* aNode1, nsINode* aNode2) { + if (aNode1 == aNode2) { + return aNode1; + } + + return GetCommonAncestorInternal(aNode1, aNode2, [](nsINode* aNode) { + return aNode->GetParentOrShadowHostNode(); + }); +} + /* static */ nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper( nsIContent* aContent1, nsIContent* aContent2) { @@ -6998,25 +7010,6 @@ bool nsContentUtils::PlatformToDOMLineBreaks(nsString& aString, return true; } -void nsContentUtils::PopulateStringFromStringBuffer(nsStringBuffer* aBuf, - nsAString& aResultString) { - MOZ_ASSERT(aBuf, "Expecting a non-null string buffer"); - - uint32_t stringLen = NS_strlen(static_cast(aBuf->Data())); - - // SANITY CHECK: In case the nsStringBuffer isn't correctly - // null-terminated, let's clamp its length using the allocated size, to be - // sure the resulting string doesn't sample past the end of the the buffer. - // (Note that StorageSize() is in units of bytes, so we have to convert that - // to units of PRUnichars, and subtract 1 for the null-terminator.) - uint32_t allocStringLen = (aBuf->StorageSize() / sizeof(char16_t)) - 1; - MOZ_ASSERT(stringLen <= allocStringLen, - "string buffer lacks null terminator!"); - stringLen = std::min(stringLen, allocStringLen); - - aBuf->ToString(stringLen, aResultString); -} - already_AddRefed nsContentUtils::GetElementsByClassName( nsINode* aRootNode, const nsAString& aClasses) { MOZ_ASSERT(aRootNode, "Must have root node"); @@ -7442,8 +7435,12 @@ int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame, // static bool nsContentUtils::IsPointInSelection( const mozilla::dom::Selection& aSelection, const nsINode& aNode, - const uint32_t aOffset) { - if (aSelection.IsCollapsed()) { + const uint32_t aOffset, const bool aAllowCrossShadowBoundary) { + const bool selectionIsCollapsed = + !aAllowCrossShadowBoundary + ? aSelection.IsCollapsed() + : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed(); + if (selectionIsCollapsed) { return false; } @@ -7457,7 +7454,8 @@ bool nsContentUtils::IsPointInSelection( } // Done when we find a range that we are in - if (range->IsPointInRange(aNode, aOffset, IgnoreErrors())) { + if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(), + aAllowCrossShadowBoundary)) { return true; } } @@ -8211,7 +8209,7 @@ nsresult nsContentUtils::IPCTransferableToTransferable( aTransferable->SetCookieJarSettings(cookieJarSettings); } aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo()); - aTransferable->SetRequestingPrincipal(aIPCTransferable.requestingPrincipal()); + aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal()); aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType()); return NS_OK; @@ -8302,7 +8300,7 @@ nsresult nsContentUtils::CalculateBufferSizeForImage( } static already_AddRefed BigBufferToDataSurface( - BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize, + const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize, SurfaceFormat aFormat) { if (!aData.Size() || !aImageSize.width || !aImageSize.height) { return nullptr; @@ -8325,22 +8323,13 @@ static already_AddRefed BigBufferToDataSurface( nsresult nsContentUtils::DeserializeTransferableDataImageContainer( const IPCTransferableDataImageContainer& aData, imgIContainer** aContainer) { - const IntSize size(aData.width(), aData.height()); - size_t maxBufferSize = 0; - size_t usedBufferSize = 0; - nsresult rv = CalculateBufferSizeForImage( - aData.stride(), size, aData.format(), &maxBufferSize, &usedBufferSize); - NS_ENSURE_SUCCESS(rv, rv); - if (usedBufferSize > aData.data().Size()) { - return NS_ERROR_FAILURE; - } - RefPtr surface = - CreateDataSourceSurfaceFromData(size, aData.format(), aData.data().Data(), - static_cast(aData.stride())); + RefPtr surface = IPCImageToSurface(aData.image()); if (!surface) { return NS_ERROR_FAILURE; } - RefPtr drawable = new gfxSurfaceDrawable(surface, size); + + RefPtr drawable = + new gfxSurfaceDrawable(surface, surface->GetSize()); nsCOMPtr imageContainer = image::ImageOps::CreateFromDrawable(drawable); imageContainer.forget(aContainer); @@ -8472,23 +8461,16 @@ void nsContentUtils::TransferableToIPCTransferableData( if (!dataSurface) { continue; } - size_t length; - int32_t stride; - Maybe surfaceData = - GetSurfaceData(*dataSurface, &length, &stride); - if (surfaceData.isNothing()) { + auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface); + if (!imageData) { continue; } IPCTransferableDataItem* item = aTransferableData->items().AppendElement(); item->flavor() = flavorStr; - - mozilla::gfx::IntSize size = dataSurface->GetSize(); - item->data() = IPCTransferableDataImageContainer( - std::move(*surfaceData), size.width, size.height, stride, - dataSurface->GetFormat()); + item->data() = IPCTransferableDataImageContainer(std::move(*imageData)); continue; } @@ -8569,8 +8551,7 @@ void nsContentUtils::TransferableToIPCTransferable( aIPCTransferable->data() = std::move(ipcTransferableData); aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData(); - aIPCTransferable->requestingPrincipal() = - aTransferable->GetRequestingPrincipal(); + aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal(); aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs); aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType(); aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo(); @@ -8617,7 +8598,7 @@ Maybe nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) { } already_AddRefed nsContentUtils::IPCImageToSurface( - IPCImage&& aImage) { + const IPCImage& aImage) { return BigBufferToDataSurface(aImage.data(), aImage.stride(), aImage.size().ToUnknownSize(), aImage.format()); } diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index 4291d2c5d1..a1f466fa8d 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -115,7 +115,6 @@ class nsNodeInfoManager; class nsParser; class nsPIWindowRoot; class nsPresContext; -class nsStringBuffer; class nsTextFragment; class nsView; class nsWrapperCache; @@ -501,6 +500,9 @@ class nsContentUtils { return GetCommonAncestorHelper(aNode1, aNode2); } + static nsINode* GetClosestCommonShadowIncludingInclusiveAncestor( + nsINode* aNode1, nsINode* aNode2); + /** * Returns the common flattened tree ancestor, if any, for two given content * nodes. @@ -2443,14 +2445,6 @@ class nsContentUtils { [[nodiscard]] static bool PlatformToDOMLineBreaks(nsString& aString, const mozilla::fallible_t&); - /** - * Populates aResultString with the contents of the string-buffer aBuf, up - * to aBuf's null-terminator. aBuf must not be null. Ownership of the string - * is not transferred. - */ - static void PopulateStringFromStringBuffer(nsStringBuffer* aBuf, - nsAString& aResultString); - static bool IsHandlingKeyBoardEvent() { return sIsHandlingKeyBoardEvent; } static void SetIsHandlingKeyBoardEvent(bool aHandling) { @@ -2778,9 +2772,13 @@ class nsContentUtils { * check. aNode and aOffset can be computed with * UIEvent::GetRangeParentContentAndOffset() if you want to * check the click point. + * @param aAllowCrossShadowBoundary If true, this method allows the selection + * to have boundaries that cross shadow + * boundaries. */ static bool IsPointInSelection(const mozilla::dom::Selection& aSelection, - const nsINode& aNode, const uint32_t aOffset); + const nsINode& aNode, const uint32_t aOffset, + const bool aAllowCrossShadowBoundary = false); /** * Takes a selection, and a text control element ( or