How to use recvChannelsCreated method in wpt

Best JavaScript code snippet using wpt

channel.sub.js

Source:channel.sub.js Github

copy

Full Screen

1(function() {2 function randInt(bits) {3 if (bits < 1 || bits > 53) {4 throw new TypeError();5 } else {6 if (bits >= 1 && bits <= 30) {7 return 0 | ((1 << bits) * Math.random());8 } else {9 var high = (0 | ((1 << (bits - 30)) * Math.random())) * (1 << 30);10 var low = 0 | ((1 << 30) * Math.random());11 return high + low;12 }13 }14 }15 function toHex(x, length) {16 var rv = x.toString(16);17 while (rv.length < length) {18 rv = "0" + rv;19 }20 return rv;21 }22 function createUuid() {23 return [toHex(randInt(32), 8),24 toHex(randInt(16), 4),25 toHex(0x4000 | randInt(12), 4),26 toHex(0x8000 | randInt(14), 4),27 toHex(randInt(48), 12)].join("-");28 }29 /**30 * Cache of WebSocket instances per channel31 *32 * For reading there can only be one channel with each UUID, so we33 * just have a simple map of {uuid: WebSocket}. The socket can be34 * closed when the channel is closed.35 *36 * For writing there can be many channels for each uuid. Those can37 * share a websocket (within a specific global), so we have a map38 * of {uuid: [WebSocket, count]}. Count is incremented when a39 * channel is opened with a given uuid, and decremented when its40 * closed. When the count reaches zero we can close the underlying41 * socket.42 */43 class SocketCache {44 constructor() {45 this.readSockets = new Map();46 this.writeSockets = new Map();47 };48 async getOrCreate(type, uuid, onmessage=null) {49 function createSocket() {50 let protocol = self.isSecureContext ? "wss" : "ws";51 let port = self.isSecureContext? "{{ports[wss][0]}}" : "{{ports[ws][0]}}";52 let url = `${protocol}://{{host}}:${port}/msg_channel?uuid=${uuid}&direction=${type}`;53 let socket = new WebSocket(url);54 if (onmessage !== null) {55 socket.onmessage = onmessage;56 };57 return new Promise(resolve => socket.addEventListener("open", () => resolve(socket)));58 }59 let socket;60 if (type === "read") {61 if (this.readSockets.has(uuid)) {62 throw new Error("Can't create multiple read sockets with same UUID");63 }64 socket = await createSocket();65 // If the socket is closed by the server, ensure it's removed from the cache66 socket.addEventListener("close", () => this.readSockets.delete(uuid));67 this.readSockets.set(uuid, socket);68 } else if (type === "write") {69 let count;70 if (onmessage !== null) {71 throw new Error("Can't set message handler for write sockets");72 }73 if (this.writeSockets.has(uuid)) {74 [socket, count] = this.writeSockets.get(uuid);75 } else {76 socket = await createSocket();77 count = 0;78 }79 count += 1;80 // If the socket is closed by the server, ensure it's removed from the cache81 socket.addEventListener("close", () => this.writeSockets.delete(uuid));82 this.writeSockets.set(uuid, [socket, count]);83 } else {84 throw new Error(`Unknown type ${type}`);85 }86 return socket;87 };88 async close(type, uuid) {89 let target = type === "read" ? this.readSockets : this.writeSockets;90 const data = target.get(uuid);91 if (!data) {92 return;93 }94 let count, socket;95 if (type == "read") {96 socket = data;97 count = 0;98 } else if (type === "write") {99 [socket, count] = data;100 count -= 1;101 if (count > 0) {102 target.set(uuid, [socket, count]);103 }104 };105 if (count <= 0 && socket) {106 target.delete(uuid);107 socket.close(1000);108 await new Promise(resolve => socket.addEventListener("close", resolve));109 }110 };111 async closeAll() {112 let sockets = [];113 this.readSockets.forEach(value => sockets.push(value));114 this.writeSockets.forEach(value => sockets.push(value[0]));115 let closePromises = sockets.map(socket =>116 new Promise(resolve => socket.addEventListener("close", resolve)));117 sockets.forEach(socket => socket.close(1000));118 this.readSockets.clear();119 this.writeSockets.clear();120 await Promise.all(closePromises);121 }122 }123 const socketCache = new SocketCache();124 /**125 * Abstract base class for objects that allow sending / receiving126 * messages over a channel.127 */128 class Channel {129 type = null;130 constructor(uuid) {131 /** UUID for the channel */132 this.uuid = uuid;133 this.socket = null;134 this.eventListeners = {135 connect: new Set(),136 close: new Set()137 };138 }139 hasConnection() {140 return this.socket !== null && this.socket.readyState <= WebSocket.OPEN;141 }142 /**143 * Connect to the channel.144 *145 * @param {Function} onmessage - Event handler function for146 * the underlying websocket message.147 */148 async connect(onmessage) {149 if (this.hasConnection()) {150 return;151 }152 this.socket = await socketCache.getOrCreate(this.type, this.uuid, onmessage);153 this._dispatch("connect");154 }155 /**156 * Close the channel and underlying websocket connection157 */158 async close() {159 this.socket = null;160 await socketCache.close(this.type, this.uuid);161 this._dispatch("close");162 }163 /**164 * Add an event callback function. Supported message types are165 * "connect", "close", and "message" (for ``RecvChannel``).166 *167 * @param {string} type - Message type.168 * @param {Function} fn - Callback function. This is called169 * with an event-like object, with ``type`` and ``data``170 * properties.171 */172 addEventListener(type, fn) {173 if (typeof type !== "string") {174 throw new TypeError(`Expected string, got ${typeof type}`);175 }176 if (typeof fn !== "function") {177 throw new TypeError(`Expected function, got ${typeof fn}`);178 }179 if (!this.eventListeners.hasOwnProperty(type)) {180 throw new Error(`Unrecognised event type ${type}`);181 }182 this.eventListeners[type].add(fn);183 };184 /**185 * Remove an event callback function.186 *187 * @param {string} type - Event type.188 * @param {Function} fn - Callback function to remove.189 */190 removeEventListener(type, fn) {191 if (!typeof type === "string") {192 throw new TypeError(`Expected string, got ${typeof type}`);193 }194 if (typeof fn !== "function") {195 throw new TypeError(`Expected function, got ${typeof fn}`);196 }197 let listeners = this.eventListeners[type];198 if (listeners) {199 listeners.delete(fn);200 }201 };202 _dispatch(type, data) {203 let listeners = this.eventListeners[type];204 if (listeners) {205 // If any listener throws we end up not calling the other206 // listeners. This hopefully makes debugging easier, but207 // is different to DOM event listeners.208 listeners.forEach(fn => fn({type, data}));209 }210 };211 }212 /**213 * Send messages over a channel214 */215 class SendChannel extends Channel {216 type = "write";217 /**218 * Connect to the channel. Automatically called when sending the219 * first message.220 */221 async connect() {222 return super.connect(null);223 }224 async _send(cmd, body=null) {225 if (!this.hasConnection()) {226 await this.connect();227 }228 this.socket.send(JSON.stringify([cmd, body]));229 }230 /**231 * Send a message. The message object must be JSON-serializable.232 *233 * @param {Object} msg - The message object to send.234 */235 async send(msg) {236 await this._send("message", msg);237 }238 /**239 * Disconnect the associated `RecvChannel <#RecvChannel>`_, if240 * any, on the server side.241 */242 async disconnectReader() {243 await this._send("disconnectReader");244 }245 /**246 * Disconnect this channel on the server side.247 */248 async delete() {249 await this._send("delete");250 }251 };252 self.SendChannel = SendChannel;253 const recvChannelsCreated = new Set();254 /**255 * Receive messages over a channel256 */257 class RecvChannel extends Channel {258 type = "read";259 constructor(uuid) {260 if (recvChannelsCreated.has(uuid)) {261 throw new Error(`Already created RecvChannel with id ${uuid}`);262 }263 super(uuid);264 this.eventListeners.message = new Set();265 }266 async connect() {267 if (this.hasConnection()) {268 return;269 }270 await super.connect(event => this.readMessage(event.data));271 }272 readMessage(data) {273 let msg = JSON.parse(data);274 this._dispatch("message", msg);275 }276 /**277 * Wait for the next message and return it (after passing it to278 * existing handlers)279 *280 * @returns {Promise} - Promise that resolves to the message data.281 */282 nextMessage() {283 return new Promise(resolve => {284 let fn = ({data}) => {285 this.removeEventListener("message", fn);286 resolve(data);287 };288 this.addEventListener("message", fn);289 });290 }291 }292 /**293 * Create a new channel pair294 *295 * @returns {Array} - Array of [RecvChannel, SendChannel] for the same channel.296 */297 self.channel = function() {298 let uuid = createUuid();299 let recvChannel = new RecvChannel(uuid);300 let sendChannel = new SendChannel(uuid);301 return [recvChannel, sendChannel];302 };303 /**304 * Create an unconnected channel defined by a `uuid` in305 * ``location.href`` for listening for `RemoteGlobal306 * <#RemoteGlobal>`_ messages.307 *308 * @returns {RemoteGlobalCommandRecvChannel} - Disconnected channel309 */310 self.global_channel = function() {311 let uuid = new URLSearchParams(location.search).get("uuid");312 if (!uuid) {313 throw new Error("URL must have a uuid parameter to use as a RemoteGlobal");314 }315 return new RemoteGlobalCommandRecvChannel(new RecvChannel(uuid));316 };317 /**318 * Start listening for `RemoteGlobal <#RemoteGlobal>`_ messages on319 * a channel defined by a `uuid` in `location.href`320 *321 * @returns {RemoteGlobalCommandRecvChannel} - Connected channel322 */323 self.start_global_channel = async function() {324 let channel = self.global_channel();325 await channel.connect();326 return channel;327 };328 /**329 * Close all WebSockets used by channels in the current realm.330 *331 */332 self.close_all_channel_sockets = async function() {333 await socketCache.closeAll();334 // Spinning the event loop after the close events is necessary to335 // ensure that the channels really are closed and don't affect336 // bfcache behaviour in at least some implementations.337 await new Promise(resolve => setTimeout(resolve, 0));338 };339 /**340 * Handler for `RemoteGlobal <#RemoteGlobal>`_ commands.341 *342 * This can't be constructed directly but must be obtained from343 * `global_channel() <#global_channel>`_ or344 * `start_global_channel() <#start_global_channel>`_.345 */346 class RemoteGlobalCommandRecvChannel {347 constructor(recvChannel) {348 this.channel = recvChannel;349 this.uuid = recvChannel.uuid;350 this.channel.addEventListener("message", ({data}) => this.handleMessage(data));351 this.messageHandlers = new Set();352 };353 /**354 * Connect to the channel and start handling messages.355 */356 async connect() {357 await this.channel.connect();358 }359 /**360 * Close the channel and underlying websocket connection361 */362 async close() {363 await this.channel.close();364 }365 async handleMessage(msg) {366 const {id, command, params, respChannel} = msg;367 let result = {};368 let resp = {id, result};369 if (command === "call") {370 const fn = deserialize(params.fn);371 const args = params.args.map(deserialize);372 try {373 let resultValue = await fn(...args);374 result.result = serialize(resultValue);375 } catch(e) {376 let exception = serialize(e);377 const getAsInt = (obj, prop) => {378 let value = prop in obj ? parseInt(obj[prop]) : 0;379 return Number.isNaN(value) ? 0 : value;380 };381 result.exceptionDetails = {382 text: e.toString(),383 lineNumber: getAsInt(e, "lineNumber"),384 columnNumber: getAsInt(e, "columnNumber"),385 exception386 };387 }388 } else if (command === "postMessage") {389 this.messageHandlers.forEach(fn => fn(deserialize(params.msg)));390 }391 if (respChannel) {392 let chan = deserialize(respChannel);393 await chan.connect();394 await chan.send(resp);395 }396 }397 /**398 * Add a handler for ``postMessage`` messages399 *400 * @param {Function} fn - Callback function that receives the401 * message.402 */403 addMessageHandler(fn) {404 this.messageHandlers.add(fn);405 }406 /**407 * Remove a handler for ``postMessage`` messages408 *409 * @param {Function} fn - Callback function to remove410 */411 removeMessageHandler(fn) {412 this.messageHandlers.delete(fn);413 }414 /**415 * Wait for the next ``postMessage`` message and return it416 * (after passing it to existing handlers)417 *418 * @returns {Promise} - Promise that resolves to the message.419 */420 nextMessage() {421 return new Promise(resolve => {422 let fn = (msg) => {423 this.removeMessageHandler(fn);424 resolve(msg);425 };426 this.addMessageHandler(fn);427 });428 }429 }430 class RemoteGlobalResponseRecvChannel {431 constructor(recvChannel) {432 this.channel = recvChannel;433 this.channel.addEventListener("message", ({data}) => this.handleMessage(data));434 this.responseHandlers = new Map();435 }436 setResponseHandler(commandId, fn) {437 this.responseHandlers.set(commandId, fn);438 }439 handleMessage(msg) {440 let {id, result} = msg;441 let handler = this.responseHandlers.get(id);442 if (handler) {443 this.responseHandlers.delete(id);444 handler(result);445 }446 }447 close() {448 return this.channel.close();449 }450 }451 /**452 * Object representing a remote global that has a453 * `RemoteGlobalCommandRecvChannel454 * <#RemoteGlobalCommandRecvChannel>`_455 */456 class RemoteGlobal {457 /**458 * Create a new RemoteGlobal object.459 *460 * This doesn't actually construct the global itself; that461 * must be done elsewhere, with a ``uuid`` query parameter in462 * its URL set to the same as the ``uuid`` property of this463 * object.464 *465 * @param {SendChannel|string} [dest] - Either a SendChannel466 * to the destination, or the UUID of the destination. If467 * ommitted, a new UUID is generated, which can be used when468 * constructing the URL for the global.469 *470 */471 constructor(dest) {472 if (dest === undefined || dest === null) {473 dest = createUuid();474 }475 if (typeof dest == "string") {476 /** UUID for the global */477 this.uuid = dest;478 this.sendChannel = new SendChannel(dest);479 } else if (dest instanceof SendChannel) {480 this.sendChannel = dest;481 this.uuid = dest.uuid;482 } else {483 throw new TypeError("Unrecognised type, expected string or SendChannel");484 }485 this.recvChannel = null;486 this.respChannel = null;487 this.connected = false;488 this.commandId = 0;489 }490 /**491 * Connect to the channel. Automatically called when sending the492 * first message493 */494 async connect() {495 if (this.connected) {496 return;497 }498 let [recvChannel, respChannel] = self.channel();499 await Promise.all([this.sendChannel.connect(), recvChannel.connect()]);500 this.recvChannel = new RemoteGlobalResponseRecvChannel(recvChannel);501 this.respChannel = respChannel;502 this.connected = true;503 }504 async sendMessage(command, params, hasResp=true) {505 if (!this.connected) {506 await this.connect();507 }508 let msg = {id: this.commandId++, command, params};509 if (hasResp) {510 msg.respChannel = serialize(this.respChannel);511 }512 let response;513 if (hasResp) {514 response = new Promise(resolve =>515 this.recvChannel.setResponseHandler(msg.id, resolve));516 } else {517 response = null;518 }519 this.sendChannel.send(msg);520 return await response;521 }522 /**523 * Run the function ``fn`` in the remote global, passing arguments524 * ``args``, and return the result after awaiting any returned525 * promise.526 *527 * @param {Function} fn - Function to run in the remote global.528 * @param {...Any} args - Arguments to pass to the function529 * @returns {Promise} - Promise resolving to the return value530 * of the function.531 */532 async call(fn, ...args) {533 let result = await this.sendMessage("call", {fn: serialize(fn), args: args.map(x => serialize(x))}, true);534 if (result.exceptionDetails) {535 throw deserialize(result.exceptionDetails.exception);536 }537 return deserialize(result.result);538 }539 /**540 * Post a message to the remote541 *542 * @param {Any} msg - The message to send.543 */544 async postMessage(msg) {545 await this.sendMessage("postMessage", {msg: serialize(msg)}, false);546 }547 /**548 * Disconnect the associated `RemoteGlobalCommandRecvChannel549 * <#RemoteGlobalCommandRecvChannel>`_, if any, on the server550 * side.551 *552 * @returns {Promise} - Resolved once the channel is disconnected.553 */554 disconnectReader() {555 // This causes any readers to disconnect until they are explictly reconnected556 return this.sendChannel.disconnectReader();557 }558 /**559 * Close the channel and underlying websocket connections560 */561 close() {562 let closers = [this.sendChannel.close()];563 if (this.recvChannel !== null) {564 closers.push(this.recvChannel.close());565 }566 if (this.respChannel !== null) {567 closers.push(this.respChannel.close());568 }569 return Promise.all(closers);570 }571 }572 self.RemoteGlobal = RemoteGlobal;573 function typeName(value) {574 let type = typeof value;575 if (type === "undefined" ||576 type === "string" ||577 type === "boolean" ||578 type === "number" ||579 type === "bigint" ||580 type === "symbol" ||581 type === "function") {582 return type;583 }584 if (value === null) {585 return "null";586 }587 // The handling of cross-global objects here is broken588 if (value instanceof RemoteObject) {589 return "remoteobject";590 }591 if (value instanceof SendChannel) {592 return "sendchannel";593 }594 if (value instanceof RecvChannel) {595 return "recvchannel";596 }597 if (value instanceof Error) {598 return "error";599 }600 if (Array.isArray(value)) {601 return "array";602 }603 let constructor = value.constructor && value.constructor.name;604 if (constructor === "RegExp" ||605 constructor === "Date" ||606 constructor === "Map" ||607 constructor === "Set" ||608 constructor == "WeakMap" ||609 constructor == "WeakSet") {610 return constructor.toLowerCase();611 }612 // The handling of cross-global objects here is broken613 if (typeof window == "object" && window === self) {614 if (value instanceof Element) {615 return "element";616 }617 if (value instanceof Document) {618 return "document";619 }620 if (value instanceof Node) {621 return "node";622 }623 if (value instanceof Window) {624 return "window";625 }626 }627 if (Promise.resolve(value) === value) {628 return "promise";629 }630 return "object";631 }632 let remoteObjectsById = new Map();633 function remoteId(obj) {634 let rv;635 rv = createUuid();636 remoteObjectsById.set(rv, obj);637 return rv;638 }639 /**640 * Representation of a non-primitive type passed through a channel641 */642 class RemoteObject {643 constructor(type, objectId) {644 this.type = type;645 this.objectId = objectId;646 }647 /**648 * Create a RemoteObject containing a handle to reference obj649 *650 * @param {Any} obj - The object to reference.651 */652 static from(obj) {653 let type = typeName(obj);654 let id = remoteId(obj);655 return new RemoteObject(type, id);656 }657 /**658 * Return the local object referenced by the ``objectId`` of659 * this ``RemoteObject``, or ``null`` if there isn't a such an660 * object in this realm.661 */662 toLocal() {663 if (remoteObjectsById.has(this.objectId)) {664 return remoteObjectsById.get(this.objectId);665 }666 return null;667 }668 /**669 * Remove the object from the local cache. This means that future670 * calls to ``toLocal`` with the same objectId will always return671 * ``null``.672 */673 delete() {674 remoteObjectsById.delete(this.objectId);675 }676 }677 self.RemoteObject = RemoteObject;678 /**679 * Serialize an object as a JSON-compatible representation.680 *681 * The format used is similar (but not identical to)682 * `WebDriver-BiDi683 * <https://w3c.github.io/webdriver-bidi/#data-types-protocolValue>`_.684 *685 * Each item to be serialized can have the following fields:686 *687 * type - The name of the type being represented e.g. "string", or688 * "map". For primitives this matches ``typeof``, but for689 * ``object`` types that have particular support in the protocol690 * e.g. arrays and maps, it is a custom value.691 *692 * value - A serialized representation of the object value. For693 * container types this is a JSON container (i.e. an object or an694 * array) containing a serialized representation of the child695 * values.696 *697 * objectId - An integer used to handle object graphs. Where698 * an object is present more than once in the serialization, the699 * first instance has both ``value`` and ``objectId`` fields, but700 * when encountered again, only ``objectId`` is present, with the701 * same value as the first instance of the object.702 *703 * @param {Any} inValue - The value to be serialized.704 * @returns {Object} - The serialized object value.705 */706 function serialize(inValue) {707 const queue = [{item: inValue}];708 let outValue = null;709 // Map from container object input to output value710 let objectsSeen = new Map();711 let lastObjectId = 0;712 /* Instead of making this recursive, use a queue holding the objects to be713 * serialized. Each item in the queue can have the following properties:714 *715 * item (required) - the input item to be serialized716 *717 * target - For collections, the output serialized object to718 * which the serialization of the current item will be added.719 *720 * targetName - For serializing object members, the name of721 * the property. For serializing maps either "key" or "value",722 * depending on whether the item represents a key or a value723 * in the map.724 */725 while (queue.length > 0) {726 const {item, target, targetName} = queue.shift();727 let type = typeName(item);728 let serialized = {type};729 if (objectsSeen.has(item)) {730 let outputValue = objectsSeen.get(item);731 if (!outputValue.hasOwnProperty("objectId")) {732 outputValue.objectId = lastObjectId++;733 }734 serialized.objectId = outputValue.objectId;735 } else {736 switch (type) {737 case "undefined":738 case "null":739 break;740 case "string":741 case "boolean":742 serialized.value = item;743 break;744 case "number":745 if (item !== item) {746 serialized.value = "NaN";747 } else if (item === 0 && 1/item == Number.NEGATIVE_INFINITY) {748 serialized.value = "-0";749 } else if (item === Number.POSITIVE_INFINITY) {750 serialized.value = "+Infinity";751 } else if (item === Number.NEGATIVE_INFINITY) {752 serialized.value = "-Infinity";753 } else {754 serialized.value = item;755 }756 break;757 case "bigint":758 case "function":759 serialized.value = item.toString();760 break;761 case "remoteobject":762 serialized.value = {763 type: item.type,764 objectId: item.objectId765 };766 break;767 case "sendchannel":768 serialized.value = item.uuid;769 break;770 case "regexp":771 serialized.value = {772 pattern: item.source,773 flags: item.flags774 };775 break;776 case "date":777 serialized.value = Date.prototype.toJSON.call(item);778 break;779 case "error":780 serialized.value = {781 type: item.constructor.name,782 name: item.name,783 message: item.message,784 lineNumber: item.lineNumber,785 columnNumber: item.columnNumber,786 fileName: item.fileName,787 stack: item.stack,788 };789 break;790 case "array":791 case "set":792 serialized.value = [];793 for (let child of item) {794 queue.push({item: child, target: serialized});795 }796 break;797 case "object":798 serialized.value = {};799 for (let [targetName, child] of Object.entries(item)) {800 queue.push({item: child, target: serialized, targetName});801 }802 break;803 case "map":804 serialized.value = [];805 for (let [childKey, childValue] of item.entries()) {806 queue.push({item: childKey, target: serialized, targetName: "key"});807 queue.push({item: childValue, target: serialized, targetName: "value"});808 }809 break;810 default:811 throw new TypeError(`Can't serialize value of type ${type}; consider using RemoteObject.from() to wrap the object`);812 };813 }814 if (serialized.objectId === undefined) {815 objectsSeen.set(item, serialized);816 }817 if (target === undefined) {818 if (outValue !== null) {819 throw new Error("Tried to create multiple output values");820 }821 outValue = serialized;822 } else {823 switch (target.type) {824 case "array":825 case "set":826 target.value.push(serialized);827 break;828 case "object":829 target.value[targetName] = serialized;830 break;831 case "map":832 // We always serialize key and value as adjacent items in the queue,833 // so when we get the key push a new output array and then the value will834 // be added on the next iteration.835 if (targetName === "key") {836 target.value.push([]);837 }838 target.value[target.value.length - 1].push(serialized);839 break;840 default:841 throw new Error(`Unknown collection target type ${target.type}`);842 }843 }844 }845 return outValue;846 }847 /**848 * Deserialize an object from a JSON-compatible representation.849 *850 * For details on the serialized representation see serialize().851 *852 * @param {Object} obj - The value to be deserialized.853 * @returns {Any} - The deserialized value.854 */855 function deserialize(obj) {856 let deserialized = null;857 let queue = [{item: obj, target: null}];858 let objectMap = new Map();859 /* Instead of making this recursive, use a queue holding the objects to be860 * deserialized. Each item in the queue has the following properties:861 *862 * item - The input item to be deserialised.863 *864 * target - For members of a collection, a wrapper around the865 * output collection. This has a ``type`` field which is the866 * name of the collection type, and a ``value`` field which is867 * the actual output collection. For primitives, this is null.868 *869 * targetName - For object members, the property name on the870 * output object. For maps, "key" if the item is a key in the output map,871 * or "value" if it's a value in the output map.872 */873 while (queue.length > 0) {874 const {item, target, targetName} = queue.shift();875 const {type, value, objectId} = item;876 let result;877 let newTarget;878 if (objectId !== undefined && value === undefined) {879 result = objectMap.get(objectId);880 } else {881 switch(type) {882 case "undefined":883 result = undefined;884 break;885 case "null":886 result = null;887 break;888 case "string":889 case "boolean":890 result = value;891 break;892 case "number":893 if (typeof value === "string") {894 switch(value) {895 case "NaN":896 result = NaN;897 break;898 case "-0":899 result = -0;900 break;901 case "+Infinity":902 result = Number.POSITIVE_INFINITY;903 break;904 case "-Infinity":905 result = Number.NEGATIVE_INFINITY;906 break;907 default:908 throw new Error(`Unexpected number value "${value}"`);909 }910 } else {911 result = value;912 }913 break;914 case "bigint":915 result = BigInt(value);916 break;917 case "function":918 result = new Function("...args", `return (${value}).apply(null, args)`);919 break;920 case "remoteobject":921 let remote = new RemoteObject(value.type, value.objectId);922 let local = remote.toLocal();923 if (local !== null) {924 result = local;925 } else {926 result = remote;927 }928 break;929 case "sendchannel":930 result = new SendChannel(value);931 break;932 case "regexp":933 result = new RegExp(value.pattern, value.flags);934 break;935 case "date":936 result = new Date(value);937 break;938 case "error":939 // The item.value.type property is the name of the error constructor.940 // If we have a constructor with the same name in the current realm,941 // construct an instance of that type, otherwise use a generic Error942 // type.943 if (item.value.type in self &&944 typeof self[item.value.type] === "function") {945 result = new self[item.value.type](item.value.message);946 } else {947 result = new Error(item.value.message);948 }949 result.name = item.value.name;950 result.lineNumber = item.value.lineNumber;951 result.columnNumber = item.value.columnNumber;952 result.fileName = item.value.fileName;953 result.stack = item.value.stack;954 break;955 case "array":956 result = [];957 newTarget = {type, value: result};958 for (let child of value) {959 queue.push({item: child, target: newTarget});960 }961 break;962 case "set":963 result = new Set();964 newTarget = {type, value: result};965 for (let child of value) {966 queue.push({item: child, target: newTarget});967 }968 break;969 case "object":970 result = {};971 newTarget = {type, value: result};972 for (let [targetName, child] of Object.entries(value)) {973 queue.push({item: child, target: newTarget, targetName});974 }975 break;976 case "map":977 result = new Map();978 newTarget = {type, value: result};979 for (let [key, child] of value) {980 queue.push({item: key, target: newTarget, targetName: "key"});981 queue.push({item: child, target: newTarget, targetName: "value"});982 }983 break;984 default:985 throw new TypeError(`Can't deserialize object of type ${type}`);986 }987 if (objectId !== undefined) {988 objectMap.set(objectId, result);989 }990 }991 if (target === null) {992 if (deserialized !== null) {993 throw new Error(`Tried to deserialized a non-root output value without a target`994 ` container object.`);995 }996 deserialized = result;997 } else {998 switch(target.type) {999 case "array":1000 target.value.push(result);1001 break;1002 case "set":1003 target.value.add(result);1004 break;1005 case "object":1006 target.value[targetName] = result;1007 break;1008 case "map":1009 // For maps the same target wrapper is shared between key and value.1010 // After deserializing the key, set the `key` property on the target1011 // until we come to the value.1012 if (targetName === "key") {1013 target.key = result;1014 } else {1015 target.value.set(target.key, result);1016 }1017 break;1018 default:1019 throw new Error(`Unknown target type ${target.type}`);1020 }1021 }1022 }1023 return deserialized;1024 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1wpt.recvChannelsCreated(channelsCreated);2wpt.recvChannelClosed(channelClosed);3wpt.recvChannelMessage(channelMessage);4wpt.recvChannelError(channelError);5wpt.recvChannelBufferedAmountLow(channelBufferedAmountLow);6wpt.recvChannelStateChanged(channelStateChanged);7wpt.recvDataChannelCreated(dataChannelCreated);8wpt.recvDataChannelClosed(dataChannelClosed);9wpt.recvDataChannelMessage(dataChannelMessage);10wpt.recvDataChannelError(dataChannelError);11wpt.recvDataChannelBufferedAmountLow(dataChannelBufferedAmountLow);12wpt.recvDataChannelStateChanged(dataChannelStateChanged);13wpt.recvPeerConnectionCreated(peerConnectionCreated);14wpt.recvPeerConnectionClosed(peerConnectionClosed);15wpt.recvPeerConnectionIceCandidate(peerConnectionIceCandidate);16wpt.recvPeerConnectionIceCandidateError(peerConnectionIceCandidateError);17wpt.recvPeerConnectionIceConnectionStateChanged(peerConnectionIceConnectionStateChanged);

Full Screen

Using AI Code Generation

copy

Full Screen

1function testRecvChannelsCreated() {2 var chan1 = new RTCDataChannel();3 var chan2 = new RTCDataChannel();4 var chan3 = new RTCDataChannel();5 var chan4 = new RTCDataChannel();6 var chan5 = new RTCDataChannel();7 var chan6 = new RTCDataChannel();8 var chan7 = new RTCDataChannel();9 var chan8 = new RTCDataChannel();10 var chan9 = new RTCDataChannel();11 var chan10 = new RTCDataChannel();12 var chan11 = new RTCDataChannel();13 var chan12 = new RTCDataChannel();14 var chan13 = new RTCDataChannel();15 var chan14 = new RTCDataChannel();16 var chan15 = new RTCDataChannel();17 var chan16 = new RTCDataChannel();18 var chan17 = new RTCDataChannel();19 var chan18 = new RTCDataChannel();20 var chan19 = new RTCDataChannel();21 var chan20 = new RTCDataChannel();22 var chan21 = new RTCDataChannel();23 var chan22 = new RTCDataChannel();24 var chan23 = new RTCDataChannel();25 var chan24 = new RTCDataChannel();26 var chan25 = new RTCDataChannel();27 var chan26 = new RTCDataChannel();28 var chan27 = new RTCDataChannel();29 var chan28 = new RTCDataChannel();30 var chan29 = new RTCDataChannel();31 var chan30 = new RTCDataChannel();32 var chan31 = new RTCDataChannel();33 var chan32 = new RTCDataChannel();34 var chan33 = new RTCDataChannel();35 var chan34 = new RTCDataChannel();36 var chan35 = new RTCDataChannel();37 var chan36 = new RTCDataChannel();38 var chan37 = new RTCDataChannel();39 var chan38 = new RTCDataChannel();40 var chan39 = new RTCDataChannel();41 var chan40 = new RTCDataChannel();42 var chan41 = new RTCDataChannel();43 var chan42 = new RTCDataChannel();44 var chan43 = new RTCDataChannel();45 var chan44 = new RTCDataChannel();46 var chan45 = new RTCDataChannel();47 var chan46 = new RTCDataChannel();48 var chan47 = new RTCDataChannel();49 var chan48 = new RTCDataChannel();50 var chan49 = new RTCDataChannel();

Full Screen

Using AI Code Generation

copy

Full Screen

1var channel = new MessageChannel();2var port1 = channel.port1;3var port2 = channel.port2;4port1.onmessage = function(e) {5 postMessage("port1 received: " + e.data);6};7port2.onmessage = function(e) {8 postMessage("port2 received: " + e.data);9};10port1.postMessage("Hello");11port2.postMessage("World");12var channel = new MessageChannel();13var port1 = channel.port1;14var port2 = channel.port2;15port1.onmessage = function(e) {16 postMessage("port1 received: " + e.data);17};18port2.onmessage = function(e) {19 postMessage("port2 received: " + e.data);20};21port1.postMessage("Hello");22port2.postMessage("World");23var channel = new MessageChannel();24var port1 = channel.port1;25var port2 = channel.port2;26port1.onmessage = function(e) {27 postMessage("port1 received: " + e.data);28};29port2.onmessage = function(e) {30 postMessage("port2 received: " + e.data);31};32port1.postMessage("Hello");33port2.postMessage("World");34var channel = new MessageChannel();35var port1 = channel.port1;36var port2 = channel.port2;37port1.onmessage = function(e) {38 postMessage("port1 received: " + e.data);39};40port2.onmessage = function(e) {41 postMessage("port2 received: " + e.data);42};43port1.postMessage("Hello");44port2.postMessage("World");45var channel = new MessageChannel();46var port1 = channel.port1;47var port2 = channel.port2;48port1.onmessage = function(e) {49 postMessage("port1 received: " + e.data);50};51port2.onmessage = function(e) {52 postMessage("port2 received: " + e.data);53};54port1.postMessage("Hello");55port2.postMessage("World");56var channel = new MessageChannel();57var port1 = channel.port1;58var port2 = channel.port2;59port1.onmessage = function(e) {

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptoolkit = require('wptoolkit');2var obj = new wptoolkit();3obj.recvChannelsCreated(function(err, resp){4 console.log(resp);5});6var wptoolkit = require('wptoolkit');7var obj = new wptoolkit();8obj.recvChannelsUpdated(function(err, resp){9 console.log(resp);10});11var wptoolkit = require('wptoolkit');12var obj = new wptoolkit();13obj.recvChannelsDeleted(function(err, resp){14 console.log(resp);15});16var wptoolkit = require('wptoolkit');17var obj = new wptoolkit();18obj.recvChannelsSubscribed(function(err, resp){19 console.log(resp);20});21var wptoolkit = require('wptoolkit');22var obj = new wptoolkit();23obj.recvChannelsUnsubscribed(function(err, resp){24 console.log(resp);25});26var wptoolkit = require('wptoolkit');27var obj = new wptoolkit();28obj.recvMessagesCreated(function(err, resp){29 console.log(resp);30});31var wptoolkit = require('wptoolkit');32var obj = new wptoolkit();33obj.recvMessagesUpdated(function(err, resp){34 console.log(resp);35});36var wptoolkit = require('wptoolkit');37var obj = new wptoolkit();38obj.recvMessagesDeleted(function(err, resp){39 console.log(resp);40});41var wptoolkit = require('wptoolkit');42var obj = new wptoolkit();43obj.recvMessagesDelivered(function(err, resp){

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful