@@ -46,7 +46,7 @@ declare global {
4646 /** Elements an earlier snapshot of this document listed; a later snapshot marks the rest `new`. */
4747 __simAgentShownElements ?: WeakSet < Element >
4848 /** Installed by {@link installPageHelpers} before every page function; cached per call. */
49- __simAgentFindExemptModal : ( ) => Element | null
49+ __simAgentIsExemptModal : ( element : Element ) => boolean
5050 /** Why the last __simAgentResolveElement call returned null — read by the
5151 * shared stale-error producers so a refusal names its cause instead of
5252 * the blanket "the page changed". Cleared on every successful resolve. */
@@ -66,23 +66,27 @@ export function serializePageCall(fn: (...args: never[]) => unknown, args: unkno
6666 */
6767export function installPageHelpers ( ) : void {
6868 /**
69- * The open modal the page aria-hid together with everything else. MUI's ModalManager
69+ * The open modal each document aria-hid together with everything else. MUI's ModalManager
7070 * aria-hides every <body> child except the modal's mount node, and a `disablePortal` modal
7171 * mounts inside the app root it just hid, so its own ancestor carries aria-hidden. Visibility
72- * checks skip only the aria-hidden test on ancestors above this modal. Null when any modal is
73- * visible unmodified (the portaled case) or no single topmost modal is contained by all of its
74- * hidden ancestors. A modal nested inside another open modal is the topmost of the two.
72+ * checks skip only the aria-hidden test on ancestors above this modal. A document has none when
73+ * any modal is visible unmodified (the portaled case), when anything other than a <body> child
74+ * hides a modal (the app hid that dialog itself), or when no single innermost modal is contained
75+ * by every hidden ancestor. Looked up per document, so a same-origin iframe gets its own.
7576 */
76- let exemptModal : Element | null | undefined
77- window . __simAgentFindExemptModal = ( ) : Element | null => {
78- if ( exemptModal === undefined ) exemptModal = findExemptModal ( )
79- return exemptModal
77+ const exemptModals = new Map < Document , Element | null > ( )
78+ window . __simAgentIsExemptModal = ( element : Element ) : boolean => {
79+ const doc = element . ownerDocument
80+ let modal = exemptModals . get ( doc )
81+ if ( modal === undefined ) {
82+ modal = findExemptModal ( doc )
83+ exemptModals . set ( doc , modal )
84+ }
85+ return modal === element
8086 }
81- function findExemptModal ( ) : Element | null {
87+ function findExemptModal ( doc : Document ) : Element | null {
8288 const rendered : Array < { modal : Element ; hidden : Element [ ] } > = [ ]
83- for ( const modal of Array . from (
84- document . querySelectorAll ( '[aria-modal="true"], dialog[open]' )
85- ) ) {
89+ for ( const modal of Array . from ( doc . querySelectorAll ( '[aria-modal="true"], dialog[open]' ) ) ) {
8690 const rect = modal . getBoundingClientRect ( )
8791 if ( rect . width <= 0 || rect . height <= 0 || modal . getAttribute ( 'aria-hidden' ) === 'true' )
8892 continue
@@ -106,7 +110,9 @@ export function installPageHelpers(): void {
106110 current = 'host' in root ? ( root . host as Element ) : null
107111 }
108112 }
109- if ( visible ) rendered . push ( { modal, hidden } )
113+ if ( visible && hidden . every ( ( ancestor ) => ancestor . parentElement === doc . body ) ) {
114+ rendered . push ( { modal, hidden } )
115+ }
110116 }
111117 if ( rendered . some ( ( { hidden } ) => hidden . length === 0 ) ) return null
112118 const topmost = rendered . filter (
@@ -283,7 +289,7 @@ export function collectSnapshot(startingElementId = 0, elementId?: number): unkn
283289 ! current . hasAttribute ( 'hidden' ) &&
284290 ( aboveExemptModal || current . getAttribute ( 'aria-hidden' ) !== 'true' )
285291 )
286- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
292+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
287293 if ( current . parentElement ) current = current . parentElement
288294 else {
289295 const root = current . getRootNode ( )
@@ -872,7 +878,7 @@ export function collectSnapshot(startingElementId = 0, elementId?: number): unkn
872878 ) {
873879 return false
874880 }
875- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
881+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
876882 if ( current . parentElement ) current = current . parentElement
877883 else {
878884 const root = current . getRootNode ( )
@@ -1110,7 +1116,7 @@ export function clickElement(
11101116 ) {
11111117 return { error : 'not-visible' }
11121118 }
1113- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
1119+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
11141120 if ( current . parentElement ) current = current . parentElement
11151121 else {
11161122 const root = current . getRootNode ( )
@@ -1603,7 +1609,7 @@ export function focusElementForTyping(id: number, moveFocus = true): unknown {
16031609 ) {
16041610 return { error : 'not-visible' }
16051611 }
1606- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
1612+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
16071613 }
16081614
16091615 if ( moveFocus ) {
@@ -2349,7 +2355,7 @@ export function readPageActionState(
23492355 ) {
23502356 return false
23512357 }
2352- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
2358+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
23532359 if ( current . parentElement ) current = current . parentElement
23542360 else {
23552361 const root = current . getRootNode ( )
@@ -2514,7 +2520,7 @@ export function readPageActionState(
25142520 ) {
25152521 return false
25162522 }
2517- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
2523+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
25182524 if ( current . parentElement ) current = current . parentElement
25192525 else {
25202526 const root = current . getRootNode ( )
@@ -2649,7 +2655,7 @@ export function scrollPage(direction: string, amount?: number, elementId?: numbe
26492655 ) {
26502656 return false
26512657 }
2652- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
2658+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
26532659 if ( current . parentElement ) current = current . parentElement
26542660 else {
26552661 const root = current . getRootNode ( )
@@ -3133,7 +3139,7 @@ export function getElementScreenshotRect(id: number): unknown {
31333139 ) {
31343140 return { error : 'not-visible' }
31353141 }
3136- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
3142+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
31373143 if ( current . parentElement ) current = current . parentElement
31383144 else {
31393145 const root = current . getRootNode ( )
@@ -3284,7 +3290,7 @@ export function readChildFrameElementState(
32843290 visible = false
32853291 break
32863292 }
3287- if ( current === window . __simAgentFindExemptModal ( ) ) aboveExemptModal = true
3293+ if ( window . __simAgentIsExemptModal ( current ) ) aboveExemptModal = true
32883294 if ( style . transform && style . transform !== 'none' ) {
32893295 try {
32903296 if ( typeof DOMMatrixReadOnly !== 'function' ) {
0 commit comments