"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeWithModules = exports.TEST_OBJ_NAME = void 0;
const selenium_webdriver_1 = require("selenium-webdriver");
const no_require_jet_1 = require("./no-require-jet");
exports.TEST_OBJ_NAME = '__ojwebdrivertest_proxy';
let _BROWSER_NAME;
/**
 * Run a remote script on the browser utilizing the requested modules. If JET runtime modules are
 * needed, test adapters should only use this script to access them. Never do direct imports/requires
 * in remote scripts.
 *
 * Only modules made available by ojs/ojwebdrivertest-proxy may be used.
 *
 * @param {WebDriver} driver
 * @param {string[]} moduleNames An array of strings of the modules to be made available
 * @param {any[]} scriptArgs An array of arguments to pass to the script. Pass blank array if no args
 * @param {string} script The script to be executed. The script should define a function that takes the
 * arguments containg: each requested module as separate parameters, and each script argument as
 * separate parameters after the modules.
 * @return {Promise<T>} Anything returned from the script
 * @template T
 */
async function executeWithModules(driver, moduleNames, scriptArgs = [], script) {
    const testProxyScript = getTestProxyScript();
    const hasProxy = !(await driver.executeAsyncScript(testProxyScript));
    if (!hasProxy) {
        throw new Error('executeWithModules called on a non-JET page');
    }
    if (!_BROWSER_NAME) {
        const caps = await driver.getCapabilities();
        _BROWSER_NAME = caps.get(selenium_webdriver_1.Capability.BROWSER_NAME);
    }
    if (_BROWSER_NAME === selenium_webdriver_1.Browser.FIREFOX) {
        return _executeWithModulesFirefox(driver, moduleNames, scriptArgs, script);
    }
    const s = `
    const args = Array.from(arguments);

    console.log('${exports.TEST_OBJ_NAME} importing modules ${moduleNames}');
    return ${exports.TEST_OBJ_NAME}.getProxy(...${JSON.stringify(moduleNames)}).then((modules) => {
      console.log('${exports.TEST_OBJ_NAME} running script');
      return (${script})(...modules.concat(args));
    })
  `;
    return driver.executeScript(s, ...scriptArgs);
}
exports.executeWithModules = executeWithModules;
/**
 * Workaround https://github.com/mozilla/geckodriver/issues/1701 where properties defined via a getter are not returned
 * a) via executeAsyncScript
 * b) via a Promise returned from executeScript
 *
 * @param driver
 * @param moduleNames
 * @param scriptArgs
 * @param script
 * @returns
 */
async function _executeWithModulesFirefox(driver, moduleNames, scriptArgs = [], script) {
    const s1 = `
    console.log('${exports.TEST_OBJ_NAME} importing modules ${moduleNames}');
    // We don't actually need the returned module values here, we just want to
    // trigger the imports.  Throw away the return values so that we don't run
    // into problems trying to encode them
    return ${exports.TEST_OBJ_NAME}.getProxy(...${JSON.stringify(moduleNames)}).then(() => {});
  `;
    await driver.executeScript(s1);
    const s2 = `
    const args = Array.from(arguments);
    const modules = ${exports.TEST_OBJ_NAME}.getCachedModules(...${JSON.stringify(moduleNames)});
    console.log('${exports.TEST_OBJ_NAME} running script');
    return (${script})(...modules.concat(args));
  `;
    return driver.executeScript(s2, ...scriptArgs);
}
function getTestProxyScript() {
    if ((0, no_require_jet_1.isNoRequireJet)()) {
        return `
      const done = arguments[0];
      (function pollForProxy() {
        if ('${exports.TEST_OBJ_NAME}' in window) {
          done();
        }
        setTimeout(pollForProxy, 100);
      })();
    `;
    }
    else {
        return `
      const done = arguments[0];
      function success() {
        done();
      }
      function failure() {
        done('Unable to load ojs/ojcore-base via RequireJS');
      }
      if (typeof require === 'function') {
        // Try sync require first
        try {
          require('ojs/ojcore-base');
          success();
        } catch (ex) {
          require(['ojs/ojcore-base'], success, failure);
          return;
        }
      } else {
        failure();
      }
    `;
    }
}
//# sourceMappingURL=oj-module-proxy.js.map