UNPKG

selenium-webdriver

Version:

The official WebDriver JavaScript bindings from the Selenium project

88 lines (78 loc) 4.05 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 { getBidiConnection } = require('../lib/bidi_connection') // Gates Domain's constructor so `new Network(someRandomThing)` fails loudly // instead of silently producing a broken instance. A Symbol can't be forged // or guessed, so this is real runtime enforcement, not just a TS annotation — // only a generated `Class.create(driver)` (and this package's own tests) may // pass it. It's exported deliberately, not hidden: the point is to stop // accidental misuse of the normal `new Network(x)` shape, not to defend // against someone who deliberately imports and passes this. const DOMAIN_TOKEN = Symbol('Domain internal construction token — obtained only via Class.create(driver)') /** * Describes one subscribable BiDi event, for use with Domain#addCallback(). * @param {string} method * @param {{fromWire(payload: unknown): unknown}} [type] Runtime record/union * class for the event's params, if the schema declares one. When present, * addCallback() parses each delivered payload through it before the * caller's handler runs — inbound wire payloads are validated against * their resolved type; an event's params is such a payload just as much * as a command's result is. * @returns {{method: string, type: ({fromWire(payload: unknown): unknown}|undefined)}} * The event descriptor, ready to pass to Domain#addCallback(). */ function event(method, type) { return { method, type } } /** Shared base for every generated BiDi domain class. See domain.d.ts for the typed surface. */ class Domain { #bidi constructor(bidi, token) { if (token !== DOMAIN_TOKEN) { throw new TypeError(`${new.target.name} must be constructed via ${new.target.name}.create(driver), not \`new\``) } this.#bidi = bidi } static async connect(driver) { return getBidiConnection(driver) } async send(method, params) { const response = await this.#bidi.send({ method, params }) if (response?.error !== undefined) { throw new Error(`${response.error}: ${response.message}`) } return response?.result } /** * Subscribes `handler` to a BiDi event. All the actual subscription-lifecycle * work — remote subscribe/unsubscribe, per-subscription bookkeeping — lives on * the connection itself (see Index#addCallback in bidi/index.js); Domain only * adds the one thing the connection can't do on its own: parsing a delivered * payload through the descriptor's type before the caller's handler runs. * @param {{method: string, type: ({fromWire(payload: unknown): unknown}|undefined)}} descriptor * An event descriptor from event(). * @param {function(unknown): void} handler Invoked with the event's params * (parsed through descriptor.type first, if one was given) each time it fires. * @returns {Promise<{id: string, unsubscribe: function(): Promise<void>}>} * A handle for this subscription — call `unsubscribe()` to stop receiving the event. */ async addCallback(descriptor, handler) { const dispatch = descriptor.type === undefined ? handler : (params) => handler(descriptor.type.fromWire(params)) return this.#bidi.addCallback(descriptor.method, dispatch) } } module.exports = { Domain, event, DOMAIN_TOKEN }