[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/1344263
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: Morten Stenshorne <mstensho@chromium.org>
Commit-Queue: vmpstr <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611264}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 5f5a7f6..6005aee7 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -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 @@
 
 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 @@
       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 @@
     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 @@
   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 @@
 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 @@
 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 @@
 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 @@
                                         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 @@
   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
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index e559092..ef2f0e1 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -93,6 +93,8 @@
   bool ShouldPaint() const;
   void DidPaint();
 
+  void DidAttachLayoutTree();
+
  private:
   friend class DisplayLockSuspendedHandle;
 
@@ -130,14 +132,18 @@
   // 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
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index f7e4b9856..41b0c1d 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2076,6 +2076,9 @@
   } 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 @@
 
   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 @@
 
   if (HasCustomStyleCallbacks())
     DidRecalcStyle(change);
+  NotifyDisplayLockDidRecalcStyle();
 }
 
 scoped_refptr<ComputedStyle> Element::PropagateInheritedProperties(
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 7c972e5..14c9bb6 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -475,6 +475,13 @@
            (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
            (!IsTablePart() || IsTableCaption()) && !IsTable();
   }
+  inline bool ShouldApplyStyleContainment() const {
+    return StyleRef().ContainsStyle();
+  }
+  inline bool ShouldApplyContentContainment() const {
+    return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment() &&
+           ShouldApplyStyleContainment();
+  }
 
  private:
   //////////////////////////////////////////
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index c756102..63263e8 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -1873,6 +1873,7 @@
   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 {
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index 4e8b48c..7369983 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -390,15 +390,16 @@
 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 ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 5609dd5..24a4f01 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -351,11 +351,6 @@
 
 # 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 ]
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-empty-expected.html b/third_party/blink/web_tests/display-lock/context-suspend-empty-expected.html
deleted file mode 100644
index 3e582be..0000000
--- a/third_party/blink/web_tests/display-lock/context-suspend-empty-expected.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  width: 100px;
-  height: 100px;
-  contain: content;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent"></div>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-expected.html b/third_party/blink/web_tests/display-lock/context-suspend-expected.html
deleted file mode 100644
index 40d1330..0000000
--- a/third_party/blink/web_tests/display-lock/context-suspend-expected.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  contain: paint;
-  width: 150px;
-  height: 150px;
-  background: lightblue;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent"></div>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-no-schedules-expected.html b/third_party/blink/web_tests/display-lock/context-suspend-no-schedules-expected.html
deleted file mode 100644
index 40d1330..0000000
--- a/third_party/blink/web_tests/display-lock/context-suspend-no-schedules-expected.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  contain: paint;
-  width: 150px;
-  height: 150px;
-  background: lightblue;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent"></div>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-resume-expected.html b/third_party/blink/web_tests/display-lock/context-suspend-resume-expected.html
deleted file mode 100644
index 0c922c7..0000000
--- a/third_party/blink/web_tests/display-lock/context-suspend-resume-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  contain: paint;
-  width: 150px;
-  height: 150px;
-  background: lightblue;
-}
-#child {
-  width: 50px;
-  height: 50px;
-  background: lightgreen;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/context-two-suspend-resume-expected.html b/third_party/blink/web_tests/display-lock/context-two-suspend-resume-expected.html
deleted file mode 100644
index 0c922c7..0000000
--- a/third_party/blink/web_tests/display-lock/context-two-suspend-resume-expected.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  contain: paint;
-  width: 150px;
-  height: 150px;
-  background: lightblue;
-}
-#child {
-  width: 50px;
-  height: 50px;
-  background: lightgreen;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.html
similarity index 66%
rename from third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.html
index 747bdf2..cbb263b 100644
--- a/third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.html
@@ -1,13 +1,13 @@
 <!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>
+
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.txt b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.txt
new file mode 100644
index 0000000..3973558
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-expected.txt
@@ -0,0 +1 @@
+CONSOLE ERROR: line 23: Uncaught Expected Exception
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.txt b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.txt
new file mode 100644
index 0000000..3973558
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container-expected.txt
@@ -0,0 +1 @@
+CONSOLE ERROR: line 23: Uncaught Expected Exception
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container.html
new file mode 100644
index 0000000..5a90f59
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws-removes-container.html
@@ -0,0 +1,45 @@
+<!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>
diff --git a/third_party/blink/web_tests/display-lock/acquire-callback-throws.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws.html
similarity index 72%
rename from third_party/blink/web_tests/display-lock/acquire-callback-throws.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws.html
index f07f320..e227724 100644
--- a/third_party/blink/web_tests/display-lock/acquire-callback-throws.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-callback-throws.html
@@ -5,8 +5,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 100px;
   height: 100px;
   background: lightblue;
