Kaynağa Gözat

Merge pull request #1439 from Siykt/fix/concurrently-execute

Fix(#1430): Concurrently execute
Ahmad Kholid 1 yıl önce
ebeveyn
işleme
3d40f81528
2 değiştirilmiş dosya ile 111 ekleme ve 78 silme
  1. 87 78
      src/content/index.js
  2. 24 0
      src/workflowEngine/WorkflowWorker.js

+ 87 - 78
src/content/index.js

@@ -240,86 +240,95 @@ async function messageListener({ data, source }) {
 
   automa('content');
 
-  browser.runtime.onMessage.addListener((data) => {
-    return new Promise((resolve, reject) => {
-      if (data.isBlock) {
-        executeBlock(data)
-          .then(resolve)
-          .catch((error) => {
-            console.error(error);
-            const elNotFound = error.message === 'element-not-found';
-            const isLoopItem = data.data?.selector?.includes('automa-loop');
-            if (elNotFound && isLoopItem) {
-              const findLoopEl = data.loopEls.find(({ url }) =>
-                window.location.href.includes(url)
-              );
-
-              const blockData = { ...data.data, ...findLoopEl, multiple: true };
-              const loopBlock = {
-                ...data,
-                onlyGenerate: true,
-                data: blockData,
-              };
-
-              blocksHandler()
-                .loopData(loopBlock)
-                .then(() => {
-                  executeBlock(data).then(resolve).catch(reject);
-                })
-                .catch((blockError) => {
-                  reject(blockError);
-                });
-              return;
-            }
-
-            reject(error);
-          });
-      } else {
-        switch (data.type) {
-          case 'input-workflow-params':
-            window.initPaletteParams?.(data.data);
-            resolve(Boolean(window.initPaletteParams));
-            break;
-          case 'content-script-exists':
-            resolve(true);
-            break;
-          case 'automa-element-selector': {
-            const selectorInstance = elementSelectorInstance();
-
-            resolve(selectorInstance);
-            break;
-          }
-          case 'context-element': {
-            let $ctxElSelector = '';
-
-            if (contextElement) {
-              $ctxElSelector = findSelector(contextElement);
-              contextElement = null;
-            }
-            if (!$ctxTextSelection) {
-              $ctxTextSelection = window.getSelection().toString();
-            }
-
-            const cloneContextData = cloneDeep({
-              $ctxLink,
-              $ctxMediaUrl,
-              $ctxElSelector,
-              $ctxTextSelection,
-            });
-
-            $ctxLink = '';
-            $ctxMediaUrl = '';
-            $ctxElSelector = '';
-            $ctxTextSelection = '';
-
-            resolve(cloneContextData);
-            break;
-          }
-          default:
-            resolve(null);
+  let locked = false;
+  const queue = [];
+
+  browser.runtime.onMessage.addListener(async (data) => {
+    const asyncExecuteBlock = async (block) => {
+      if (locked) {
+        return new Promise((resolve, reject) => {
+          queue.push([block, resolve, reject]);
+        });
+      }
+
+      try {
+        locked = true;
+        const res = await executeBlock(block);
+        return res;
+      } catch (error) {
+        console.error(error);
+        const elNotFound = error.message === 'element-not-found';
+        const isLoopItem = data.data?.selector?.includes('automa-loop');
+
+        if (!elNotFound || !isLoopItem) return Promise.reject(error);
+
+        const findLoopEl = data.loopEls.find(({ url }) =>
+          window.location.href.includes(url)
+        );
+
+        const blockData = { ...data.data, ...findLoopEl, multiple: true };
+        const loopBlock = {
+          ...data,
+          onlyGenerate: true,
+          data: blockData,
+        };
+
+        await blocksHandler().loopData(loopBlock);
+        return executeBlock(block);
+      } finally {
+        locked = false;
+      }
+    };
+
+    if (data.isBlock) {
+      const res = await asyncExecuteBlock(data);
+      while (queue.length) {
+        const [block, resolve, reject] = queue.shift();
+        requestAnimationFrame(() => {
+          asyncExecuteBlock(block).then(resolve).catch(reject);
+        });
+      }
+
+      return res;
+    }
+
+    switch (data.type) {
+      case 'input-workflow-params':
+        window.initPaletteParams?.(data.data);
+        return Boolean(window.initPaletteParams);
+      case 'content-script-exists':
+        return true;
+      case 'automa-element-selector': {
+        return elementSelectorInstance();
+      }
+      case 'context-element': {
+        let $ctxElSelector = '';
+
+        if (contextElement) {
+          $ctxElSelector = findSelector(contextElement);
+          contextElement = null;
+        }
+        if (!$ctxTextSelection) {
+          $ctxTextSelection = window.getSelection().toString();
         }
+
+        const cloneContextData = cloneDeep({
+          $ctxLink,
+          $ctxMediaUrl,
+          $ctxElSelector,
+          $ctxTextSelection,
+        });
+
+        $ctxLink = '';
+        $ctxMediaUrl = '';
+        $ctxElSelector = '';
+        $ctxTextSelection = '';
+
+        return cloneContextData;
       }
-    });
+      default:
+        return null;
+    }
   });
 })();
 

+ 24 - 0
src/workflowEngine/WorkflowWorker.js

@@ -141,6 +141,29 @@ class WorkflowWorker {
     prevBlockData,
     nextBlockBreakpointCount = null
   ) {
+    // pre check
+    for (const connection of connections) {
+      const id = typeof connection === 'string' ? connection : connection.id;
+
+      const block = this.engine.blocks[id];
+
+      if (!block) {
+        console.error(`Block ${id} doesn't exist`);
+        this.engine.destroy('stopped');
+        return;
+      }
+
+      // pass disabled block
+      // eslint-disable-next-line no-continue
+      if (block.data.disableBlock) continue;
+
+      // check if the next block is breakpoint
+      if (block.data?.$breakpoint) {
+        // set breakpoint state
+        nextBlockBreakpointCount = 0;
+      }
+    }
+
     connections.forEach((connection, index) => {
       const { id, targetHandle, sourceHandle } =
         typeof connection === 'string'
@@ -166,6 +189,7 @@ class WorkflowWorker {
           currentBlock: this.currentBlock,
           repeatedTasks: this.repeatedTasks,
           preloadScripts: this.preloadScripts,
+          debugAttached: this.debugAttached,
         });
 
         this.engine.addWorker({