Skip to content

Commit

Permalink
Make dialog focus async when removing open attribute
Browse files Browse the repository at this point in the history
When the dialog's open attribute is removed which closes the dialog, we
should make the focus async in order to prevent more script from running
inside attribute removal.

Context: whatwg/html#10124 (comment)

Bug: 3419353
Change-Id: I1b76f003e04b802b1868b427a0faddf5f19a3c5e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6085725
Reviewed-by: Di Zhang <[email protected]>
Commit-Queue: Joey Arhar <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1402551}
  • Loading branch information
josepharhar authored and chromium-wpt-export-bot committed Jan 6, 2025
1 parent cdaff80 commit 58fd4f8
Showing 1 changed file with 18 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,34 @@
<script src="/resources/testdriver-vendor.js"></script>

<button>button</button>
<dialog>hello world</dialog>
<dialog>
<button>button in dialog</button>
</dialog>

<script>
const dialog = document.querySelector('dialog');
const button = document.querySelector('button');
const dialogbutton = document.querySelector('dialog > button');

promise_test(async t => {
button.focus();
dialog.showModal();
assert_equals(document.activeElement, dialogbutton,
'<button> in <dialog> should be focused after opening.');

let closeFired = false;
let cancelFired = false;
dialog.addEventListener('close', () => closeFired = true);
dialog.addEventListener('cancel', () => cancelFired = true);

dialog.removeAttribute('open');
assert_equals(document.activeElement, dialogbutton,
'<button> in <dialog> should still be focused immediately after removing open.');
await new Promise(resolve => t.step_timeout(resolve, 0));
await new Promise(requestAnimationFrame);

assert_equals(document.activeElement, button,
'Previously focused element should be focused after waiting for a task.');
assert_false(dialog.matches(':modal'),
'The dialog should not match :modal after closing.');
assert_false(cancelFired,
Expand All @@ -40,17 +50,24 @@
}, 'Removing the open attribute from an open modal dialog should run the closing algorithm.');

promise_test(async t => {
button.focus();
dialog.show();
assert_equals(document.activeElement, dialogbutton,
'<button> in <dialog> should be focused after opening.');

let closeFired = false;
let cancelFired = false;
dialog.addEventListener('close', () => closeFired = true);
dialog.addEventListener('cancel', () => cancelFired = true);

dialog.removeAttribute('open');
assert_equals(document.activeElement, dialogbutton,
'<button> in <dialog> should still be focused immediately after removing open.');
await new Promise(resolve => t.step_timeout(resolve, 0));
await new Promise(requestAnimationFrame);

assert_equals(document.activeElement, button,
'Previously focused element should be focused after waiting for a task.');
assert_false(cancelFired,
'The cancel event should not fire when removing the open attribute.');
assert_true(closeFired,
Expand Down

0 comments on commit 58fd4f8

Please sign in to comment.