UNPKG

react-native-fast-io

Version:

Modern IO for React Native, built on top of Nitro and Web standards

179 lines (171 loc) 4.94 kB
"use strict"; import { Event, EventTarget, getEventAttributeValue, setEventAttributeValue } from 'event-target-shim'; import { WebSocketManager } from "../native/ws.nitro.js"; import { Blob } from "./blob.js"; var WebSocketReadyState = /*#__PURE__*/function (WebSocketReadyState) { WebSocketReadyState[WebSocketReadyState["CONNECTING"] = 0] = "CONNECTING"; WebSocketReadyState[WebSocketReadyState["OPEN"] = 1] = "OPEN"; WebSocketReadyState[WebSocketReadyState["CLOSING"] = 2] = "CLOSING"; WebSocketReadyState[WebSocketReadyState["CLOSED"] = 3] = "CLOSED"; return WebSocketReadyState; }(WebSocketReadyState || {}); /** * https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 */ const ABNORMAL_CLOSURE = 1006; /** * Events */ export class MessageEvent extends Event { constructor(data) { super('message'); this.data = data; } } export class ErrorEvent extends Event { constructor(error) { super('error'); this.error = error; } } export class CloseEvent extends Event { constructor(code = 0, reason = '') { super('close'); this.code = code; this.reason = reason; } get wasClean() { throw new Error('Not implemented'); } } /** * https://websockets.spec.whatwg.org/#interface-definition */ export class WebSocket extends EventTarget { CONNECTING = WebSocketReadyState.CONNECTING; OPEN = WebSocketReadyState.OPEN; CLOSING = WebSocketReadyState.CLOSING; CLOSED = WebSocketReadyState.CLOSED; binaryType = 'blob'; #readyState = WebSocketReadyState.CONNECTING; get readyState() { return this.#readyState; } get bufferedAmount() { throw new Error('Not implemented'); } get extensions() { throw new Error('Not implemented'); } #protocol = ''; get protocol() { return this.#protocol; } constructor(url, protocols = []) { super(); this.url = url; this.ws = WebSocketManager.create(url, Array.isArray(protocols) ? protocols : [protocols]); this.ws.onOpen(protocol => { this.#readyState = WebSocketReadyState.OPEN; this.#protocol = protocol; this.dispatchEvent(new Event('open')); }); this.ws.onMessage(data => { this.dispatchEvent(new MessageEvent(data)); }); this.ws.onArrayBuffer(buffer => { if (this.binaryType === 'blob') { this.dispatchEvent(new MessageEvent(new Blob([buffer]))); return; } this.dispatchEvent(new MessageEvent(buffer)); }); this.ws.onError(message => { this.dispatchEvent(new ErrorEvent(message)); /** * Sending `close` frame before proceeding to close the connection * https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.7 */ this.#readyState = WebSocketReadyState.CLOSED; this.dispatchEvent(new CloseEvent(ABNORMAL_CLOSURE)); this.close(); }); this.ws.onClose((code, reason) => { this.#readyState = WebSocketReadyState.CLOSED; this.dispatchEvent(new CloseEvent(code, reason)); }); this.ws.connect(); } /** * https://websockets.spec.whatwg.org/#dom-websocket-send */ send(message) { if (this.#readyState === WebSocketReadyState.CONNECTING) { throw new Error('InvalidStateError'); } if (this.#readyState !== WebSocketReadyState.OPEN) { return; } if (typeof message === 'string') { this.ws.send(message); return; } if (message instanceof ArrayBuffer) { this.ws.sendArrayBuffer(message); return; } if (ArrayBuffer.isView(message)) { this.ws.sendArrayBuffer(message.buffer); return; } if (message instanceof Blob) { ; (async () => { const arrayBuffer = await message.arrayBuffer(); this.ws.sendArrayBuffer(arrayBuffer); })(); return; } } /** * https://websockets.spec.whatwg.org/#dom-websocket-close */ close(code = 1000, reason = '') { if (this.#readyState === WebSocketReadyState.CLOSING || this.#readyState === WebSocketReadyState.CLOSED) { return; } if (code !== 1000 && (code < 3000 || code > 4999)) { throw new Error('Invalid close code. Must be 1000 or in range 3000-4999.'); } this.#readyState = WebSocketReadyState.CLOSING; this.ws.close(code, reason); } ping() { this.ws.ping(); } get onopen() { return getEventAttributeValue(this, 'open'); } set onopen(value) { setEventAttributeValue(this, 'open', value); } get onmessage() { return getEventAttributeValue(this, 'message'); } set onmessage(value) { setEventAttributeValue(this, 'message', value); } get onerror() { return getEventAttributeValue(this, 'error'); } set onerror(value) { setEventAttributeValue(this, 'error', value); } get onclose() { return getEventAttributeValue(this, 'close'); } set onclose(value) { setEventAttributeValue(this, 'close', value); } } //# sourceMappingURL=ws.js.map