Script
Page being translated from English to Japanese. Do you speak Japanese? Help us to translate it by sending us pull requests!
Commands
This section contains the APIs related to script commands.
Call function in a browsing context
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Call function in a sandbox
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Call function in a realm
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Evaluate script in a browsing context
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Evaluate script in a sandbox
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Evaluate script in a realm
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Disown handles in a browsing context
            script.disownBrowsingContextScript(/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    await manager.disownBrowsingContextScript(id, boxId)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Disown handles in a realm
            script.disownRealmScript(realmId, List.of(boxId));/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    await manager.disownRealmScript(realmId, boxId)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Get all realms
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Get realm by type
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Get browsing context realms
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Get browsing context realms by type
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Preload a script
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Remove a preloaded script
                script.removePreloadScript(id);/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.module.LogInspector;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.browsingcontext.ReadinessState;
import org.openqa.selenium.bidi.log.ConsoleLogEntry;
import org.openqa.selenium.bidi.script.ChannelValue;
import org.openqa.selenium.bidi.script.EvaluateResult;
import org.openqa.selenium.bidi.script.EvaluateResultExceptionValue;
import org.openqa.selenium.bidi.script.EvaluateResultSuccess;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.ObjectLocalValue;
import org.openqa.selenium.bidi.script.PrimitiveProtocolValue;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.bidi.script.RemoteReference;
import org.openqa.selenium.bidi.script.ResultOwnership;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    @Test
    void canCallFunction() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));
            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);
            arguments.add(thisParameter);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(64L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithDeclaration() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id, "()=>{return 1+2;}", false, Optional.empty(), Optional.empty(), Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithArguments() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            LocalValue value1 = PrimitiveProtocolValue.stringValue("ARGUMENT_STRING_VALUE");
            LocalValue value2 = PrimitiveProtocolValue.numberValue(42);
            arguments.add(value1);
            arguments.add(value2);
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "(...args)=>{return args}",
                            false,
                            Optional.of(arguments),
                            Optional.empty(),
                            Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(2, ((List<Object>) successResult.getResult().getValue().get()).size());
        }
    }
    @Test
    void canCallFunctionWithAwaitPromise() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "async function() {{\n"
                                + "            await new Promise(r => setTimeout(() => r(), 0));\n"
                                + "            return \"SOME_DELAYED_RESULT\";\n"
                                + "          }}",
                        true,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("SOME_DELAYED_RESULT", (String) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithThisParameter() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        Map<Object, LocalValue> value = new HashMap<>();
        value.put("some_property", PrimitiveProtocolValue.numberValue(42));
        LocalValue thisParameter = LocalValue.objectValue(value);
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "function(){return this.some_property}",
                        false,
                        Optional.empty(),
                        Optional.of(thisParameter),
                        Optional.empty());
        EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
        Assertions.assertEquals("number", successResult.getResult().getType());
        Assertions.assertEquals(42L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canCallFunctionWithOwnershipRoot() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "async function(){return {a:1}}",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
            }
        }
    @Test
    void canCallFunctionThatThrowsException() {
        String id = driver.getWindowHandle();
    try (Script script = new Script(id, driver)) {
        EvaluateResult result =
                script.callFunctionInBrowsingContext(
                        id,
                        "))) !!@@## some invalid JS script (((",
                        false,
                        Optional.empty(),
                        Optional.empty(),
                        Optional.empty());
        EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
        Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
        Assertions.assertEquals(
                "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canCallFunctionInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());
        Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canCallFunctionInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateScript() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
            Assertions.assertEquals(3L, (Long) successResult.getResult().getValue().get());
        }
    }
    @Test
    void canEvaluateScriptThatThrowsException() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "))) !!@@## some invalid JS script (((", false, Optional.empty());
            EvaluateResultExceptionValue exception = (EvaluateResultExceptionValue) result;
            Assertions.assertEquals("error", exception.getExceptionDetails().getException().getType());
            Assertions.assertEquals(
                    "SyntaxError: expected expression, got ')'", exception.getExceptionDetails().getText());
        }
    }
    @Test
    void canEvaluateScriptWithResulWithOwnership() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "Promise.resolve({a:1})", true, Optional.of(ResultOwnership.ROOT));
            EvaluateResultSuccess successResult = (EvaluateResultSuccess) result;
            Assertions.assertTrue(successResult.getResult().getHandle().isPresent());
        }
    }
    @Test
    void canEvaluateInASandBox() {
        String id = driver.getWindowHandle();
        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canEvaluateInARealm() {
        String tab = driver.getWindowHandle();
        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canDisownHandle() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            script.disownBrowsingContextScript(
                            window, List.of(boxId));
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canDisownHandleInARealm() {
        String window = driver.getWindowHandle();
        try (Script script = new Script(window, driver)) {
            BrowsingContext context = new BrowsingContext(driver, window);
            context.navigate("https://www.selenium.dev/selenium/web/dynamic.html", ReadinessState.COMPLETE);
            driver.findElement(By.id("adder")).click();
            getLocatedElement(driver, By.id("box0"));
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();
            // Retrieve the handle for the element added to DOM
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            window, "document.querySelector('.redbox');", false, Optional.of(ResultOwnership.ROOT));
            String boxId = ((EvaluateResultSuccess)result).getResult().getHandle().get();
            LocalValue value =
                    LocalValue.remoteReference(
                            RemoteReference.Type.HANDLE, boxId);
            EvaluateResult checkHandle = script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty());
            // The handle is present in memory, else it would result in exception
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, checkHandle.getResultType());
            // Useful to memory management in a dynamic webpage where DOM mutations happen often
            script.disownRealmScript(realmId, List.of(boxId));
            // Since the handle is now eligible for garbage collections, it is no longer available to be used.
            Assertions.assertThrows(WebDriverException.class, () -> script.callFunctionInBrowsingContext(
                    window,
                    "arg => arg.a",
                    false, Optional.of(List.of(value)),
                    Optional.empty(),
                    Optional.empty()));
        }
    }
    @Test
    void canGetAllRealms() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmByType() {
        String firstWindow = driver.getWindowHandle();
        String secondWindow = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();
        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);
            Assertions.assertEquals(2, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContext() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);
            Assertions.assertEquals(1, realms.size());
        }
    }
    @Test
    void canGetRealmInBrowsingContextByType() {
        String windowId = driver.getWindowHandle();
        String tabId = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();
        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);
            Assertions.assertEquals(1, windowRealms.size());
        }
    }
    @Test
    void canAddPreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
                Assertions.assertEquals("{preload_script_console_text}", logEntry.getText());
            }
        }
    }
    @Test
    void canAddPreloadScriptWithArguments() {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript(
                            "(channel) => channel('will_be_send', 'will_be_ignored')",
                            List.of(new ChannelValue("channel_name")));
            Assertions.assertNotNull(id);
        }
    }
    @Test
    void canAddPreloadScriptInASandbox() {
        try (Script script = new Script(driver)) {
            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");
            Assertions.assertNotNull(id);
            driver.get("https://www.selenium.dev/selenium/blankPage");
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            driver.getWindowHandle(), "sandbox", "window.bar", true, Optional.empty());
            Assertions.assertEquals(EvaluateResult.Type.SUCCESS, result.getResultType());
        }
    }
    @Test
    void canRemovePreloadScript() throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            String id =
                    script.addPreloadScript("() => {{ console.log('{preload_script_console_text}') }}");
            Assertions.assertNotNull(id);
            try (LogInspector logInspector = new LogInspector(driver)) {
                CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
                logInspector.onConsoleEntry(future::complete);
                script.removePreloadScript(id);
                driver.get("https://www.selenium.dev/selenium/blankPage");
                Assertions.assertThrows(TimeoutException.class, () -> future.get(5, TimeUnit.SECONDS));
            }
        }
    }
}
    await manager.removePreloadScript(scriptId)/examples/javascript/test/bidirectional/script_commands.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {By, until, Builder} = require("selenium-webdriver")
