123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- import { customAlphabet } from 'nanoid/non-secure';
- import browser from 'webextension-polyfill';
- import cloneDeep from 'lodash.clonedeep';
- import { jsContentHandler } from '@/newtab/utils/javascriptBlockUtil';
- import { messageSandbox, automaRefDataStr, waitTabLoaded } from '../helper';
- const nanoid = customAlphabet('1234567890abcdef', 5);
- function getAutomaScript(refData, everyNewTab) {
- const varName = `automa${nanoid()}`;
- let str = `
- const ${varName} = ${JSON.stringify(refData)};
- ${automaRefDataStr(varName)}
- function automaSetVariable(name, value) {
- ${varName}.variables[name] = value;
- }
- function automaNextBlock(data, insert = true) {
- document.body.dispatchEvent(new CustomEvent('__automa-next-block__', { detail: { data, insert, refData: ${varName} } }));
- }
- function automaResetTimeout() {
- document.body.dispatchEvent(new CustomEvent('__automa-reset-timeout__'));
- }
- `;
- if (everyNewTab) str = automaRefDataStr(varName);
- return str;
- }
- async function executeInWebpage(args, target, worker) {
- if (worker.engine.isMV2 || BROWSER_TYPE === 'firefox') {
- args[0] = cloneDeep(args[0]);
- const result = await worker._sendMessageToTab({
- label: 'javascript-code',
- data: args,
- });
- return result;
- }
- const [{ result }] = await browser.scripting.executeScript({
- args,
- target,
- world: 'MAIN',
- func: jsContentHandler,
- });
- return result;
- }
- export async function javascriptCode({ outputs, data, ...block }, { refData }) {
- const nextBlockId = this.getBlockConnections(block.id);
- if (data.everyNewTab) {
- const isScriptExist = this.preloadScripts.some(({ id }) => id === block.id);
- if (!isScriptExist)
- this.preloadScripts.push({ id: block.id, data: cloneDeep(data) });
- if (!this.activeTab.id) return { data: '', nextBlockId };
- } else if (!this.activeTab.id && data.context !== 'background') {
- throw new Error('no-tab');
- }
- const payload = {
- ...block,
- data,
- refData: { variables: {} },
- frameSelector: this.frameSelector,
- };
- if (data.code.includes('automaRefData')) {
- payload.refData = { ...refData, secrets: {} };
- }
- const preloadScriptsPromise = await Promise.allSettled(
- data.preloadScripts.map(async (script) => {
- const { protocol } = new URL(script.src);
- const isValidUrl = /https?/.test(protocol);
- if (!isValidUrl) return null;
- const response = await fetch(script.src);
- if (!response.ok) throw new Error(response.statusText);
- const result = await response.text();
- return {
- script: result,
- id: `automa-script-${nanoid()}`,
- removeAfterExec: script.removeAfterExec,
- };
- })
- );
- const preloadScripts = preloadScriptsPromise.reduce((acc, item) => {
- if (item.status === 'fulfilled') acc.push(item.value);
- return acc;
- }, []);
- const automaScript =
- data.everyNewTab || data.context === 'background'
- ? ''
- : getAutomaScript(payload.refData, data.everyNewTab);
- if (data.context !== 'background') {
- await waitTabLoaded({
- tabId: this.activeTab.id,
- ms: this.settings?.tabLoadTimeout ?? 30000,
- });
- }
- const result = await (data.context === 'background'
- ? messageSandbox('javascriptBlock', {
- preloadScripts,
- refData: payload.refData,
- blockData: cloneDeep(payload.data),
- })
- : executeInWebpage(
- [payload, preloadScripts, automaScript],
- {
- tabId: this.activeTab.id,
- frameIds: [this.activeTab.frameId || 0],
- },
- this
- ));
- if (result) {
- if (result.columns.data?.$error) {
- throw new Error(result.columns.data.message);
- }
- if (result.variables) {
- Object.keys(result.variables).forEach((varName) => {
- this.setVariable(varName, result.variables[varName]);
- });
- }
- if (result.columns.insert && result.columns.data) {
- const params = Array.isArray(result.columns.data)
- ? result.columns.data
- : [result.columns.data];
- this.addDataToColumn(params);
- }
- }
- return {
- nextBlockId,
- data: result?.columns.data || {},
- };
- }
- export default javascriptCode;
|