@@ -14,14 +14,13 @@
 </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 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;
diff --git a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock-expected.html
similarity index 76%
rename from third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock-expected.html
index 0c922c7..358dfcb 100644
--- a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock-expected.html
@@ -1,7 +1,7 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/acquire-display-lock.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock.html
similarity index 75%
rename from third_party/blink/web_tests/display-lock/acquire-display-lock.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock.html
index fc397fd..b70f886 100644
--- a/third_party/blink/web_tests/display-lock/acquire-display-lock.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-display-lock.html
@@ -5,8 +5,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -19,7 +19,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -28,7 +27,7 @@
 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 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;
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails.html
new file mode 100644
index 0000000..7033b03
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-inline-fails.html
@@ -0,0 +1,40 @@
+<!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>
+
diff --git a/third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added-expected.html
similarity index 65%
copy from third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html
copy to third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added-expected.html
index 747bdf2..b8eb232 100644
--- a/third_party/blink/web_tests/display-lock/acquire-callback-throws-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added-expected.html
@@ -1,13 +1,12 @@
 <!doctype HTML>
 
 <style>
-#parent {
-  contain: paint;
+.contained {
+  contain: content;
   width: 100px;
   height: 100px;
   background: lightblue;
 }
 </style>
-
 <div id="log">PASS</div>
-<div id="parent"></div>
+<div class="contained"></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added.html
new file mode 100644
index 0000000..10e70a9
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-added.html
@@ -0,0 +1,43 @@
+<!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>
+
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails.html
new file mode 100644
index 0000000..904775b
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-on-no-containment-fails.html
@@ -0,0 +1,31 @@
+<!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>
+
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-empty.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty.html
similarity index 71%
rename from third_party/blink/web_tests/display-lock/context-suspend-empty.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty.html
index c4fa664..32444df 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend-empty.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-empty.html
@@ -6,15 +6,14 @@
 -->
 
 <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 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;
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-no-schedules.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules.html
similarity index 74%
rename from third_party/blink/web_tests/display-lock/context-suspend-no-schedules.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules.html
index 184a5a2..cbb8beb 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend-no-schedules.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-no-schedules.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -20,7 +20,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -29,7 +28,7 @@
 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 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;
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-resume-empty-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty-expected.html
similarity index 74%
rename from third_party/blink/web_tests/display-lock/context-suspend-resume-empty-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty-expected.html
index 3e582be..808c279 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend-resume-empty-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty-expected.html
@@ -1,12 +1,12 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-resume-empty.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty.html
similarity index 76%
rename from third_party/blink/web_tests/display-lock/context-suspend-resume-empty.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty.html
index 79e5fce..657d653 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend-resume-empty.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-empty.html
@@ -6,15 +6,14 @@
 -->
 
 <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 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;
diff --git a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-expected.html
similarity index 69%
copy from third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
copy to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-expected.html
index 0c922c7..ad35377 100644
--- a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/context-suspend-resume.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume.html
similarity index 76%
rename from third_party/blink/web_tests/display-lock/context-suspend-resume.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume.html
index 145e346..de2e980 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend-resume.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend-resume.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -25,7 +25,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -35,7 +34,7 @@
 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 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;
diff --git a/third_party/blink/web_tests/display-lock/context-suspend.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend.html
similarity index 76%
rename from third_party/blink/web_tests/display-lock/context-suspend.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-suspend.html
index f9f0656..3bbece4 100644
--- a/third_party/blink/web_tests/display-lock/context-suspend.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-suspend.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -20,7 +20,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -29,7 +28,8 @@
 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 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);
 }
 
diff --git a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume-expected.html
similarity index 69%
copy from third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
copy to third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume-expected.html
index 0c922c7..ad35377 100644
--- a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/context-two-suspend-resume.html b/third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume.html
similarity index 80%
rename from third_party/blink/web_tests/display-lock/context-two-suspend-resume.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume.html
index f091eb5..8dc73cb4 100644
--- a/third_party/blink/web_tests/display-lock/context-two-suspend-resume.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/context-two-suspend-resume.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -25,7 +25,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -35,7 +34,7 @@
 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 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;
