Bug 1389274 - Correct the behavior of Element.scrollIntoView to match the draft spec and pass web platform tests; r=annevk,bkelly

MozReview-Commit-ID: 3is36wstsdb

--HG--
extra : rebase_source : f4a7598aad5b04a2dcaf40d09ee7733b4d6982f6
This commit is contained in:
Thomas Wisniewski 2017-09-28 16:57:24 -04:00
Родитель f39cc5cc25
Коммит cdaa875696
9 изменённых файлов: 63 добавлений и 174 удалений

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

@ -728,19 +728,23 @@ Element::GetScrollFrame(nsIFrame **aStyledFrame, FlushType aFlushType)
}
void
Element::ScrollIntoView()
Element::ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject)
{
ScrollIntoView(ScrollIntoViewOptions());
}
void
Element::ScrollIntoView(bool aTop)
{
ScrollIntoViewOptions options;
if (!aTop) {
options.mBlock = ScrollLogicalPosition::End;
if (aObject.IsScrollIntoViewOptions()) {
return ScrollIntoView(aObject.GetAsScrollIntoViewOptions());
}
ScrollIntoView(options);
MOZ_DIAGNOSTIC_ASSERT(aObject.IsBoolean());
ScrollIntoViewOptions options;
if (aObject.GetAsBoolean()) {
options.mBlock = ScrollLogicalPosition::Start;
options.mInline = ScrollLogicalPosition::Nearest;
} else {
options.mBlock = ScrollLogicalPosition::End;
options.mInline = ScrollLogicalPosition::Nearest;
}
return ScrollIntoView(options);
}
void
@ -757,9 +761,41 @@ Element::ScrollIntoView(const ScrollIntoViewOptions &aOptions)
return;
}
int16_t vpercent = (aOptions.mBlock == ScrollLogicalPosition::Start)
? nsIPresShell::SCROLL_TOP
: nsIPresShell::SCROLL_BOTTOM;
int16_t vpercent = nsIPresShell::SCROLL_CENTER;
switch (aOptions.mBlock) {
case ScrollLogicalPosition::Start:
vpercent = nsIPresShell::SCROLL_TOP;
break;
case ScrollLogicalPosition::Center:
vpercent = nsIPresShell::SCROLL_CENTER;
break;
case ScrollLogicalPosition::End:
vpercent = nsIPresShell::SCROLL_BOTTOM;
break;
case ScrollLogicalPosition::Nearest:
vpercent = nsIPresShell::SCROLL_MINIMUM;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected ScrollLogicalPosition value");
}
int16_t hpercent = nsIPresShell::SCROLL_CENTER;
switch (aOptions.mInline) {
case ScrollLogicalPosition::Start:
hpercent = nsIPresShell::SCROLL_LEFT;
break;
case ScrollLogicalPosition::Center:
hpercent = nsIPresShell::SCROLL_CENTER;
break;
case ScrollLogicalPosition::End:
hpercent = nsIPresShell::SCROLL_RIGHT;
break;
case ScrollLogicalPosition::Nearest:
hpercent = nsIPresShell::SCROLL_MINIMUM;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected ScrollLogicalPosition value");
}
uint32_t flags = nsIPresShell::SCROLL_OVERFLOW_HIDDEN;
if (aOptions.mBehavior == ScrollBehavior::Smooth) {
@ -772,7 +808,9 @@ Element::ScrollIntoView(const ScrollIntoViewOptions &aOptions)
nsIPresShell::ScrollAxis(
vpercent,
nsIPresShell::SCROLL_ALWAYS),
nsIPresShell::ScrollAxis(),
nsIPresShell::ScrollAxis(
hpercent,
nsIPresShell::SCROLL_ALWAYS),
flags);
}

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

@ -1079,9 +1079,10 @@ public:
return slots ? slots->mShadowRoot.get() : nullptr;
}
void ScrollIntoView();
void ScrollIntoView(bool aTop);
private:
void ScrollIntoView(const ScrollIntoViewOptions &aOptions);
public:
void ScrollIntoView(const BooleanOrScrollIntoViewOptions& aObject);
void Scroll(double aXScroll, double aYScroll);
void Scroll(const ScrollToOptions& aOptions);
void ScrollTo(double aXScroll, double aYScroll);

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

@ -171,9 +171,10 @@ interface Element : Node {
};
// http://dev.w3.org/csswg/cssom-view/
enum ScrollLogicalPosition { "start", "end" };
enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
dictionary ScrollIntoViewOptions : ScrollOptions {
ScrollLogicalPosition block = "start";
ScrollLogicalPosition inline = "nearest";
};
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface
@ -182,8 +183,7 @@ partial interface Element {
DOMRect getBoundingClientRect();
// scrolling
void scrollIntoView(boolean top);
void scrollIntoView(optional ScrollIntoViewOptions options);
void scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg);
// None of the CSSOM attributes are [Pure], because they flush
attribute long scrollTop; // scroll on setting
attribute long scrollLeft; // scroll on setting

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

