UNPKG

selenium-webdriver

Version:

The official WebDriver JavaScript bindings from the Selenium project

85 lines (78 loc) 3.22 kB
// Licensed to the Software Freedom Conservancy (SFC) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The SFC licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. const BiDi = require('../bidi') /** * One BiDi connection per driver, kept outside the WebDriver class itself so * it isn't a discoverable method on it — see * docs/decisions/17670-bidi-implementation-boundaries.md. Not re-exported from * the package's public entry point. * * Stores the in-flight promise, not the resolved connection, so a second * concurrent call for the same driver awaits the same creation instead of * racing its own and leaking whichever connection loses. * @type {WeakMap<object, Promise<BiDi>>} */ const connections = new WeakMap() /** * Returns the BiDi connection for `driver`, creating it on first access. * @param {object} driver The WebDriver instance to obtain a BiDi connection for. * @returns {Promise<BiDi>} A promise resolving to `driver`'s BiDi connection, shared * with any other in-flight or already-resolved call for the same driver. */ function getBidiConnection(driver) { if (!connections.has(driver)) { connections.set(driver, createConnection(driver)) } return connections.get(driver) } /** * @param {object} driver * @returns {Promise<BiDi>} */ async function createConnection(driver) { const caps = await driver.getCapabilities() const webSocketUrl = caps['map_'].get('webSocketUrl') if (!webSocketUrl) { throw new Error('WebDriver instance must support BiDi protocol') } return new BiDi(webSocketUrl.replace('localhost', '127.0.0.1')) } /** * Closes `driver`'s BiDi connection, if one was ever opened. A no-op * otherwise — must not lazily create a connection just to close it. * * Callers (e.g. quit()) invoke this fire-and-forget, so it must never reject: * if the original connection attempt itself had failed, `pending` is already * rejected and there is nothing live to close. * @param {object} driver The WebDriver instance whose BiDi connection should be closed. * @returns {Promise<void>} A promise that always resolves, once any open connection * has been closed (or immediately, if none was ever opened). */ async function closeBidiConnection(driver) { const pending = connections.get(driver) if (pending === undefined) { return } connections.delete(driver) try { const connection = await pending await connection.close() } catch { // Nothing to close — the original connection attempt failed. } } module.exports = { getBidiConnection, closeBidiConnection }