diff --git a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context-expected.html
similarity index 69%
copy from third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
copy to third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context-expected.html
index 0c922c7..ad35377 100644
--- a/third_party/blink/web_tests/display-lock/acquire-display-lock-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context.html b/third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context.html
new file mode 100644
index 0000000..8cce7f6
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/element-retained-by-context.html
@@ -0,0 +1,63 @@
+<!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>
diff --git a/third_party/blink/web_tests/display-lock/multiple-schedules-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-expected.html
similarity index 88%
rename from third_party/blink/web_tests/display-lock/multiple-schedules-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-expected.html
index d672c18..a642ca2 100644
--- a/third_party/blink/web_tests/display-lock/multiple-schedules-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/multiple-schedules-recursive-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive-expected.html
similarity index 87%
rename from third_party/blink/web_tests/display-lock/multiple-schedules-recursive-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive-expected.html
index 87f4deb..e19ce30 100644
--- a/third_party/blink/web_tests/display-lock/multiple-schedules-recursive-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/multiple-schedules-recursive.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive.html
similarity index 83%
rename from third_party/blink/web_tests/display-lock/multiple-schedules-recursive.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive.html
index b79c71ae..ab977bc 100644
--- a/third_party/blink/web_tests/display-lock/multiple-schedules-recursive.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules-recursive.html
@@ -7,8 +7,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -21,7 +21,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -35,7 +34,7 @@
 }
 
 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 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>
 
-
-
diff --git a/third_party/blink/web_tests/display-lock/multiple-schedules.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules.html
similarity index 75%
rename from third_party/blink/web_tests/display-lock/multiple-schedules.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules.html
index 90e63c54..a9c4f79 100644
--- a/third_party/blink/web_tests/display-lock/multiple-schedules.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-schedules.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -30,7 +30,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -43,15 +42,15 @@
 }
 
 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 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>
 
-
diff --git a/third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1-expected.html
similarity index 85%
rename from third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1-expected.html
index c69add3..290e473 100644
--- a/third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/simple-schedule-1.html b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1.html
similarity index 75%
rename from third_party/blink/web_tests/display-lock/simple-schedule-1.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1.html
index 69892bb..4ad698f 100644
--- a/third_party/blink/web_tests/display-lock/simple-schedule-1.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-1.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -25,7 +25,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -38,11 +37,11 @@
 }
 
 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 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>
 
diff --git a/third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2-expected.html
similarity index 85%
copy from third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html
copy to third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2-expected.html
index c69add3..290e473 100644
--- a/third_party/blink/web_tests/display-lock/simple-schedule-1-expected.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2-expected.html
@@ -1,8 +1,8 @@
 <!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>
diff --git a/third_party/blink/web_tests/display-lock/simple-schedule-2.html b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2.html
similarity index 76%
rename from third_party/blink/web_tests/display-lock/simple-schedule-2.html
rename to third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2.html
index 77443e6..9602446 100644
--- a/third_party/blink/web_tests/display-lock/simple-schedule-2.html
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/simple-schedule-2.html
@@ -6,8 +6,8 @@
 -->
 
 <style>
-#parent {
-  contain: paint;
+#container {
+  contain: content;
   width: 150px;
   height: 150px;
   background: lightblue;
@@ -25,7 +25,6 @@
 </style>
 
 <div id="log"></div>
-<div id="parent"></div>
 
 <script>
 if (window.testRunner)
@@ -38,12 +37,12 @@
 }
 
 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 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>
 
diff --git a/third_party/blink/web_tests/display-lock/simple-schedule-2-expected.html b/third_party/blink/web_tests/display-lock/simple-schedule-2-expected.html
deleted file mode 100644
index c69add3..0000000
--- a/third_party/blink/web_tests/display-lock/simple-schedule-2-expected.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!doctype HTML>
-
-<style>
-#parent {
-  contain: paint;
-  width: 150px;
-  height: 150px;
-  background: lightblue;
-}
-#child1 {
-  width: 50px;
-  height: 50px;
-  background: lightgreen;
-}
-#child2 {
-  width: 50px;
-  height: 50px;
-  background: lightyellow;
-}
-</style>
-
-<div id="log">PASS</div>
-<div id="parent">
-  <div id="child1"></div>
-  <div id="child2"></div>
-</div>
diff --git a/third_party/blink/web_tests/virtual/display-lock/display-lock/acquire-callback-throws-expected.txt b/third_party/blink/web_tests/virtual/display-lock/display-lock/acquire-callback-throws-expected.txt
deleted file mode 100644
index 64e41f0..0000000
--- a/third_party/blink/web_tests/virtual/display-lock/display-lock/acquire-callback-throws-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-CONSOLE ERROR: line 24: Uncaught Error