const ScriptManager = require('selenium-webdriver/bidi/scriptManager')
const {ResultOwnership} = require("selenium-webdriver/bidi/resultOwnership");
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue");
const {LocalValue, RemoteReferenceType, ReferenceValue} = require("selenium-webdriver/bidi/protocolValue");
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
const BrowsingContext = require("selenium-webdriver/bidi/browsingContext");
const {WebDriverError} = require("selenium-webdriver/lib/error");
const {RealmType} = require("selenium-webdriver/bidi/realmInfo");
const LogInspector = require("selenium-webdriver/bidi/logInspector");
describe('Script commands', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can call function', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 64)
  })
  it('can call function with declaration', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '()=>{return 1+2;}', false)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can call function to get element', async function () {
    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded')
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '() => document.getElementById("consoleLog")',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.type, 'node')
    assert.notEqual(result.result.value, null)
    assert.notEqual(result.result.value.nodeType, null)
  })
  it('can call function with arguments', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let argumentValues = []
    let value1 = new ArgumentValue(LocalValue.createStringValue('ARGUMENT_STRING_VALUE'))
    let value2 = new ArgumentValue(LocalValue.createNumberValue(42))
    argumentValues.push(value1)
    argumentValues.push(value2)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      '(...args)=>{return args}',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value.length, 2)
  })
  it('can call function with await promise', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      true,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 'SOME_DELAYED_RESULT')
  })
  it('can call function with await promise false', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function() {{\n' +
      '            await new Promise(r => setTimeout(() => r(), 0));\n' +
      '            return "SOME_DELAYED_RESULT";\n' +
      '          }}',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.type, 'promise')
  })
  it('can call function with this parameter', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function(){return this.some_property}',
      false,
      null,
      thisParameter,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 42)
  })
  it('can call function with ownership root', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function with ownership none', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(
      id,
      'async function(){return {a:1}}',
      true,
      null,
      null,
      ResultOwnership.NONE,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.realmId, null)
    assert.equal(result.result.handle, undefined)
    assert.notEqual(result.result.value, null)
  })
  it('can call function that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.callFunctionInBrowsingContext(id, '))) !!@@## some invalid JS script (((', false)
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can call function in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')
    const resultInSandbox = await manager.callFunctionInBrowsingContext(
      id,
      '() => window.foo',
      true,
      null,
      null,
      null,
      'sandbox',
    )
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
  })
  it('can call function in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)
    const result = await manager.callFunctionInRealm(realmId, '() => window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can evaluate script that throws exception', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      '))) !!@@## some invalid JS script (((',
      false,
    )
    assert.equal(result.resultType, EvaluateResultType.EXCEPTION)
    assert.equal(result.exceptionDetails.exception.type, 'error')
    assert.equal(result.exceptionDetails.text, "SyntaxError: expected expression, got ')'")
    assert.equal(result.exceptionDetails.columnNumber, 39)
    assert.equal(result.exceptionDetails.stackTrace.callFrames.length, 0)
  })
  it('can evaluate script with result ownership', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const result = await manager.evaluateFunctionInBrowsingContext(
      id,
      'Promise.resolve({a:1})',
      true,
      ResultOwnership.ROOT,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(result.result.handle, null)
  })
  it('can evaluate in a sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')
    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')
    assert.equal(resultInSandbox.resultType, EvaluateResultType.SUCCESS)
    assert.equal(resultInSandbox.result.value, 2)
  })
  it('can evaluate in a realm', async function () {
    const firstTab = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(firstTab, driver)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)
    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.equal(result.result.value, 3)
  })
  it('can disown handles', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    await manager.disownBrowsingContextScript(id, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can disown handles in realm', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const browsingContext = await BrowsingContext(driver, {browsingContextId: id})
    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/dynamic.html',
      'complete'
    )
    await driver.findElement(By.id('adder')).click()
    await driver.wait(until.elementLocated(By.id('box0')), 10000)
    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId
    const evaluateResult = await manager.evaluateFunctionInBrowsingContext(
      id,
      "document.querySelector('.redbox');",
      false,
      ResultOwnership.ROOT,
    )
    assert.equal(evaluateResult.resultType, EvaluateResultType.SUCCESS)
    let boxId = evaluateResult.result.handle
    let argumentValues = []
    let value1 = new ArgumentValue(new ReferenceValue(RemoteReferenceType.HANDLE, boxId))
    argumentValues.push(value1)
    let checkHandle = await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false, argumentValues)
    assert.equal(checkHandle.resultType, EvaluateResultType.SUCCESS)
    await manager.disownRealmScript(realmId, boxId)
    await manager.callFunctionInBrowsingContext(id, 'arg => arg.a', false).catch((error) => {
      assert(error instanceof WebDriverError)
    })
  })
  it('can get all realms', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getAllRealms()
    assert.equal(realms.length, 2)
  })
  it('can get realm by type', async function () {
    const firstWindow = await driver.getWindowHandle()
    await driver.switchTo().newWindow('window')
    const secondWindow = await driver.getWindowHandle()
    const manager = await ScriptManager(firstWindow, driver)
    const realms = await manager.getRealmsByType(RealmType.WINDOW)
    assert.equal(realms.length, 2)
  })
  it('can get realm in browsing context', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const tabId = await driver.getWindowHandle()
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContext(tabId)
    const tabRealm = realms[0]
    assert.equal(tabRealm.realmType, RealmType.WINDOW)
  })
  it('can get realm in browsing context by type', async function () {
    const windowId = await driver.getWindowHandle()
    await driver.switchTo().newWindow('tab')
    const manager = await ScriptManager(windowId, driver)
    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)
    const windowRealm = realms[0]
    assert.equal(windowRealm.realmType, RealmType.WINDOW)
  })
  it('can add preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry.text, '{preload_script_console_text}')
  })
  it('can add preload script to sandbox', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    await manager.addPreloadScript('() => { window.bar = 2; }', undefined, 'sandbox')
    await driver.get('https://www.selenium.dev/selenium/blank')
    let result_in_sandbox = await manager.evaluateFunctionInBrowsingContext(
      id,
      'window.bar',
      true,
      null,
      'sandbox',
    )
    assert.equal(result_in_sandbox.result.type, 'number')
    assert.equal(result_in_sandbox.result.value, 2)
  })
  it('can remove preload script', async function () {
    const id = await driver.getWindowHandle()
    const manager = await ScriptManager(id, driver)
    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')
    let logEntry = null
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })
    await manager.removePreloadScript(scriptId)
    await driver.get('https://www.selenium.dev/selenium/blank')
    assert.equal(logEntry, null)
  })
})
Events
This section contains the APIs related to script events.
Message
        try (Script script = new Script(driver)) {
            CompletableFuture<Message> future = new CompletableFuture<>();
            script.onMessage(future::complete);
            script.callFunctionInBrowsingContext(
                    driver.getWindowHandle(),
                    "(channel) => channel('foo')",
                    false,
                    Optional.of(List.of(LocalValue.channelValue("channel_name"))),
                    Optional.empty(),
                    Optional.empty());
            Message message = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals("channel_name", message.getChannel());
        }/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.Message;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptEventsTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    
    @Test
    void canListenToChannelMessage()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<Message> future = new CompletableFuture<>();
            script.onMessage(future::complete);
            script.callFunctionInBrowsingContext(
                    driver.getWindowHandle(),
                    "(channel) => channel('foo')",
                    false,
                    Optional.of(List.of(LocalValue.channelValue("channel_name"))),
                    Optional.empty(),
                    Optional.empty());
            Message message = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals("channel_name", message.getChannel());
        }
    }
    @Test
    @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI")
    void canListenToRealmCreatedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmCreated(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/blankPage");
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
    @Test
    @Disabled
    void canListenToRealmDestroyedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmDestroyed(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.close();
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
}
    const manager = await ScriptManager(undefined, driver)
    let message = null
    await manager.onMessage((m) => {
      message = m
    })
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name')))
    argumentValues.push(value)
    const result = await manager.callFunctionInBrowsingContext(
      await driver.getWindowHandle(),
      '(channel) => channel("foo")',
      false,
      argumentValues,
    )/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver")
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue")
const {RealmType} = require("selenium-webdriver/bidi/realmInfo")
const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue")
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
describe('Script events', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can listen to channel message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let message = null
    await manager.onMessage((m) => {
      message = m
    })
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name')))
    argumentValues.push(value)
    const result = await manager.callFunctionInBrowsingContext(
      await driver.getWindowHandle(),
      '(channel) => channel("foo")',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(message, null)
    assert.equal(message.channel, 'channel_name')
    assert.equal(message.data.type, 'string')
    assert.equal(message.data.value, 'foo')
  })
  it('can listen to realm created message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmCreated((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
  xit('can listen to realm destroyed message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmDestroyed((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.close()
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
})
Realm Created
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmCreated(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/blankPage");
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.Message;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptEventsTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    
    @Test
    void canListenToChannelMessage()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<Message> future = new CompletableFuture<>();
            script.onMessage(future::complete);
            script.callFunctionInBrowsingContext(
                    driver.getWindowHandle(),
                    "(channel) => channel('foo')",
                    false,
                    Optional.of(List.of(LocalValue.channelValue("channel_name"))),
                    Optional.empty(),
                    Optional.empty());
            Message message = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals("channel_name", message.getChannel());
        }
    }
    @Test
    @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI")
    void canListenToRealmCreatedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmCreated(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/blankPage");
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
    @Test
    @Disabled
    void canListenToRealmDestroyedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmDestroyed(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.close();
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
}
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmCreated((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver")
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue")
const {RealmType} = require("selenium-webdriver/bidi/realmInfo")
const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue")
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
describe('Script events', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can listen to channel message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let message = null
    await manager.onMessage((m) => {
      message = m
    })
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name')))
    argumentValues.push(value)
    const result = await manager.callFunctionInBrowsingContext(
      await driver.getWindowHandle(),
      '(channel) => channel("foo")',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(message, null)
    assert.equal(message.channel, 'channel_name')
    assert.equal(message.data.type, 'string')
    assert.equal(message.data.value, 'foo')
  })
  it('can listen to realm created message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmCreated((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
  xit('can listen to realm destroyed message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmDestroyed((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.close()
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
})
Realm Destroyed
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmDestroyed(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.close();
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/ScriptEventsTest.java
package dev.selenium.bidirectional.webdriver_bidi;
import dev.selenium.BaseTest;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.openqa.selenium.bidi.module.Script;
import org.openqa.selenium.bidi.browsingcontext.BrowsingContext;
import org.openqa.selenium.bidi.script.LocalValue;
import org.openqa.selenium.bidi.script.Message;
import org.openqa.selenium.bidi.script.RealmInfo;
import org.openqa.selenium.bidi.script.RealmType;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
class ScriptEventsTest extends BaseTest {
    @BeforeEach
    public void setup() {
        FirefoxOptions options = new FirefoxOptions();
        options.setCapability("webSocketUrl", true);
        driver = new FirefoxDriver(options);
    }
    
    @Test
    void canListenToChannelMessage()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<Message> future = new CompletableFuture<>();
            script.onMessage(future::complete);
            script.callFunctionInBrowsingContext(
                    driver.getWindowHandle(),
                    "(channel) => channel('foo')",
                    false,
                    Optional.of(List.of(LocalValue.channelValue("channel_name"))),
                    Optional.empty(),
                    Optional.empty());
            Message message = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals("channel_name", message.getChannel());
        }
    }
    @Test
    @DisabledOnOs(value = OS.MAC, disabledReason = "Works locally, times out on CI")
    void canListenToRealmCreatedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmCreated(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/blankPage");
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
    @Test
    @Disabled
    void canListenToRealmDestroyedEvent()
            throws ExecutionException, InterruptedException, TimeoutException {
        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmDestroyed(future::complete);
            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.close();
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }
    }
}
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmDestroyed((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.close()/examples/javascript/test/bidirectional/script_events.spec.js
const assert = require("assert")
const firefox = require('selenium-webdriver/firefox')
const {ScriptManager, BrowsingContext, Builder} = require("selenium-webdriver")
const {ArgumentValue} = require("selenium-webdriver/bidi/argumentValue")
const {RealmType} = require("selenium-webdriver/bidi/realmInfo")
const {LocalValue, ChannelValue} = require("selenium-webdriver/bidi/protocolValue")
const {EvaluateResultType} = require("selenium-webdriver/bidi/evaluateResult");
describe('Script events', function () {
  let driver
  beforeEach(async function () {
    driver = new Builder()
      .forBrowser('firefox')
      .setFirefoxOptions(new firefox.Options().enableBidi())
      .build()
  })
  afterEach(async function () {
    await driver.quit()
  })
  it('can listen to channel message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let message = null
    await manager.onMessage((m) => {
      message = m
    })
    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name')))
    argumentValues.push(value)
    const result = await manager.callFunctionInBrowsingContext(
      await driver.getWindowHandle(),
      '(channel) => channel("foo")',
      false,
      argumentValues,
    )
    assert.equal(result.resultType, EvaluateResultType.SUCCESS)
    assert.notEqual(message, null)
    assert.equal(message.channel, 'channel_name')
    assert.equal(message.data.type, 'string')
    assert.equal(message.data.value, 'foo')
  })
  it('can listen to realm created message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmCreated((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
  xit('can listen to realm destroyed message', async function () {
    const manager = await ScriptManager(undefined, driver)
    let realmInfo = null
    await manager.onRealmDestroyed((result) => {
      realmInfo = result
    })
    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await browsingContext.close()
    assert.notEqual(realmInfo, null)
    assert.notEqual(realmInfo.realmId, null)
    assert.equal(realmInfo.realmType, RealmType.WINDOW)
  })
})
最終更新 July 10, 2024: Release 4.22 Updates (#1765) (fa7b1165ed)




