Commit 3df81bcb authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

Make ScriptRunner a ContextLifecycleStateObserver

ScriptRunner has special cases in Document to allow it to
pause/unpause, but ContextLifecycleStateObserver is the standard way
to pause/unpause.

Bug: 1029822
Change-Id: Ie8b5e427e6a217ba6a1aad9af7a286ce22444918
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1949225Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Nate Chapin <japhet@chromium.org>
Auto-Submit: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#722506}
parent a6919374
......@@ -7293,15 +7293,11 @@ void Document::AddConsoleMessageImpl(ConsoleMessage* console_message,
}
void Document::TasksWerePaused() {
GetScriptRunner()->Suspend();
if (scripted_animation_controller_)
scripted_animation_controller_->Pause();
}
void Document::TasksWereUnpaused() {
GetScriptRunner()->Resume();
if (scripted_animation_controller_)
scripted_animation_controller_->Unpause();
}
......
......@@ -35,13 +35,16 @@
#include "third_party/blink/renderer/platform/scheduler/public/cooperative_scheduling_manager.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
ScriptRunner::ScriptRunner(Document* document)
: document_(document),
: ContextLifecycleStateObserver(document),
document_(document),
task_runner_(document->GetTaskRunner(TaskType::kNetworking)) {
DCHECK(document);
UpdateStateIfNeeded();
}
void ScriptRunner::QueueScriptForExecution(PendingScript* pending_script) {
......@@ -70,18 +73,17 @@ void ScriptRunner::PostTask(const base::Location& web_trace_location) {
WTF::Bind(&ScriptRunner::ExecuteTask, WrapWeakPersistent(this)));
}
void ScriptRunner::Suspend() {
is_suspended_ = true;
}
void ScriptRunner::Resume() {
DCHECK(is_suspended_);
is_suspended_ = false;
void ScriptRunner::ContextLifecycleStateChanged(
mojom::FrameLifecycleState state) {
if (!IsExecutionSuspended())
PostTasksForReadyScripts(FROM_HERE);
}
bool ScriptRunner::IsExecutionSuspended() {
return !GetExecutionContext() || GetExecutionContext()->IsContextPaused() ||
is_force_deferred_;
}
void ScriptRunner::SetForceDeferredExecution(bool force_deferred) {
DCHECK(force_deferred != is_force_deferred_);
......@@ -260,6 +262,7 @@ void ScriptRunner::ExecuteTask() {
}
void ScriptRunner::Trace(Visitor* visitor) {
ContextLifecycleStateObserver::Trace(visitor);
visitor->Trace(document_);
visitor->Trace(pending_in_order_scripts_);
visitor->Trace(pending_async_scripts_);
......
......@@ -30,6 +30,7 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
......@@ -42,7 +43,10 @@ class PendingScript;
class ScriptLoader;
class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
public ContextLifecycleStateObserver,
public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptRunner);
public:
explicit ScriptRunner(Document*);
......@@ -51,14 +55,14 @@ class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
return !pending_in_order_scripts_.IsEmpty() ||
!pending_async_scripts_.IsEmpty();
}
void Suspend();
void Resume();
void SetForceDeferredExecution(bool force_deferred);
void NotifyScriptReady(PendingScript*);
void ContextLifecycleStateChanged(mojom::FrameLifecycleState) final;
static void MovePendingScript(Document&, Document&, ScriptLoader*);
void Trace(Visitor*);
void Trace(Visitor*) override;
const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
private:
......@@ -81,7 +85,7 @@ class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
void ExecuteTask();
bool IsExecutionSuspended() { return is_suspended_ || is_force_deferred_; }
bool IsExecutionSuspended();
Member<Document> document_;
......@@ -96,8 +100,6 @@ class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
int number_of_in_order_scripts_with_pending_notification_ = 0;
bool is_suspended_ = false;
// Whether script execution is suspended due to there being force deferred
// scripts that have not yet been executed. This is expected to be in sync
// with HTMLParserScriptRunner::suspended_async_script_execution_.
......
......@@ -327,8 +327,10 @@ TEST_F(ScriptRunnerTest, ResumeAndSuspend_InOrder) {
NotifyScriptReady(pending_script3);
platform_->RunSingleTask();
script_runner_->Suspend();
script_runner_->Resume();
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kPaused);
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
// Make sure elements are correct and in right order.
......@@ -356,8 +358,10 @@ TEST_F(ScriptRunnerTest, ResumeAndSuspend_Async) {
.WillOnce(InvokeWithoutArgs([this] { order_.push_back(3); }));
platform_->RunSingleTask();
script_runner_->Suspend();
script_runner_->Resume();
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kPaused);
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
// Make sure elements are correct.
......@@ -400,12 +404,14 @@ TEST_F(ScriptRunnerTest, SetForceDeferredAndResumeAndSuspend) {
platform_->RunSingleTask();
ASSERT_EQ(0u, order_.size());
script_runner_->Suspend();
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kPaused);
platform_->RunSingleTask();
ASSERT_EQ(0u, order_.size());
// Resume will not execute script while still in ForceDeferred state.
script_runner_->Resume();
// Resuming will not execute script while still in ForceDeferred state.
script_runner_->ContextLifecycleStateChanged(
mojom::FrameLifecycleState::kRunning);
platform_->RunUntilIdle();
ASSERT_EQ(0u, order_.size());
......
Tests that reparenting media elements also reparents ActiveDOMObject.
Before Reparenting
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '1' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '4' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '2' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '5' and is.
After Reparenting
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '4' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '2' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(document) should be '5' and is.
PASS: internals.contextLifecycleStateObserverObjectCount(iframe) should be '3' and is.
......@@ -10,8 +10,8 @@
window.iframe = document.querySelector('iframe').contentDocument;
log('Before Reparenting');
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 1);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 4);
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 2);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 5);
document.body.appendChild(window.iframe.querySelector('video'));
......@@ -20,8 +20,8 @@
// but a new one will be created in |document|, so the count is expected
// to differ by one.
log('After Reparenting');
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 4);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 2);
shouldBe('internals.contextLifecycleStateObserverObjectCount(document)', 5);
shouldBe('internals.contextLifecycleStateObserverObjectCount(iframe)', 3);
}
</script>
</body>
......
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