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 sadym-chromium committed Jan 14, 2025
1 parent 930f383 commit 7566bcc
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 7566bcc

Please sign in to comment.