Bug 1768275 - Use SetAnyPromiseIsHandled instead of SetSettledPromiseIsHandled for promise that's not guaranteed to be not-yet-resolved. r=birtles

Differential Revision: https://phabricator.services.mozilla.com/D146032
This commit is contained in:
Tooru Fujisawa 2022-05-11 16:51:52 +00:00
Родитель f8ed722831
Коммит 99809832ac
2 изменённых файлов: 74 добавлений и 2 удалений

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

@ -550,7 +550,8 @@ void Animation::Cancel(PostRestyleMode aPostRestyle) {
if (mFinished) {
mFinished->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
mFinished->SetSettledPromiseIsHandled();
// mFinished can already be resolved.
MOZ_ALWAYS_TRUE(mFinished->SetAnyPromiseIsHandled());
}
ResetFinishedPromise();
@ -1710,7 +1711,7 @@ void Animation::ResetPendingTasks() {
if (mReady) {
mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
mReady->SetSettledPromiseIsHandled();
MOZ_ALWAYS_TRUE(mReady->SetAnyPromiseIsHandled());
mReady = nullptr;
}
}

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

@ -58,5 +58,76 @@ promise_test(t => {
});
}, 'After cancelling an animation, it can still be re-used');
promise_test(async t => {
for (const type of ["resolve", "reject"]) {
const anim = new Animation();
let isThenGet = false;
let isThenCalled = false;
let resolveFinished;
let rejectFinished;
const thenCalledPromise = new Promise(resolveThenCalledPromise => {
// Make `anim` thenable.
Object.defineProperty(anim, "then", {
get() {
isThenGet = true;
return function(resolve, reject) {
isThenCalled = true;
resolveThenCalledPromise(true);
resolveFinished = resolve;
rejectFinished = reject;
};
},
});
});
// Lazily create finished promise.
const finishedPromise = anim.finished;
assert_false(isThenGet, "then property shouldn't be accessed yet");
// Resolve finished promise with `anim`, that gets `then`, and
// calls in the thenable job.
anim.finish();
assert_true(isThenGet, "then property should be accessed");
assert_false(isThenCalled, "then property shouldn't be called yet");
// Reject finished promise.
// This should be ignored.
anim.cancel();
// Wait for the thenable job.
await thenCalledPromise;
assert_true(isThenCalled, "then property should be called");
const dummyPromise = new Promise(resolve => {
step_timeout(() => {
resolve("dummy");
}, 100);
});
const dummy = await Promise.race([finishedPromise, dummyPromise]);
assert_equals(dummy, "dummy", "finishedPromise shouldn't be settled yet");
if (type === "resolve") {
resolveFinished("hello");
const finished = await finishedPromise;
assert_equals(finished, "hello",
"finishedPromise should be resolved with given value");
} else {
rejectFinished("hello");
try {
await finishedPromise;
assert_unreached("finishedPromise should be rejected")
} catch (e) {
assert_equals(e, "hello",
"finishedPromise should be rejected with given value");
}
}
}
}, "Animation.finished promise should not be rejected by cancel method once "
+ "it is resolved with inside finish method");
</script>
</body>