mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1617154 - [intersection-observer] Accept a Document as an explicit root. r=emilio,bzbarsky
This patch allows users to specify a Document as an explicit root of an intersection observer. For rationale, see the intent-to thread: https://groups.google.com/forum/#!topic/mozilla.dev.platform/64nDLTAZGzY It is implemented under a preference option enabled in Nightly: dom.IntersectionObserverExplicitDocumentRoot.enabled When disabled, the current TypeError exception is preserved so that people can continue to feature detect the support. The enhancement is tested by and enabled for the following test: https://w3c-test.org/intersection-observer/document-scrolling-element-root.html Differential Revision: https://phabricator.services.mozilla.com/D63766 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
41606ddbd6
commit
f70d494fe7
@ -12,6 +12,7 @@
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/DocumentInlines.h"
|
||||
@ -91,7 +92,20 @@ already_AddRefed<DOMIntersectionObserver> DOMIntersectionObserver::Constructor(
|
||||
RefPtr<DOMIntersectionObserver> observer =
|
||||
new DOMIntersectionObserver(window.forget(), aCb);
|
||||
|
||||
observer->mRoot = aOptions.mRoot;
|
||||
if (!aOptions.mRoot.IsNull()) {
|
||||
if (aOptions.mRoot.Value().IsElement()) {
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsElement();
|
||||
} else {
|
||||
MOZ_ASSERT(aOptions.mRoot.Value().IsDocument());
|
||||
if (!StaticPrefs::
|
||||
dom_IntersectionObserverExplicitDocumentRoot_enabled()) {
|
||||
aRv.ThrowTypeError<dom::MSG_DOES_NOT_IMPLEMENT_INTERFACE>(
|
||||
u"'root' member of IntersectionObserverInit", u"Element");
|
||||
return nullptr;
|
||||
}
|
||||
observer->mRoot = aOptions.mRoot.Value().GetAsDocument();
|
||||
}
|
||||
}
|
||||
|
||||
if (!observer->SetRootMargin(aOptions.mRootMargin)) {
|
||||
aRv.ThrowSyntaxError("rootMargin must be specified in pixels or percent.");
|
||||
@ -257,7 +271,7 @@ enum class BrowsingContextOrigin { Similar, Different, Unknown };
|
||||
// contexts" is gone, but this is still in the spec, see
|
||||
// https://github.com/w3c/IntersectionObserver/issues/161
|
||||
static BrowsingContextOrigin SimilarOrigin(const Element& aTarget,
|
||||
const Element* aRoot) {
|
||||
const nsINode* aRoot) {
|
||||
if (!aRoot) {
|
||||
return BrowsingContextOrigin::Unknown;
|
||||
}
|
||||
@ -466,10 +480,10 @@ void DOMIntersectionObserver::Update(Document* aDocument,
|
||||
// document.
|
||||
nsRect rootRect;
|
||||
nsIFrame* rootFrame = nullptr;
|
||||
Element* root = mRoot;
|
||||
nsINode* root = mRoot;
|
||||
Maybe<nsRect> remoteDocumentVisibleRect;
|
||||
if (mRoot) {
|
||||
if ((rootFrame = mRoot->GetPrimaryFrame())) {
|
||||
if (mRoot && mRoot->IsElement()) {
|
||||
if ((rootFrame = mRoot->AsElement()->GetPrimaryFrame())) {
|
||||
nsRect rootRectRelativeToRootFrame;
|
||||
if (rootFrame->IsScrollFrame()) {
|
||||
// rootRectRelativeToRootFrame should be the content rect of rootFrame,
|
||||
@ -485,21 +499,26 @@ void DOMIntersectionObserver::Update(Document* aDocument,
|
||||
rootRect = nsLayoutUtils::TransformFrameRectToAncestor(
|
||||
rootFrame, rootRectRelativeToRootFrame, containingBlock);
|
||||
}
|
||||
} else if (Document* topLevelDocument = GetTopLevelDocument(*aDocument)) {
|
||||
if (PresShell* presShell = topLevelDocument->GetPresShell()) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
} else {
|
||||
MOZ_ASSERT(!mRoot || mRoot->IsDocument());
|
||||
Document* rootDocument =
|
||||
mRoot ? mRoot->AsDocument() : GetTopLevelDocument(*aDocument);
|
||||
if (rootDocument) {
|
||||
if (PresShell* presShell = rootDocument->GetPresShell()) {
|
||||
rootFrame = presShell->GetRootScrollFrame();
|
||||
if (rootFrame) {
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
}
|
||||
} else if (Maybe<OopIframeMetrics> metrics =
|
||||
GetOopIframeMetrics(*aDocument)) {
|
||||
// `implicit root` case in an out-of-process iframe.
|
||||
rootFrame = metrics->mInProcessRootFrame;
|
||||
rootRect = metrics->mInProcessRootRect;
|
||||
remoteDocumentVisibleRect = Some(metrics->mRemoteDocumentVisibleRect);
|
||||
}
|
||||
} else if (Maybe<OopIframeMetrics> metrics =
|
||||
GetOopIframeMetrics(*aDocument)) {
|
||||
// `implicit root` case in an out-of-process iframe.
|
||||
rootFrame = metrics->mInProcessRootFrame;
|
||||
rootRect = metrics->mInProcessRootRect;
|
||||
remoteDocumentVisibleRect = Some(metrics->mRemoteDocumentVisibleRect);
|
||||
}
|
||||
|
||||
nsMargin rootMargin; // This root margin is NOT applied in `implicit root`
|
||||
|
@ -118,7 +118,7 @@ class DOMIntersectionObserver final : public nsISupports,
|
||||
|
||||
nsISupports* GetParentObject() const { return mOwner; }
|
||||
|
||||
Element* GetRoot() const { return mRoot; }
|
||||
nsINode* GetRoot() const { return mRoot; }
|
||||
|
||||
void GetRootMargin(DOMString& aRetVal);
|
||||
void GetThresholds(nsTArray<double>& aRetVal);
|
||||
@ -151,7 +151,7 @@ class DOMIntersectionObserver final : public nsISupports,
|
||||
RefPtr<Document> mDocument;
|
||||
Variant<RefPtr<dom::IntersectionCallback>, NativeIntersectionObserverCallback>
|
||||
mCallback;
|
||||
RefPtr<Element> mRoot;
|
||||
RefPtr<nsINode> mRoot;
|
||||
StyleRect<LengthPercentage> mRootMargin;
|
||||
nsTArray<double> mThresholds;
|
||||
|
||||
|
@ -34,7 +34,7 @@ interface IntersectionObserver {
|
||||
optional IntersectionObserverInit options = {});
|
||||
|
||||
[Constant]
|
||||
readonly attribute Element? root;
|
||||
readonly attribute Node? root;
|
||||
[Constant]
|
||||
readonly attribute DOMString rootMargin;
|
||||
[Constant,Cached]
|
||||
@ -57,7 +57,7 @@ dictionary IntersectionObserverEntryInit {
|
||||
};
|
||||
|
||||
dictionary IntersectionObserverInit {
|
||||
Element? root = null;
|
||||
(Element or Document)? root = null;
|
||||
DOMString rootMargin = "0px";
|
||||
(double or sequence<double>) threshold = 0;
|
||||
};
|
||||
|
@ -1749,6 +1749,11 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
- name: dom.IntersectionObserverExplicitDocumentRoot.enabled
|
||||
type: bool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
- name: dom.ipc.cancel_content_js_when_navigating
|
||||
type: bool
|
||||
value: true
|
||||
|
@ -1 +1 @@
|
||||
prefs: [dom.IntersectionObserver.enabled:true]
|
||||
prefs: [dom.IntersectionObserver.enabled:true, dom.IntersectionObserverExplicitDocumentRoot.enabled:true]
|
||||
|
@ -1,4 +0,0 @@
|
||||
[document-scrolling-element-root.html]
|
||||
[Observer with explicit root which is the document.]
|
||||
expected: FAIL
|
||||
|
Loading…
Reference in New Issue
Block a user