@@ -5,6 +5,22 @@ import logger from "../logger";
55
66type Workflow = WorkflowFile [ "workflow" ] ;
77
8+ type ShadowBoundary = {
9+ type : 'shadow' ;
10+ host : HTMLElement ;
11+ root : ShadowRoot ;
12+ element : HTMLElement ;
13+ } ;
14+
15+ type IframeBoundary = {
16+ type : 'iframe' ;
17+ frame : HTMLIFrameElement ;
18+ document : Document ;
19+ element : HTMLElement ;
20+ } ;
21+
22+ type Boundary = ShadowBoundary | IframeBoundary ;
23+
824/**
925 * Checks the basic info about an element and returns a {@link BaseActionInfo} object.
1026 * If the element is not found, returns undefined.
@@ -762,22 +778,6 @@ export const getSelectors = async (page: Page, coordinates: Coordinates) => {
762778 One ,
763779 }
764780
765- type ShadowBoundary = {
766- type : 'shadow' ;
767- host : HTMLElement ;
768- root : ShadowRoot ;
769- element : HTMLElement ;
770- } ;
771-
772- type IframeBoundary = {
773- type : 'iframe' ;
774- frame : HTMLIFrameElement ;
775- document : Document ;
776- element : HTMLElement ;
777- } ;
778-
779- type Boundary = ShadowBoundary | IframeBoundary ;
780-
781781 type Options = {
782782 root : Element ;
783783 idName : ( name : string ) => boolean ;
@@ -1547,14 +1547,6 @@ interface SelectorResult {
15471547 */
15481548
15491549export const getNonUniqueSelectors = async ( page : Page , coordinates : Coordinates , listSelector : string ) : Promise < SelectorResult > => {
1550- interface DOMContext {
1551- type : 'iframe' | 'shadow' ;
1552- element : HTMLElement ;
1553- container : HTMLIFrameElement | ShadowRoot ;
1554- host ?: HTMLElement ;
1555- document ?: Document ;
1556- }
1557-
15581550 try {
15591551 if ( ! listSelector ) {
15601552 const selectors = await page . evaluate ( ( { x, y } : { x : number , y : number } ) => {
@@ -1648,8 +1640,8 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
16481640 }
16491641
16501642
1651- function getContextPath ( element : HTMLElement ) : DOMContext [ ] {
1652- const path : DOMContext [ ] = [ ] ;
1643+ function getContextPath ( element : HTMLElement ) : Boundary [ ] {
1644+ const path : Boundary [ ] = [ ] ;
16531645 let current = element ;
16541646 let depth = 0 ;
16551647 const MAX_DEPTH = 4 ;
@@ -1660,9 +1652,9 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
16601652 if ( rootNode instanceof ShadowRoot ) {
16611653 path . unshift ( {
16621654 type : 'shadow' ,
1663- element : current ,
1664- container : rootNode ,
1665- host : rootNode . host as HTMLElement
1655+ host : rootNode . host as HTMLElement ,
1656+ root : rootNode ,
1657+ element : current
16661658 } ) ;
16671659 current = rootNode . host as HTMLElement ;
16681660 depth ++ ;
@@ -1674,15 +1666,28 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
16741666 const frameElement = ownerDocument ?. defaultView ?. frameElement as HTMLIFrameElement ;
16751667
16761668 if ( frameElement ) {
1677- path . unshift ( {
1678- type : 'iframe' ,
1679- element : current ,
1680- container : frameElement ,
1681- document : ownerDocument
1682- } ) ;
1683- current = frameElement ;
1684- depth ++ ;
1685- continue ;
1669+ try {
1670+ // Check if we can access the iframe's origin
1671+ const iframeOrigin = new URL ( frameElement . src ) . origin ;
1672+ const currentOrigin = window . location . origin ;
1673+ if ( iframeOrigin !== currentOrigin ) {
1674+ console . warn ( `Skipping cross-origin iframe: ${ iframeOrigin } ` ) ;
1675+ break ;
1676+ }
1677+
1678+ path . unshift ( {
1679+ type : 'iframe' ,
1680+ frame : frameElement ,
1681+ document : ownerDocument ,
1682+ element : current
1683+ } ) ;
1684+ current = frameElement ;
1685+ depth ++ ;
1686+ continue ;
1687+ } catch ( error ) {
1688+ console . warn ( 'Cannot access iframe origin:' , error ) ;
1689+ break ;
1690+ }
16861691 }
16871692
16881693 break ;
@@ -1701,7 +1706,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
17011706
17021707 contextPath . forEach ( ( context , index ) => {
17031708 const containerSelector = getNonUniqueSelector (
1704- context . type === 'shadow' ? context . host ! : context . container as HTMLElement
1709+ context . type === 'shadow' ? context . host ! : context . element as HTMLElement
17051710 ) ;
17061711
17071712 if ( index === contextPath . length - 1 ) {
@@ -1888,8 +1893,8 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
18881893 }
18891894
18901895 // Get complete context path (both iframe and shadow DOM)
1891- function getContextPath ( element : HTMLElement ) : DOMContext [ ] {
1892- const path : DOMContext [ ] = [ ] ;
1896+ function getContextPath ( element : HTMLElement ) : Boundary [ ] {
1897+ const path : Boundary [ ] = [ ] ;
18931898 let current = element ;
18941899 let depth = 0 ;
18951900 const MAX_DEPTH = 4 ;
@@ -1900,9 +1905,9 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
19001905 if ( rootNode instanceof ShadowRoot ) {
19011906 path . unshift ( {
19021907 type : 'shadow' ,
1903- element : current ,
1904- container : rootNode ,
1905- host : rootNode . host as HTMLElement
1908+ host : rootNode . host as HTMLElement ,
1909+ root : rootNode ,
1910+ element : current
19061911 } ) ;
19071912 current = rootNode . host as HTMLElement ;
19081913 depth ++ ;
@@ -1914,15 +1919,28 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
19141919 const frameElement = ownerDocument ?. defaultView ?. frameElement as HTMLIFrameElement ;
19151920
19161921 if ( frameElement ) {
1917- path . unshift ( {
1918- type : 'iframe' ,
1919- element : current ,
1920- container : frameElement ,
1921- document : ownerDocument
1922- } ) ;
1923- current = frameElement ;
1924- depth ++ ;
1925- continue ;
1922+ try {
1923+ // Check if we can access the iframe's origin
1924+ const iframeOrigin = new URL ( frameElement . src ) . origin ;
1925+ const currentOrigin = window . location . origin ;
1926+ if ( iframeOrigin !== currentOrigin ) {
1927+ console . warn ( `Skipping cross-origin iframe: ${ iframeOrigin } ` ) ;
1928+ break ;
1929+ }
1930+
1931+ path . unshift ( {
1932+ type : 'iframe' ,
1933+ frame : frameElement ,
1934+ document : ownerDocument ,
1935+ element : current
1936+ } ) ;
1937+ current = frameElement ;
1938+ depth ++ ;
1939+ continue ;
1940+ } catch ( error ) {
1941+ console . warn ( 'Cannot access iframe origin:' , error ) ;
1942+ break ;
1943+ }
19261944 }
19271945
19281946 break ;
@@ -1941,7 +1959,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates
19411959
19421960 contextPath . forEach ( ( context , index ) => {
19431961 const containerSelector = getNonUniqueSelector (
1944- context . type === 'shadow' ? context . host ! : context . container as HTMLElement
1962+ context . type === 'shadow' ? context . host ! : context . element as HTMLElement
19451963 ) ;
19461964
19471965 if ( index === contextPath . length - 1 ) {
0 commit comments