@ -337739,12 +337739,6 @@
{}
]
],
"cssom-view/scrollIntoView-empty-args.html": [
[
"/cssom-view/scrollIntoView-empty-args.html",
{}
]
],
"cssom-view/scrollIntoView-shadow.html": [
[
"/cssom-view/scrollIntoView-shadow.html",
@ -578704,10 +578698,6 @@
"987051cdbad355cbb1bbb8ea1030a3b17e533f09",
"manual"
],
"cssom-view/scrollIntoView-empty-args.html": [
"57e22136750f54145c37722674389590b7f340b6",
"testharness"
],
"cssom-view/scrollIntoView-shadow.html": [
"3c4a18992105fd7bf19cbf29f0b6d80cb12ca98c",
"testharness"

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

@ -1,11 +0,0 @@
[scrollIntoView-empty-args.html]
type: testharness
[scrollIntoView should behave correctly when the arg is not fully specified as ScrollIntoViewOptions]
expected: FAIL
[scrollIntoView should behave correctly when the arg is [object Object\]]
expected: FAIL
[scrollIntoView should behave correctly when the arg is null]
expected: FAIL

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

@ -1,5 +1,8 @@
[scrollIntoView-shadow.html]
type: testharness
[scrollIntoView should behave correctly if applies to shadow dom elements]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1293844
expected:
if stylo: FAIL
PASS

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

@ -1,11 +0,0 @@
[scrollIntoView-smooth.html]
type: testharness
[Smooth scrollIntoView should scroll the element to the 'nearest' position]
expected: FAIL
[Smooth scrollIntoView should scroll the element to the 'start' position]
expected: FAIL
[Smooth scrollIntoView should scroll the element to the 'center' position]
expected: FAIL

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

@ -1,38 +0,0 @@
[scrollintoview.html]
type: testharness
[scrollIntoView({block: "center", inline: "center"}) starting at left,top]
expected: FAIL
[scrollIntoView({block: "center", inline: "center"}) starting at left,bottom]
expected: FAIL
[scrollIntoView({block: "center", inline: "center"}) starting at right,top]
expected: FAIL
[scrollIntoView({block: "center", inline: "center"}) starting at right,bottom]
expected: FAIL
[scrollIntoView({block: "start", inline: "start"}) starting at left,top]
expected: FAIL
[scrollIntoView({block: "start", inline: "start"}) starting at left,bottom]
expected: FAIL
[scrollIntoView({block: "end", inline: "end"}) starting at right,top]
expected: FAIL
[scrollIntoView({block: "end", inline: "end"}) starting at right,bottom]
expected: FAIL
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at left,top]
expected: FAIL
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at left,bottom]
expected: FAIL
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at right,top]
expected: FAIL
[scrollIntoView({block: "nearest", inline: "nearest"}) starting at right,bottom]
expected: FAIL

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

@ -1,83 +0,0 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<title>Check End Position of scrollIntoView when arg is not fully specified</title>
<style>
#container {
position: relative;
height: 1000px;
width: 800px;
overflow: scroll;
}
#content {
position: absolute;
height: 500px;
width: 400px;
left: 1000px;
top: 1000px;
background-color: red;
}
</style>
<div id="container">
<div id="filler" style="height: 2500px; width: 2500px"></div>
<div id="content">I must become visible</div>
</div>
<script>
add_completion_callback(() => document.getElementById("container").remove());
var content = document.getElementById("content");
var container = document.getElementById("container");
var remaining_width = container.clientWidth - content.clientWidth;
var remaining_height = container.clientHeight - content.clientHeight;
function instantScrollToTestArgs(arg, expected_x, expected_y) {
test(t => {
container.scrollTop = container.scrollLeft = 0;
assert_not_equals(container.scrollLeft, expected_x);
assert_not_equals(container.scrollTop, expected_y);
if (arg == "omitted")
content.scrollIntoView();
else
content.scrollIntoView(arg);
assert_approx_equals(container.scrollTop, expected_y, 1, "verify scroll top");
assert_approx_equals(container.scrollLeft, expected_x, 1, "verify scroll left");
}, "scrollIntoView should behave correctly when the arg is " + arg);
}
// expected alignment: inline => nearest, block => start
instantScrollToTestArgs("omitted",
content.offsetLeft - remaining_width,
content.offsetTop);
// expected alignment: inline => nearest, block => start
instantScrollToTestArgs(true,
content.offsetLeft - remaining_width,
content.offsetTop);
// expected alignment: inline => nearest, block => end
instantScrollToTestArgs(false,
content.offsetLeft - remaining_width,
content.offsetTop - remaining_height);
// expected alignment: inline => center, block => center
instantScrollToTestArgs({},
content.offsetLeft - remaining_width / 2,
content.offsetTop - remaining_height / 2);
// expected alignment: inline => center, block => center
instantScrollToTestArgs(null,
content.offsetLeft - remaining_width / 2,
content.offsetTop - remaining_height / 2);
// expected alignment: inline => nearest, block => start
instantScrollToTestArgs(undefined,
content.offsetLeft - remaining_width,
content.offsetTop);
</script>