Bug 1153322 - Implement Document.scrollingElement, r=bz

--HG--
extra : rebase_source : 733ede0178b80b518e488bf9768e57498080f0b2
This commit is contained in:
Olli Pettay 2016-01-27 02:44:05 +02:00
Родитель 94dd6e702f
Коммит baf69da299
7 изменённых файлов: 166 добавлений и 1 удалений

Просмотреть файл

@ -9,7 +9,7 @@
*/
#include "nsDocument.h"
#include "nsIDocumentInlines.h"
#include "mozilla/AnimationComparator.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/AutoRestore.h"
@ -10731,6 +10731,54 @@ nsDocument::CaretPositionFromPoint(float aX, float aY, nsISupports** aCaretPos)
return NS_OK;
}
static bool
IsPotentiallyScrollable(HTMLBodyElement* aBody)
{
// An element is potentially scrollable if all of the following conditions are
// true:
// The element has an associated CSS layout box.
nsIFrame* bodyFrame = aBody->GetPrimaryFrame();
if (!bodyFrame) {
return false;
}
// The element is not the HTML body element, or it is and the root element's
// used value of the overflow-x or overflow-y properties is not visible.
MOZ_ASSERT(aBody->GetParent() == aBody->OwnerDoc()->GetRootElement());
nsIFrame* parentFrame = aBody->GetParent()->GetPrimaryFrame();
if (parentFrame &&
parentFrame->StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE &&
parentFrame->StyleDisplay()->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) {
return false;
}
// The element's used value of the overflow-x or overflow-y properties is not
// visible.
if (bodyFrame->StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE &&
bodyFrame->StyleDisplay()->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) {
return false;
}
return true;
}
Element*
nsIDocument::GetScrollingElement()
{
if (GetCompatibilityMode() == eCompatibility_NavQuirks) {
FlushPendingNotifications(Flush_Layout);
HTMLBodyElement* body = GetBodyElement();
if (body && !IsPotentiallyScrollable(body)) {
return body;
}
return nullptr;
}
return GetRootElement();
}
void
nsIDocument::ObsoleteSheet(nsIURI *aSheetURI, ErrorResult& rv)
{

Просмотреть файл

@ -2544,6 +2544,8 @@ public:
already_AddRefed<nsDOMCaretPosition>
CaretPositionFromPoint(float aX, float aY);
Element* GetScrollingElement();
// QuerySelector and QuerySelectorAll already defined on nsINode
nsINodeList* GetAnonymousNodes(Element& aElement);
Element* GetAnonymousElementByAttribute(Element& aElement,

Просмотреть файл

@ -280,6 +280,9 @@ partial interface Document {
Element? elementFromPoint (float x, float y);
CaretPosition? caretPositionFromPoint (float x, float y);
[Pref="dom.document.scrollingElement.enabled"]
readonly attribute Element? scrollingElement;
};
// http://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html

Просмотреть файл

@ -206,6 +206,12 @@ pref("dom.url.getters_decode_hash", false);
// significantly increase the number of compartments in the system.
pref("dom.compartment_per_addon", true);
#ifdef NIGHTLY_BUILD
pref("dom.document.scrollingElement.enabled", true);
#else
pref("dom.document.scrollingElement.enabled", false);
#endif
// Fastback caching - if this pref is negative, then we calculate the number
// of content viewers to cache based on the amount of available memory.
pref("browser.sessionhistory.max_total_viewers", -1);

Просмотреть файл

@ -33330,6 +33330,12 @@
"deleted": [],
"items": {
"testharness": {
"cssom-view/scrollingElement.html": [
{
"path": "cssom-view/scrollingElement.html",
"url": "/cssom-view/scrollingElement.html"
}
],
"html/semantics/embedded-content/the-embed-element/embed-document.html": [
{
"path": "html/semantics/embedded-content/the-embed-element/embed-document.html",

Просмотреть файл

@ -0,0 +1,3 @@
[scrollingElement.html]
type: testharness
prefs: [dom.document.scrollingElement.enabled:true]

Просмотреть файл

@ -0,0 +1,97 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>cssom-view - scrollingElement</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe id="quirksframe"></iframe>
<iframe id="nonquirksframe"></iframe>
<div id="log"></div>
<script>
var quirksFrame;
var nonQuirksFrame;
function loadTestFrames(callback) {
quirksFrame = document.getElementById("quirksframe");
quirksFrame.onload = function() {
nonQuirksFrame = document.getElementById("nonquirksframe");
nonQuirksFrame.onload = callback;
nonQuirksFrame.src =
URL.createObjectURL(new Blob(["<!doctype html>"], { type: "text/html" }));
}
quirksFrame.src =
URL.createObjectURL(new Blob([""], { type: "text/html" }));
}
var test = async_test("Tests for scrollingElement");
loadTestFrames(function() {
test.step(function() {
var quirksDoc = quirksFrame.contentDocument;
var nonQuirksDoc = nonQuirksFrame.contentDocument;
// Initial checks that we have the expected kinds of documents.
assert_equals(quirksDoc.compatMode, "BackCompat", "Should be in quirks mode.");
assert_equals(nonQuirksDoc.compatMode, "CSS1Compat", "Should be in standards mode.");
assert_not_equals(quirksDoc.body, null, "Should have a body element");
assert_not_equals(nonQuirksDoc.body, null, "Should have a body element");
// Tests for quirks mode document.
assert_equals(quirksDoc.scrollingElement, quirksDoc.body,
"scrollingElement in quirks mode should default to body element.");
quirksDoc.documentElement.style.overflow = "scroll";
quirksDoc.body.style.overflow = "scroll";
assert_equals(quirksDoc.scrollingElement, null,
"scrollingElement in quirks mode should be null if overflow of body and root element isn't visible.");
quirksDoc.documentElement.style.overflow = "visible";
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
quirksDoc.documentElement.style.overflow = "scroll";
quirksDoc.body.style.overflow = "visible";
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
quirksDoc.documentElement.style.overflow = "visible";
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
quirksDoc.body.style.display = "none";
assert_equals(quirksDoc.scrollingElement, quirksDoc.body)
quirksDoc.body.style.display = "block";
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
quirksDoc.documentElement.appendChild(quirksDoc.createElement("body"));
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
assert_equals(quirksDoc.scrollingElement, quirksDoc.getElementsByTagName("body")[0]);
quirksDoc.documentElement.removeChild(quirksDoc.documentElement.lastChild);
assert_equals(quirksDoc.scrollingElement, quirksDoc.body);
quirksDoc.documentElement.removeChild(quirksDoc.body);
assert_equals(quirksDoc.scrollingElement, null);
quirksDoc.documentElement.appendChild(quirksDoc.createElementNS("foobarNS", "body"));
assert_equals(quirksDoc.scrollingElement, null);
quirksDoc.removeChild(quirksDoc.documentElement);
assert_equals(quirksDoc.scrollingElement, null);
quirksDoc.appendChild(quirksDoc.createElementNS("foobarNS", "html"));
quirksDoc.documentElement.appendChild(quirksDoc.createElement("body"));
assert_equals(quirksDoc.scrollingElement, null);
quirksDoc.removeChild(quirksDoc.documentElement);
quirksDoc.appendChild(quirksDoc.createElement("body"));
assert_equals(quirksDoc.scrollingElement, null);
// Tests for standards mode document.
assert_equals(nonQuirksDoc.scrollingElement, nonQuirksDoc.documentElement,
"scrollingElement in standards mode should be the document element.");
nonQuirksDoc.documentElement.style.overflow = "scroll";
nonQuirksDoc.body.style.overflow = "scroll";
assert_equals(nonQuirksDoc.scrollingElement, nonQuirksDoc.documentElement);
nonQuirksDoc.removeChild(nonQuirksDoc.documentElement);
assert_equals(nonQuirksDoc.scrollingElement, null);
nonQuirksDoc.appendChild(nonQuirksDoc.createElement("foobar"));
assert_equals(nonQuirksDoc.scrollingElement.localName, "foobar");
});
test.done();
});
</script>