Commit 1d74e21c authored by Kevin Ellis's avatar Kevin Ellis Committed by Commit Bot

Mark animation ready and finished promises as handled

Per spec, a rejected animation ready or finished promise should be
marked as handled. A small change was added to script promise property
to support marking the promise as handled.

Bug: 1066458
Change-Id: I22f1adaaf35a05d0730f72c892d67b6a3bf15e8b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2129774Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Commit-Queue: Kevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755165}
parent e1eae95f
......@@ -72,6 +72,8 @@ class ScriptPromiseProperty final
// suppress the check forcibly.
resolver->SuppressDetachCheck();
ScriptPromise promise = resolver->Promise();
if (mark_as_handled_)
promise.MarkAsHandled();
switch (state_) {
case kPending:
resolvers_.push_back(resolver);
......@@ -147,6 +149,14 @@ class ScriptPromiseProperty final
resolved_with_undefined_ = false;
}
// Mark generated promises as handled to avoid reporting unhandled rejections.
void MarkAsHandled() {
mark_as_handled_ = true;
for (auto& promise : promises_) {
promise.MarkAsHandled();
}
}
void Trace(Visitor* visitor) override {
TraceIfNeeded<ResolvedType>::Trace(visitor, resolved_);
TraceIfNeeded<RejectedType>::Trace(visitor, rejected_);
......@@ -164,6 +174,7 @@ class ScriptPromiseProperty final
HeapVector<Member<ScriptPromiseResolver>> resolvers_;
HeapVector<ScriptPromise> promises_;
bool resolved_with_undefined_ = false;
bool mark_as_handled_ = false;
DISALLOW_COPY_AND_ASSIGN(ScriptPromiseProperty);
};
......
......@@ -479,6 +479,47 @@ TEST_F(ScriptPromisePropertyGarbageCollectedTest, Reset) {
EXPECT_NE(old_actual, new_actual);
}
TEST_F(ScriptPromisePropertyGarbageCollectedTest, MarkAsHandled) {
{
// Unhandled promise.
ScriptState::Scope scope(MainScriptState());
ScriptPromise promise =
GetProperty()->Promise(DOMWrapperWorld::MainWorld());
GarbageCollectedScriptWrappable* reason =
MakeGarbageCollected<GarbageCollectedScriptWrappable>("reason");
GetProperty()->Reject(reason);
EXPECT_FALSE(promise.V8Value().As<v8::Promise>()->HasHandler());
}
GetProperty()->Reset();
{
// MarkAsHandled applies to newly created promises.
ScriptState::Scope scope(MainScriptState());
GetProperty()->MarkAsHandled();
ScriptPromise promise =
GetProperty()->Promise(DOMWrapperWorld::MainWorld());
GarbageCollectedScriptWrappable* reason =
MakeGarbageCollected<GarbageCollectedScriptWrappable>("reason");
GetProperty()->Reject(reason);
EXPECT_TRUE(promise.V8Value().As<v8::Promise>()->HasHandler());
}
GetProperty()->Reset();
{
// MarkAsHandled applies to previously vended promises.
ScriptState::Scope scope(MainScriptState());
ScriptPromise promise =
GetProperty()->Promise(DOMWrapperWorld::MainWorld());
GetProperty()->MarkAsHandled();
GarbageCollectedScriptWrappable* reason =
MakeGarbageCollected<GarbageCollectedScriptWrappable>("reason");
GetProperty()->Reject(reason);
EXPECT_TRUE(promise.V8Value().As<v8::Promise>()->HasHandler());
}
}
TEST_F(ScriptPromisePropertyNonScriptWrappableResolutionTargetTest,
ResolveWithUndefined) {
Test(ToV8UndefinedGenerator(), "undefined", __FILE__, __LINE__);
......
......@@ -1466,6 +1466,9 @@ ScriptPromise Animation::finished(ScriptState* script_state) {
if (!finished_promise_) {
finished_promise_ = MakeGarbageCollected<AnimationPromise>(
ExecutionContext::From(script_state));
// Do not report unhandled rejections of the finished promise.
finished_promise_->MarkAsHandled();
// Defer resolving the finished promise if the finish notification task is
// pending. The finished state could change before the next microtask
// checkpoint.
......@@ -1485,6 +1488,8 @@ ScriptPromise Animation::ready(ScriptState* script_state) {
if (!ready_promise_) {
ready_promise_ = MakeGarbageCollected<AnimationPromise>(
ExecutionContext::From(script_state));
// Do not report unhandled rejections of the ready promise.
ready_promise_->MarkAsHandled();
if (!is_pending)
ready_promise_->Resolve(this);
}
......
This is a testharness.js-based test.
Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: The user aborted a request.
PASS A new ready promise is created when setting animation-play-state: running
PASS ready promise is rejected when an animation is canceled by resetting the animation property
PASS ready promise is rejected when an animation is canceled by updating the animation property
PASS A new ready promise is created when setting animation-play-state: paused
PASS Pausing twice re-uses the same Promise
Harness: the test ran to completion.
This is a testharness.js-based test.
Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: The user aborted a request.
PASS Test pausing then playing does not change the finished promise
PASS Test restarting a finished animation
PASS Test restarting a reversed finished animation
PASS Test redundant finishing of animation
PASS Finished promise does not resolve when paused
PASS Finished promise does not resolve when pause-pending
PASS The finished promise is fulfilled with its Animation
PASS finished promise is rejected when an animation is canceled by calling cancel()
PASS canceling an already-finished animation replaces the finished promise
PASS Test finished promise changes for animation duration changes
PASS Test finished promise changes when playbackRate == 0
PASS Test finished promise resolves when reaching to the natural boundary.
PASS Test finished promise changes when a prior finished promise resolved and the animation falls out finished state
PASS Test no new finished promise generated when finished state is checked asynchronously
PASS Test new finished promise generated when finished state is checked synchronously
PASS Test synchronous finished promise resolved even if finished state is changed soon
PASS Test synchronous finished promise resolved even if asynchronous finished promise happens just before synchronous promise
PASS Test finished promise is not resolved when the animation falls out finished state immediately
PASS Test finished promise is not resolved once the animation falls out finished state even though the current finished promise is generated soon after animation state became finished
PASS Finished promise should be resolved after the ready promise is resolved
PASS Finished promise should be rejected after the ready promise is rejected
FAIL Finished promise does not report an unhandledrejection when rejected assert_unreached: Should not get an unhandled rejection Reached unreachable code
Harness: the test ran to completion.
This is a testharness.js-based test.
Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: The user aborted a request.
PASS A new ready promise is created when play()/pause() is called
PASS Redundant calls to play() do not generate new ready promise objects
PASS The ready promise is fulfilled with its Animation
FAIL The ready promise does not report an unhandledrejection when rejected assert_unreached: Should not get an unhandled rejection Reached unreachable code
Harness: the test ran to completion.
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