Przeglądaj źródła

fix: iframe multi-level nested inner element cannot be accessed (#1476)

Ahmad Kholid 1 rok temu
rodzic
commit
7f1c3b78cb
2 zmienionych plików z 29 dodań i 12 usunięć
  1. 10 4
      src/content/handleSelector.js
  2. 19 8
      src/content/index.js

+ 10 - 4
src/content/handleSelector.js

@@ -10,13 +10,18 @@ export function markElement(el, { id, data }) {
 }
 
 export function getDocumentCtx(frameSelector) {
+  if (!frameSelector) return document;
+
   let documentCtx = document;
 
-  if (frameSelector) {
-    const type = isXPath(frameSelector) ? 'xpath' : 'cssSelector';
-    const element = FindElement[type]({ selector: frameSelector });
+  const iframeSelectors = frameSelector.split('|>');
+  const type = isXPath(frameSelector) ? 'xpath' : 'cssSelector';
+  iframeSelectors.forEach((selector) => {
+    if (!documentCtx) return;
+
+    const element = FindElement[type]({ selector }, documentCtx);
     documentCtx = element?.contentDocument;
-  }
+  });
 
   return documentCtx;
 }
@@ -62,6 +67,7 @@ export default async function (
   }
 
   const documentCtx = getDocumentCtx(frameSelector);
+
   if (!documentCtx) {
     if (onError) onError(new Error('iframe-not-found'));
 

+ 19 - 8
src/content/index.js

@@ -5,7 +5,10 @@ import findSelector from '@/lib/findSelector';
 import { sendMessage } from '@/utils/message';
 import automa from '@business';
 import { toCamelCase, isXPath } from '@/utils/helper';
-import handleSelector, { queryElements } from './handleSelector';
+import handleSelector, {
+  queryElements,
+  getDocumentCtx,
+} from './handleSelector';
 import blocksHandler from './blocksHandler';
 import showExecutedBlock from './showExecutedBlock';
 import shortcutListener from './services/shortcutListener';
@@ -49,19 +52,27 @@ function messageToFrame(frameElement, blockData) {
 async function executeBlock(data) {
   const removeExecutedBlock = showExecutedBlock(data, data.executedBlockOnWeb);
   if (data.data?.selector?.includes('|>')) {
-    const [frameSelector, selector] = data.data.selector.split(/\|>(.+)/);
+    const selectorsArr = data.data.selector.split('|>');
+    const selector = selectorsArr.pop();
+    const frameSelector = selectorsArr.join('|>');
+
+    const framElSelector = selectorsArr.pop();
 
     let findBy = data?.data?.findBy;
     if (!findBy) {
       findBy = isXPath(frameSelector) ? 'xpath' : 'cssSelector';
     }
 
-    const frameElement = await queryElements({
-      findBy,
-      multiple: false,
-      waitForSelector: 5000,
-      selector: frameSelector,
-    });
+    const documentCtx = getDocumentCtx(selectorsArr.join('|>'));
+    const frameElement = await queryElements(
+      {
+        findBy,
+        multiple: false,
+        waitForSelector: 5000,
+        selector: framElSelector,
+      },
+      documentCtx
+    );
     const frameError = (message) => {
       const error = new Error(message);
       error.data = { selector: frameSelector };