Commit ddc12b7e authored by Vladimir Levin's avatar Vladimir Levin Committed by Commit Bot

[DL] Update layout tests to be mode 2 tests.

This updates the layout test and some code changes to make those tests
pass to be mode 2 tests (ie append after lock).

R=chrishtr@chromium.org

Bug: 882663
Change-Id: I44554d486c5af0db1c680d5be719d687fd2745d2
Reviewed-on: https://chromium-review.googlesource.com/c/1344263Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Commit-Queue: vmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611264}
parent d3efa822
......@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/display_lock/display_lock_suspended_handle.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
......@@ -108,11 +109,12 @@ DisplayLockContext::~DisplayLockContext() {
void DisplayLockContext::Trace(blink::Visitor* visitor) {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
ScriptWrappable::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
visitor->Trace(callbacks_);
visitor->Trace(resolver_);
visitor->Trace(element_);
ScriptWrappable::Trace(visitor);
ActiveScriptWrappable::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
}
void DisplayLockContext::Dispose() {
......@@ -201,10 +203,14 @@ void DisplayLockContext::ProcessQueue() {
ALLOW_UNUSED_LOCAL(result);
if (try_catch.HasCaught()) {
RejectAndCleanUp();
// We should run the checkpoint here, since the rejection callback (for
// the promise rejected in RejectAndCleanUp()) may modify DOM which
// should happen here, as opposed to after a potential lifecycle update
// (or whenever the next microtask checkpoint is going to happen).
Microtask::PerformCheckpoint(callback->GetIsolate());
return;
}
}
Microtask::PerformCheckpoint(callback->GetIsolate());
}
if (callbacks_.IsEmpty() && state_ != kSuspended) {
......@@ -224,6 +230,14 @@ void DisplayLockContext::RejectAndCleanUp() {
resolver_ = nullptr;
}
callbacks_.clear();
// We may have a dirty subtree and have not propagated the dirty bit up the
// ancestor tree. Since we're now rejecting the promise and unlocking the
// element, ensure that we can reach both style and layout subtrees if they
// are dirty by propagating the bit.
if (element_->NeedsStyleRecalc() || element_->ChildNeedsStyleRecalc())
element_->MarkAncestorsWithChildNeedsStyleRecalc();
InvalidateElementLayout();
}
void DisplayLockContext::Resume() {
......@@ -296,6 +310,13 @@ void DisplayLockContext::DidStyle() {
if (state_ != kCommitting)
return;
// We must have contain: content for display locking.
auto* style = element_->GetComputedStyle();
if (!style || !style->ContainsContent()) {
RejectAndCleanUp();
return;
}
if (lifecycle_update_state_ <= kNeedsStyle)
lifecycle_update_state_ = kNeedsLayout;
}
......@@ -303,7 +324,7 @@ void DisplayLockContext::DidStyle() {
bool DisplayLockContext::ShouldLayout() const {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
return std::tie(state_, lifecycle_update_state_) >=
std::tuple<State, LifecycleUpdateState>(kCommitting, kNeedsLayout);
std::tuple<State, LifecycleUpdateState>{kCommitting, kNeedsLayout};
}
void DisplayLockContext::DidLayout() {
......@@ -318,7 +339,7 @@ void DisplayLockContext::DidLayout() {
bool DisplayLockContext::ShouldPrePaint() const {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
return std::tie(state_, lifecycle_update_state_) >=
std::tuple<State, LifecycleUpdateState>(kCommitting, kNeedsPrePaint);
std::tuple<State, LifecycleUpdateState>{kCommitting, kNeedsPrePaint};
}
void DisplayLockContext::DidPrePaint() {
......@@ -336,7 +357,7 @@ void DisplayLockContext::DidPrePaint() {
bool DisplayLockContext::ShouldPaint() const {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
return std::tie(state_, lifecycle_update_state_) >=
std::tuple<State, LifecycleUpdateState>(kCommitting, kNeedsPaint);
std::tuple<State, LifecycleUpdateState>{kCommitting, kNeedsPaint};
}
void DisplayLockContext::DidPaint() {
......@@ -358,6 +379,18 @@ void DisplayLockContext::DidPaint() {
WrapWeakPersistent(this)));
}
void DisplayLockContext::DidAttachLayoutTree() {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
// Note that although we checked at style recalc time that the element has
// "contain: content", it might not actually apply the containment (e.g. see
// ShouldApplyContentContainment()). This confirms that containment should
// apply.
auto* layout_object = element_->GetLayoutObject();
if (!layout_object || !layout_object->ShouldApplyContentContainment())
RejectAndCleanUp();
}
void DisplayLockContext::FinishResolution() {
SCOPED_LOGGER(__PRETTY_FUNCTION__);
if (state_ == kResolving)
......@@ -375,18 +408,27 @@ void DisplayLockContext::StartCommit() {
else
DidStyle();
if (state_ != kCommitting)
return;
// Also ensure we reach it for layout.
// TODO(vmpstr): This should just mark the ancestor chain if needed.
element_->GetLayoutObject()->SetNeedsLayout(
layout_invalidation_reason::kDisplayLockCommitting);
if (auto* parent = element_->GetLayoutObject()->Parent()) {
parent->SetNeedsLayout(layout_invalidation_reason::kDisplayLockCommitting);
}
InvalidateElementLayout();
// Schedule an animation to perform the lifecycle phases.
element_->GetDocument().GetPage()->Animator().ScheduleVisualUpdate(
element_->GetDocument().GetFrame());
DCHECK(element_->GetLayoutObject());
}
void DisplayLockContext::InvalidateElementLayout() {
if (auto* layout_object = element_->GetLayoutObject()) {
layout_object->SetNeedsLayout(
layout_invalidation_reason::kDisplayLockCommitting);
if (auto* parent = layout_object->Parent()) {
parent->SetNeedsLayout(
layout_invalidation_reason::kDisplayLockCommitting);
}
}
}
} // namespace blink
......@@ -93,6 +93,8 @@ class CORE_EXPORT DisplayLockContext final
bool ShouldPaint() const;
void DidPaint();
void DidAttachLayoutTree();
private:
friend class DisplayLockSuspendedHandle;
......@@ -130,14 +132,18 @@ class CORE_EXPORT DisplayLockContext final
// Initiate a commit.
void StartCommit();
// Invalidates the layout of the element, making sure that the layout code can
// reach it.
void InvalidateElementLayout();
HeapVector<Member<V8DisplayLockCallback>> callbacks_;
Member<ScriptPromiseResolver> resolver_;
WeakMember<Element> element_;
Member<Element> element_;
bool process_queue_task_scheduled_ = false;
unsigned suspended_count_ = 0;
State state_ = kUninitialized;
LifecycleUpdateState lifecycle_update_state_ = kNeedsLayout;
LifecycleUpdateState lifecycle_update_state_ = kNeedsStyle;
};
} // namespace blink
......
......@@ -2076,6 +2076,9 @@ void Element::AttachLayoutTree(AttachContext& context) {
} else {
context.previous_in_flow = children_context.previous_in_flow;
}
if (auto* display_lock_context = GetDisplayLockContext())
display_lock_context->DidAttachLayoutTree();
}
void Element::DetachLayoutTree(const AttachContext& context) {
......@@ -2212,7 +2215,6 @@ void Element::RecalcStyle(StyleRecalcChange change) {
if (StyleRecalcBlockedByDisplayLock())
return;
NotifyDisplayLockDidRecalcStyle();
// If we are re-attaching in a Shadow DOM v0 tree, we recalc down to the
// distributed nodes to propagate kReattach down the flat tree (See
......@@ -2315,6 +2317,7 @@ void Element::RecalcStyle(StyleRecalcChange change) {
if (HasCustomStyleCallbacks())
DidRecalcStyle(change);
NotifyDisplayLockDidRecalcStyle();
}
scoped_refptr<ComputedStyle> Element::PropagateInheritedProperties(
......
......@@ -475,6 +475,13 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
(!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
(!IsTablePart() || IsTableCaption()) && !IsTable();
}
inline bool ShouldApplyStyleContainment() const {
return StyleRef().ContainsStyle();
}
inline bool ShouldApplyContentContainment() const {
return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment() &&
ShouldApplyStyleContainment();
}
private:
//////////////////////////////////////////
......
......@@ -1873,6 +1873,7 @@ class ComputedStyle : public ComputedStyleBase,
bool ContainsStyle() const { return Contain() & kContainsStyle; }
bool ContainsLayout() const { return Contain() & kContainsLayout; }
bool ContainsSize() const { return Contain() & kContainsSize; }
bool ContainsContent() const { return Contain() & kContainsContent; }
// Display utility functions.
bool IsDisplayReplacedType() const {
......
......@@ -390,15 +390,16 @@ crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-doc
crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ]
crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ]
crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ]
crbug.com/591099 virtual/display-lock/display-lock/acquire-callback-throws.html [ Pass ]
crbug.com/591099 virtual/display-lock/display-lock/acquire-display-lock.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/context-suspend-resume-empty.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/context-suspend-resume.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/context-two-suspend-resume.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/multiple-schedules-recursive.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/multiple-schedules.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/simple-schedule-1.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/simple-schedule-2.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-display-lock.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/acquire-on-no-containment-added.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-suspend-resume-empty.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-suspend-resume.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/context-two-suspend-resume.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/element-retained-by-context.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/multiple-schedules-recursive.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/multiple-schedules.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/simple-schedule-1.html [ Timeout ]
crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/simple-schedule-2.html [ Timeout ]
crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ]
crbug.com/591099 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ]
......
......@@ -351,11 +351,6 @@ crbug.com/414283 virtual/fractional_scrolling_threaded/fast/scrolling/fractional
# Display locking, currently only available via a virtual test.
crbug.com/882663 display-lock [ Skip ]
# The following tests (and maybe the rest of them) need to be re-written to not rely on stale pixels.
# In other words, the tests should only test the lock-before-append mode.
crbug.com/882663 virtual/display-lock/display-lock/acquire-callback-throws.html [ Failure ]
crbug.com/882663 virtual/display-lock/display-lock/context-suspend-no-schedules.html [ Failure ]
crbug.com/882663 virtual/display-lock/display-lock/context-suspend.html [ Failure ]
# Sheriff 2018/05/25
crbug.com/846747 http/tests/navigation/navigation-interrupted-by-fragment.html [ Pass Timeout ]
......
<!doctype HTML>
<style>
#parent {
contain: paint;
width: 150px;
height: 150px;
background: lightblue;
}
</style>
<div id="log">PASS</div>
<div id="parent"></div>
<!doctype HTML>
<style>
#parent {
contain: paint;
width: 150px;
height: 150px;
background: lightblue;
}
</style>
<div id="log">PASS</div>
<div id="parent"></div>
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 100px;
height: 100px;
background: lightblue;
}
</style>
<div id="log">PASS</div>
<div id="parent"></div>
<div id="container"></div>
<!doctype HTML>
<!--
Runs an acquireDisplayLock, the callback throws.
-->
<style>
#container {
contain: content;
width: 100px;
height: 100px;
background: lightblue;
}
</style>
<div id="log"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function throwingFunction(context) {
throw "Expected Exception";
}
function finishTest(status_string, to_remove) {
if (document.getElementById("log").innerHTML === "")
document.getElementById("log").innerHTML = status_string;
if (to_remove)
to_remove.remove();
if (window.testRunner)
window.testRunner.notifyDone();
}
function acquire() {
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(throwingFunction).then(
() => { finishTest("FAIL"); },
() => { finishTest("PASS", container); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
......@@ -5,8 +5,8 @@ Runs an acquireDisplayLock, the callback throws.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 100px;
height: 100px;
background: lightblue;
......@@ -14,14 +14,13 @@ Runs an acquireDisplayLock, the callback throws.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function throwingFunction(context) {
throw "Error";
throw "Expected Exception";
}
function finishTest(status_string) {
......@@ -32,9 +31,12 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(throwingFunction).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(throwingFunction).then(
() => { finishTest("FAIL"); },
() => { finishTest("PASS"); });
document.body.appendChild(container);
}
window.onload = acquire;
......
<!doctype HTML>
<style>
#parent {
#container {
contain: paint;
width: 150px;
height: 150px;
......@@ -15,4 +15,4 @@
</style>
<div id="log">PASS</div>
<div id="parent"><div id="child"></div></div>
<div id="container"><div id="child"></div></div>
......@@ -5,8 +5,8 @@ Runs an acquireDisplayLock, which appends a child.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -19,7 +19,6 @@ Runs an acquireDisplayLock, which appends a child.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -28,7 +27,7 @@ if (window.testRunner)
function modifyDom(context) {
let child = document.createElement("div");
child.id = "child";
document.getElementById("parent").appendChild(child);
context.lockedElement.appendChild(child);
}
function finishTest(status_string) {
......@@ -39,9 +38,12 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(modifyDom).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(modifyDom).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
......
<!doctype HTML>
<!--
Runs an acquireDisplayLock on an element that doesn't has contain: paint, but
is an inline, which means we won't actually apply paint containment.
This rejects the promise.
-->
<style>
#container {
contain: content;
}
</style>
<div id="log"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function finishTest(status_string) {
if (document.getElementById("log").innerHTML === "")
document.getElementById("log").innerHTML = status_string;
if (window.testRunner)
window.testRunner.notifyDone();
}
function acquire() {
let container = document.createElement("span");
container.id = "container";
container.acquireDisplayLock((context) => {}).then(
() => { finishTest("FAIL"); },
() => { finishTest("PASS"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
<!doctype HTML>
<style>
#parent {
.contained {
contain: content;
width: 100px;
height: 100px;
contain: content;
background: lightblue;
}
</style>
<div id="log">PASS</div>
<div id="parent"></div>
<div class="contained"></div>
<!doctype HTML>
<!--
Runs an acquireDisplayLock on an element that doesn't have containment.
The callback adds containment.
-->
<style>
.contained {
contain: content;
width: 100px;
height: 100px;
background: lightblue;
}
</style>
<div id="log"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function addContainment(context) {
context.lockedElement.classList = "contained";
}
function finishTest(status_string) {
if (document.getElementById("log").innerHTML === "")
document.getElementById("log").innerHTML = status_string;
if (window.testRunner)
window.testRunner.notifyDone();
}
function acquire() {
let container = document.createElement("div");
container.acquireDisplayLock(addContainment).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
<!doctype HTML>
<!--
Runs an acquireDisplayLock on an element that doesn't have containment.
This rejects the promise.
-->
<div id="log"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function finishTest(status_string) {
if (document.getElementById("log").innerHTML === "")
document.getElementById("log").innerHTML = status_string;
if (window.testRunner)
window.testRunner.notifyDone();
}
function acquire() {
let container = document.createElement("div");
container.acquireDisplayLock((context) => {}).then(
() => { finishTest("FAIL"); },
() => { finishTest("PASS"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
......@@ -6,15 +6,14 @@ The associated promise should never resolve.
-->
<style>
#parent {
#container {
contain: content;
width: 100px;
height: 100px;
contain: content;
}
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -28,13 +27,13 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(
(context) => {
context.suspend();
}).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock((context) => { context.suspend(); }).then(
() => { finishTest("FAIL"); },
() => { finishTest("FAIL"); });
setTimeout(() => { finishTest("PASS"); }, 50);
document.body.appendChild(container);
setTimeout(() => { finishTest("PASS"); }, 100);
}
window.onload = acquire;
......
......@@ -6,8 +6,8 @@ DOM changes should never be visible.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -20,7 +20,6 @@ DOM changes should never be visible.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -29,7 +28,7 @@ if (window.testRunner)
function modifyDom(context) {
let child = document.createElement("div");
child.id = "child";
document.getElementById("parent").appendChild(child);
context.lockedElement.appendChild(child);
}
function finishTest(status_string) {
......@@ -40,14 +39,17 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(
(context) => {
modifyDom();
modifyDom(context);
context.suspend();
}).then(
() => { finishTest("FAIL"); },
() => { finishTest("FAIL"); });
setTimeout(() => { finishTest("PASS"); }, 50);
document.body.appendChild(container);
setTimeout(() => { finishTest("PASS"); }, 100);
}
window.onload = acquire;
......
<!doctype HTML>
<style>
#parent {
#container {
contain: content;
width: 100px;
height: 100px;
contain: content;
}
</style>
<div id="log">PASS</div>
<div id="parent"></div>
<div id="container"></div>
......@@ -6,15 +6,14 @@ The context is then resumed which is when the promise resolves.
-->
<style>
#parent {
#container {
contain: content;
width: 100px;
height: 100px;
contain: content;
}
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -29,17 +28,19 @@ function finishTest(status_string) {
function acquire() {
let current_status = "FAIL";
let resume_handle = undefined;
document.getElementById("parent").acquireDisplayLock(
(context) => {
resume_handle = context.suspend();
let resume_handle;
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock((context) => {
resume_handle = context.suspend();
}).then(
() => { finishTest(current_status); },
() => { finishTest("FAIL - rejected"); });
document.body.appendChild(container);
setTimeout(() => {
current_status = "PASS";
resume_handle.resume();
}, 50);
}, 100);
}
window.onload = acquire;
......
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -15,4 +15,4 @@
</style>
<div id="log">PASS</div>
<div id="parent"><div id="child"></div></div>
<div id="container"><div id="child"></div></div>
......@@ -6,8 +6,8 @@ a continuation; later resumes the context.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -25,7 +25,6 @@ a continuation; later resumes the context.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -35,7 +34,7 @@ var child_class = "fail_child";
function modifyDom(context) {
let child = document.createElement("div");
child.id = child_class;
document.getElementById("parent").appendChild(child);
context.lockedElement.appendChild(child);
}
function finishTest(status_string) {
......@@ -47,20 +46,21 @@ function finishTest(status_string) {
function acquire() {
let current_status = "FAIL";
let resume_handle = undefined;
document.getElementById("parent").acquireDisplayLock(
(context) => {
context.schedule(modifyDom);
resume_handle = context.suspend();
let resume_handle;
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock((context) => {
context.schedule(modifyDom);
resume_handle = context.suspend();
}).then(
() => { finishTest(current_status); },
() => { finishTest("FAIL - rejected"); });
document.body.appendChild(container);
setTimeout(() => {
current_status = "PASS";
child_class = "pass_child";
resume_handle.resume();
}, 50);
}, 100);
}
window.onload = acquire;
......
......@@ -6,8 +6,8 @@ a continuation, which should never run.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -20,7 +20,6 @@ a continuation, which should never run.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -29,7 +28,8 @@ if (window.testRunner)
function modifyDom(context) {
let child = document.createElement("div");
child.id = "child";
document.getElementById("parent").appendChild(child);
// Append to body directly so it's clear whether this runs or not.
document.body.appendChild(child);
}
function finishTest(status_string) {
......@@ -40,13 +40,16 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(
(context) => {
context.schedule(modifyDom);
context.suspend();
}).then(
() => { finishTest("FAIL"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
setTimeout(() => { finishTest("PASS"); }, 50);
}
......
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -15,4 +15,4 @@
</style>
<div id="log">PASS</div>
<div id="parent"><div id="child"></div></div>
<div id="container"><div id="child"></div></div>
......@@ -6,8 +6,8 @@ a continuation; later resumes the context (twice).
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -25,7 +25,6 @@ a continuation; later resumes the context (twice).
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -35,7 +34,7 @@ var child_class = "fail_child";
function modifyDom(context) {
let child = document.createElement("div");
child.id = child_class;
document.getElementById("parent").appendChild(child);
context.lockedElement.appendChild(child);
}
function finishTest(status_string) {
......@@ -47,25 +46,26 @@ function finishTest(status_string) {
function acquire() {
let current_status = "FAIL";
let resume_handle1 = undefined;
let resume_handle2 = undefined;
document.getElementById("parent").acquireDisplayLock(
(context) => {
let resume_handle1;
let resume_handle2;
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock((context) => {
context.schedule(modifyDom);
resume_handle1 = context.suspend();
resume_handle2 = context.suspend();
}).then(
() => { finishTest(current_status); },
() => { finishTest("FAIL - rejected"); });
document.body.appendChild(container);
setTimeout(() => {
resume_handle1.resume();
setTimeout(() => {
current_status = "PASS";
child_class = "pass_child";
resume_handle2.resume();
}, 50);
}, 50);
}, 100);
}, 100);
}
window.onload = acquire;
......
<!doctype HTML>
<style>
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
}
#child {
width: 50px;
height: 50px;
background: lightgreen;
}
</style>
<div id="log">PASS</div>
<div id="container"><div id="child"></div></div>
<!doctype HTML>
<!--
Suspends a context with a continuation to append locked element. Before resuming,
calls gc to ensure that we still retain the locked element.
-->
<style>
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
}
#child {
width: 50px;
height: 50px;
background: lightgreen;
}
</style>
<div id="log"></div>
<script>
if (window.testRunner)
window.testRunner.waitUntilDone();
function appendLockedToBody(context) {
document.body.appendChild(context.lockedElement);
}
function scheduleAndSuspend(context) {
let child = document.createElement("div");
child.id = "child";
context.lockedElement.appendChild(child);
context.schedule(appendLockedToBody);
return context.suspend();
}
function finishTest(status_string) {
if (document.getElementById("log").innerHTML === "")
document.getElementById("log").innerHTML = status_string;
if (window.testRunner)
window.testRunner.notifyDone();
}
function acquire() {
let container = document.createElement("div");
container.id = "container";
let resume_handle;
container.acquireDisplayLock((context) => {
resume_handle = scheduleAndSuspend(context);
}).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
setTimeout(() => {
gc();
resume_handle.resume();
}, 100);
}
window.onload = acquire;
</script>
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -25,7 +25,7 @@
</style>
<div id="log">PASS</div>
<div id="parent">
<div id="container">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3"></div>
......
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -15,7 +15,7 @@
</style>
<div id="log">PASS</div>
<div id="parent">
<div id="container">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
......
......@@ -7,8 +7,8 @@ as scheduling two more continuations each, for a total of 7 children.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -21,7 +21,6 @@ as scheduling two more continuations each, for a total of 7 children.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -35,7 +34,7 @@ function createChild(id) {
}
function addChild(id, context) {
document.getElementById("parent").appendChild(createChild(id));
context.lockedElement.appendChild(createChild(id));
if (id > 3)
return;
context.schedule((context) => { addChild(id * 2, context); });
......@@ -50,15 +49,15 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(
(context) => { addChild(1, context) }).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
......@@ -6,8 +6,8 @@ continuations, which append the second and the third children.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -30,7 +30,6 @@ continuations, which append the second and the third children.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -43,15 +42,15 @@ function createChild(id) {
}
function addChild3(context) {
document.getElementById("parent").appendChild(createChild("child3"));
context.lockedElement.appendChild(createChild("child3"));
}
function addChild2(context) {
document.getElementById("parent").appendChild(createChild("child2"));
context.lockedElement.appendChild(createChild("child2"));
}
function addChild1(context) {
document.getElementById("parent").appendChild(createChild("child1"));
context.lockedElement.appendChild(createChild("child1"));
context.schedule(addChild2);
context.schedule(addChild3);
}
......@@ -64,13 +63,14 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(addChild1).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(addChild1).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -20,7 +20,7 @@
</style>
<div id="log">PASS</div>
<div id="parent">
<div id="container">
<div id="child1"></div>
<div id="child2"></div>
</div>
......@@ -6,8 +6,8 @@ continuation, which in turn appends the second child.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -25,7 +25,6 @@ continuation, which in turn appends the second child.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -38,11 +37,11 @@ function createChild(id) {
}
function addChild2(context) {
document.getElementById("parent").appendChild(createChild("child2"));
context.lockedElement.appendChild(createChild("child2"));
}
function addChild1(context) {
document.getElementById("parent").appendChild(createChild("child1"));
context.lockedElement.appendChild(createChild("child1"));
context.schedule(addChild2);
}
......@@ -54,12 +53,14 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(addChild1).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(addChild1).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
<!doctype HTML>
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -20,7 +20,7 @@
</style>
<div id="log">PASS</div>
<div id="parent">
<div id="container">
<div id="child1"></div>
<div id="child2"></div>
</div>
......@@ -6,8 +6,8 @@ appends the first child. The continuation appends the second child.
-->
<style>
#parent {
contain: paint;
#container {
contain: content;
width: 150px;
height: 150px;
background: lightblue;
......@@ -25,7 +25,6 @@ appends the first child. The continuation appends the second child.
</style>
<div id="log"></div>
<div id="parent"></div>
<script>
if (window.testRunner)
......@@ -38,12 +37,12 @@ function createChild(id) {
}
function addChild2(context) {
document.getElementById("parent").appendChild(createChild("child2"));
context.lockedElement.appendChild(createChild("child2"));
}
function addChild1(context) {
context.schedule(addChild2);
document.getElementById("parent").appendChild(createChild("child1"));
context.lockedElement.appendChild(createChild("child1"));
}
function finishTest(status_string) {
......@@ -54,12 +53,14 @@ function finishTest(status_string) {
}
function acquire() {
document.getElementById("parent").acquireDisplayLock(addChild1).then(
let container = document.createElement("div");
container.id = "container";
container.acquireDisplayLock(addChild1).then(
() => { finishTest("PASS"); },
() => { finishTest("FAIL"); });
document.body.appendChild(container);
}
window.onload = acquire;
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment