mirror of
https://gitlab.com/upRootNutrition/zookeeper.git
synced 2025-06-16 18:35:13 -05:00
feat: init
This commit is contained in:
parent
8379d09058
commit
2cfa016090
2929 changed files with 299087 additions and 3 deletions
652
node_modules/undici/lib/web/websocket/websocket.js
generated
vendored
Normal file
652
node_modules/undici/lib/web/websocket/websocket.js
generated
vendored
Normal file
|
@ -0,0 +1,652 @@
|
|||
'use strict'
|
||||
|
||||
const { webidl } = require('../fetch/webidl')
|
||||
const { URLSerializer } = require('../fetch/data-url')
|
||||
const { getGlobalOrigin } = require('../fetch/global')
|
||||
const { staticPropertyDescriptors, states, sentCloseFrameState, opcodes, emptyBuffer } = require('./constants')
|
||||
const {
|
||||
kWebSocketURL,
|
||||
kReadyState,
|
||||
kController,
|
||||
kBinaryType,
|
||||
kResponse,
|
||||
kSentClose,
|
||||
kByteParser
|
||||
} = require('./symbols')
|
||||
const {
|
||||
isConnecting,
|
||||
isEstablished,
|
||||
isClosed,
|
||||
isClosing,
|
||||
isValidSubprotocol,
|
||||
failWebsocketConnection,
|
||||
fireEvent
|
||||
} = require('./util')
|
||||
const { establishWebSocketConnection } = require('./connection')
|
||||
const { WebsocketFrameSend } = require('./frame')
|
||||
const { ByteParser } = require('./receiver')
|
||||
const { kEnumerableProperty, isBlobLike } = require('../../core/util')
|
||||
const { getGlobalDispatcher } = require('../../global')
|
||||
const { types } = require('node:util')
|
||||
|
||||
let experimentalWarned = false
|
||||
|
||||
// https://websockets.spec.whatwg.org/#interface-definition
|
||||
class WebSocket extends EventTarget {
|
||||
#events = {
|
||||
open: null,
|
||||
error: null,
|
||||
close: null,
|
||||
message: null
|
||||
}
|
||||
|
||||
#bufferedAmount = 0
|
||||
#protocol = ''
|
||||
#extensions = ''
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
* @param {string|string[]} protocols
|
||||
*/
|
||||
constructor (url, protocols = []) {
|
||||
super()
|
||||
|
||||
webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' })
|
||||
|
||||
if (!experimentalWarned) {
|
||||
experimentalWarned = true
|
||||
process.emitWarning('WebSockets are experimental, expect them to change at any time.', {
|
||||
code: 'UNDICI-WS'
|
||||
})
|
||||
}
|
||||
|
||||
const options = webidl.converters['DOMString or sequence<DOMString> or WebSocketInit'](protocols)
|
||||
|
||||
url = webidl.converters.USVString(url)
|
||||
protocols = options.protocols
|
||||
|
||||
// 1. Let baseURL be this's relevant settings object's API base URL.
|
||||
const baseURL = getGlobalOrigin()
|
||||
|
||||
// 1. Let urlRecord be the result of applying the URL parser to url with baseURL.
|
||||
let urlRecord
|
||||
|
||||
try {
|
||||
urlRecord = new URL(url, baseURL)
|
||||
} catch (e) {
|
||||
// 3. If urlRecord is failure, then throw a "SyntaxError" DOMException.
|
||||
throw new DOMException(e, 'SyntaxError')
|
||||
}
|
||||
|
||||
// 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws".
|
||||
if (urlRecord.protocol === 'http:') {
|
||||
urlRecord.protocol = 'ws:'
|
||||
} else if (urlRecord.protocol === 'https:') {
|
||||
// 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss".
|
||||
urlRecord.protocol = 'wss:'
|
||||
}
|
||||
|
||||
// 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException.
|
||||
if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') {
|
||||
throw new DOMException(
|
||||
`Expected a ws: or wss: protocol, got ${urlRecord.protocol}`,
|
||||
'SyntaxError'
|
||||
)
|
||||
}
|
||||
|
||||
// 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError"
|
||||
// DOMException.
|
||||
if (urlRecord.hash || urlRecord.href.endsWith('#')) {
|
||||
throw new DOMException('Got fragment', 'SyntaxError')
|
||||
}
|
||||
|
||||
// 8. If protocols is a string, set protocols to a sequence consisting
|
||||
// of just that string.
|
||||
if (typeof protocols === 'string') {
|
||||
protocols = [protocols]
|
||||
}
|
||||
|
||||
// 9. If any of the values in protocols occur more than once or otherwise
|
||||
// fail to match the requirements for elements that comprise the value
|
||||
// of `Sec-WebSocket-Protocol` fields as defined by The WebSocket
|
||||
// protocol, then throw a "SyntaxError" DOMException.
|
||||
if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) {
|
||||
throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError')
|
||||
}
|
||||
|
||||
if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) {
|
||||
throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError')
|
||||
}
|
||||
|
||||
// 10. Set this's url to urlRecord.
|
||||
this[kWebSocketURL] = new URL(urlRecord.href)
|
||||
|
||||
// 11. Let client be this's relevant settings object.
|
||||
|
||||
// 12. Run this step in parallel:
|
||||
|
||||
// 1. Establish a WebSocket connection given urlRecord, protocols,
|
||||
// and client.
|
||||
this[kController] = establishWebSocketConnection(
|
||||
urlRecord,
|
||||
protocols,
|
||||
this,
|
||||
(response) => this.#onConnectionEstablished(response),
|
||||
options
|
||||
)
|
||||
|
||||
// Each WebSocket object has an associated ready state, which is a
|
||||
// number representing the state of the connection. Initially it must
|
||||
// be CONNECTING (0).
|
||||
this[kReadyState] = WebSocket.CONNECTING
|
||||
|
||||
this[kSentClose] = sentCloseFrameState.NOT_SENT
|
||||
|
||||
// The extensions attribute must initially return the empty string.
|
||||
|
||||
// The protocol attribute must initially return the empty string.
|
||||
|
||||
// Each WebSocket object has an associated binary type, which is a
|
||||
// BinaryType. Initially it must be "blob".
|
||||
this[kBinaryType] = 'blob'
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://websockets.spec.whatwg.org/#dom-websocket-close
|
||||
* @param {number|undefined} code
|
||||
* @param {string|undefined} reason
|
||||
*/
|
||||
close (code = undefined, reason = undefined) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (code !== undefined) {
|
||||
code = webidl.converters['unsigned short'](code, { clamp: true })
|
||||
}
|
||||
|
||||
if (reason !== undefined) {
|
||||
reason = webidl.converters.USVString(reason)
|
||||
}
|
||||
|
||||
// 1. If code is present, but is neither an integer equal to 1000 nor an
|
||||
// integer in the range 3000 to 4999, inclusive, throw an
|
||||
// "InvalidAccessError" DOMException.
|
||||
if (code !== undefined) {
|
||||
if (code !== 1000 && (code < 3000 || code > 4999)) {
|
||||
throw new DOMException('invalid code', 'InvalidAccessError')
|
||||
}
|
||||
}
|
||||
|
||||
let reasonByteLength = 0
|
||||
|
||||
// 2. If reason is present, then run these substeps:
|
||||
if (reason !== undefined) {
|
||||
// 1. Let reasonBytes be the result of encoding reason.
|
||||
// 2. If reasonBytes is longer than 123 bytes, then throw a
|
||||
// "SyntaxError" DOMException.
|
||||
reasonByteLength = Buffer.byteLength(reason)
|
||||
|
||||
if (reasonByteLength > 123) {
|
||||
throw new DOMException(
|
||||
`Reason must be less than 123 bytes; received ${reasonByteLength}`,
|
||||
'SyntaxError'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Run the first matching steps from the following list:
|
||||
if (isClosing(this) || isClosed(this)) {
|
||||
// If this's ready state is CLOSING (2) or CLOSED (3)
|
||||
// Do nothing.
|
||||
} else if (!isEstablished(this)) {
|
||||
// If the WebSocket connection is not yet established
|
||||
// Fail the WebSocket connection and set this's ready state
|
||||
// to CLOSING (2).
|
||||
failWebsocketConnection(this, 'Connection was closed before it was established.')
|
||||
this[kReadyState] = WebSocket.CLOSING
|
||||
} else if (this[kSentClose] === sentCloseFrameState.NOT_SENT) {
|
||||
// If the WebSocket closing handshake has not yet been started
|
||||
// Start the WebSocket closing handshake and set this's ready
|
||||
// state to CLOSING (2).
|
||||
// - If neither code nor reason is present, the WebSocket Close
|
||||
// message must not have a body.
|
||||
// - If code is present, then the status code to use in the
|
||||
// WebSocket Close message must be the integer given by code.
|
||||
// - If reason is also present, then reasonBytes must be
|
||||
// provided in the Close message after the status code.
|
||||
|
||||
this[kSentClose] = sentCloseFrameState.PROCESSING
|
||||
|
||||
const frame = new WebsocketFrameSend()
|
||||
|
||||
// If neither code nor reason is present, the WebSocket Close
|
||||
// message must not have a body.
|
||||
|
||||
// If code is present, then the status code to use in the
|
||||
// WebSocket Close message must be the integer given by code.
|
||||
if (code !== undefined && reason === undefined) {
|
||||
frame.frameData = Buffer.allocUnsafe(2)
|
||||
frame.frameData.writeUInt16BE(code, 0)
|
||||
} else if (code !== undefined && reason !== undefined) {
|
||||
// If reason is also present, then reasonBytes must be
|
||||
// provided in the Close message after the status code.
|
||||
frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength)
|
||||
frame.frameData.writeUInt16BE(code, 0)
|
||||
// the body MAY contain UTF-8-encoded data with value /reason/
|
||||
frame.frameData.write(reason, 2, 'utf-8')
|
||||
} else {
|
||||
frame.frameData = emptyBuffer
|
||||
}
|
||||
|
||||
/** @type {import('stream').Duplex} */
|
||||
const socket = this[kResponse].socket
|
||||
|
||||
socket.write(frame.createFrame(opcodes.CLOSE), (err) => {
|
||||
if (!err) {
|
||||
this[kSentClose] = sentCloseFrameState.SENT
|
||||
}
|
||||
})
|
||||
|
||||
// Upon either sending or receiving a Close control frame, it is said
|
||||
// that _The WebSocket Closing Handshake is Started_ and that the
|
||||
// WebSocket connection is in the CLOSING state.
|
||||
this[kReadyState] = states.CLOSING
|
||||
} else {
|
||||
// Otherwise
|
||||
// Set this's ready state to CLOSING (2).
|
||||
this[kReadyState] = WebSocket.CLOSING
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://websockets.spec.whatwg.org/#dom-websocket-send
|
||||
* @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data
|
||||
*/
|
||||
send (data) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' })
|
||||
|
||||
data = webidl.converters.WebSocketSendData(data)
|
||||
|
||||
// 1. If this's ready state is CONNECTING, then throw an
|
||||
// "InvalidStateError" DOMException.
|
||||
if (isConnecting(this)) {
|
||||
throw new DOMException('Sent before connected.', 'InvalidStateError')
|
||||
}
|
||||
|
||||
// 2. Run the appropriate set of steps from the following list:
|
||||
// https://datatracker.ietf.org/doc/html/rfc6455#section-6.1
|
||||
// https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
|
||||
|
||||
if (!isEstablished(this) || isClosing(this)) {
|
||||
return
|
||||
}
|
||||
|
||||
/** @type {import('stream').Duplex} */
|
||||
const socket = this[kResponse].socket
|
||||
|
||||
// If data is a string
|
||||
if (typeof data === 'string') {
|
||||
// If the WebSocket connection is established and the WebSocket
|
||||
// closing handshake has not yet started, then the user agent
|
||||
// must send a WebSocket Message comprised of the data argument
|
||||
// using a text frame opcode; if the data cannot be sent, e.g.
|
||||
// because it would need to be buffered but the buffer is full,
|
||||
// the user agent must flag the WebSocket as full and then close
|
||||
// the WebSocket connection. Any invocation of this method with a
|
||||
// string argument that does not throw an exception must increase
|
||||
// the bufferedAmount attribute by the number of bytes needed to
|
||||
// express the argument as UTF-8.
|
||||
|
||||
const value = Buffer.from(data)
|
||||
const frame = new WebsocketFrameSend(value)
|
||||
const buffer = frame.createFrame(opcodes.TEXT)
|
||||
|
||||
this.#bufferedAmount += value.byteLength
|
||||
socket.write(buffer, () => {
|
||||
this.#bufferedAmount -= value.byteLength
|
||||
})
|
||||
} else if (types.isArrayBuffer(data)) {
|
||||
// If the WebSocket connection is established, and the WebSocket
|
||||
// closing handshake has not yet started, then the user agent must
|
||||
// send a WebSocket Message comprised of data using a binary frame
|
||||
// opcode; if the data cannot be sent, e.g. because it would need
|
||||
// to be buffered but the buffer is full, the user agent must flag
|
||||
// the WebSocket as full and then close the WebSocket connection.
|
||||
// The data to be sent is the data stored in the buffer described
|
||||
// by the ArrayBuffer object. Any invocation of this method with an
|
||||
// ArrayBuffer argument that does not throw an exception must
|
||||
// increase the bufferedAmount attribute by the length of the
|
||||
// ArrayBuffer in bytes.
|
||||
|
||||
const value = Buffer.from(data)
|
||||
const frame = new WebsocketFrameSend(value)
|
||||
const buffer = frame.createFrame(opcodes.BINARY)
|
||||
|
||||
this.#bufferedAmount += value.byteLength
|
||||
socket.write(buffer, () => {
|
||||
this.#bufferedAmount -= value.byteLength
|
||||
})
|
||||
} else if (ArrayBuffer.isView(data)) {
|
||||
// If the WebSocket connection is established, and the WebSocket
|
||||
// closing handshake has not yet started, then the user agent must
|
||||
// send a WebSocket Message comprised of data using a binary frame
|
||||
// opcode; if the data cannot be sent, e.g. because it would need to
|
||||
// be buffered but the buffer is full, the user agent must flag the
|
||||
// WebSocket as full and then close the WebSocket connection. The
|
||||
// data to be sent is the data stored in the section of the buffer
|
||||
// described by the ArrayBuffer object that data references. Any
|
||||
// invocation of this method with this kind of argument that does
|
||||
// not throw an exception must increase the bufferedAmount attribute
|
||||
// by the length of data’s buffer in bytes.
|
||||
|
||||
const ab = Buffer.from(data, data.byteOffset, data.byteLength)
|
||||
|
||||
const frame = new WebsocketFrameSend(ab)
|
||||
const buffer = frame.createFrame(opcodes.BINARY)
|
||||
|
||||
this.#bufferedAmount += ab.byteLength
|
||||
socket.write(buffer, () => {
|
||||
this.#bufferedAmount -= ab.byteLength
|
||||
})
|
||||
} else if (isBlobLike(data)) {
|
||||
// If the WebSocket connection is established, and the WebSocket
|
||||
// closing handshake has not yet started, then the user agent must
|
||||
// send a WebSocket Message comprised of data using a binary frame
|
||||
// opcode; if the data cannot be sent, e.g. because it would need to
|
||||
// be buffered but the buffer is full, the user agent must flag the
|
||||
// WebSocket as full and then close the WebSocket connection. The data
|
||||
// to be sent is the raw data represented by the Blob object. Any
|
||||
// invocation of this method with a Blob argument that does not throw
|
||||
// an exception must increase the bufferedAmount attribute by the size
|
||||
// of the Blob object’s raw data, in bytes.
|
||||
|
||||
const frame = new WebsocketFrameSend()
|
||||
|
||||
data.arrayBuffer().then((ab) => {
|
||||
const value = Buffer.from(ab)
|
||||
frame.frameData = value
|
||||
const buffer = frame.createFrame(opcodes.BINARY)
|
||||
|
||||
this.#bufferedAmount += value.byteLength
|
||||
socket.write(buffer, () => {
|
||||
this.#bufferedAmount -= value.byteLength
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get readyState () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
// The readyState getter steps are to return this's ready state.
|
||||
return this[kReadyState]
|
||||
}
|
||||
|
||||
get bufferedAmount () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#bufferedAmount
|
||||
}
|
||||
|
||||
get url () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
// The url getter steps are to return this's url, serialized.
|
||||
return URLSerializer(this[kWebSocketURL])
|
||||
}
|
||||
|
||||
get extensions () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#extensions
|
||||
}
|
||||
|
||||
get protocol () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#protocol
|
||||
}
|
||||
|
||||
get onopen () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#events.open
|
||||
}
|
||||
|
||||
set onopen (fn) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (this.#events.open) {
|
||||
this.removeEventListener('open', this.#events.open)
|
||||
}
|
||||
|
||||
if (typeof fn === 'function') {
|
||||
this.#events.open = fn
|
||||
this.addEventListener('open', fn)
|
||||
} else {
|
||||
this.#events.open = null
|
||||
}
|
||||
}
|
||||
|
||||
get onerror () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#events.error
|
||||
}
|
||||
|
||||
set onerror (fn) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (this.#events.error) {
|
||||
this.removeEventListener('error', this.#events.error)
|
||||
}
|
||||
|
||||
if (typeof fn === 'function') {
|
||||
this.#events.error = fn
|
||||
this.addEventListener('error', fn)
|
||||
} else {
|
||||
this.#events.error = null
|
||||
}
|
||||
}
|
||||
|
||||
get onclose () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#events.close
|
||||
}
|
||||
|
||||
set onclose (fn) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (this.#events.close) {
|
||||
this.removeEventListener('close', this.#events.close)
|
||||
}
|
||||
|
||||
if (typeof fn === 'function') {
|
||||
this.#events.close = fn
|
||||
this.addEventListener('close', fn)
|
||||
} else {
|
||||
this.#events.close = null
|
||||
}
|
||||
}
|
||||
|
||||
get onmessage () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this.#events.message
|
||||
}
|
||||
|
||||
set onmessage (fn) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (this.#events.message) {
|
||||
this.removeEventListener('message', this.#events.message)
|
||||
}
|
||||
|
||||
if (typeof fn === 'function') {
|
||||
this.#events.message = fn
|
||||
this.addEventListener('message', fn)
|
||||
} else {
|
||||
this.#events.message = null
|
||||
}
|
||||
}
|
||||
|
||||
get binaryType () {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
return this[kBinaryType]
|
||||
}
|
||||
|
||||
set binaryType (type) {
|
||||
webidl.brandCheck(this, WebSocket)
|
||||
|
||||
if (type !== 'blob' && type !== 'arraybuffer') {
|
||||
this[kBinaryType] = 'blob'
|
||||
} else {
|
||||
this[kBinaryType] = type
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol
|
||||
*/
|
||||
#onConnectionEstablished (response) {
|
||||
// processResponse is called when the "response’s header list has been received and initialized."
|
||||
// once this happens, the connection is open
|
||||
this[kResponse] = response
|
||||
|
||||
const parser = new ByteParser(this)
|
||||
parser.on('drain', function onParserDrain () {
|
||||
this.ws[kResponse].socket.resume()
|
||||
})
|
||||
|
||||
response.socket.ws = this
|
||||
this[kByteParser] = parser
|
||||
|
||||
// 1. Change the ready state to OPEN (1).
|
||||
this[kReadyState] = states.OPEN
|
||||
|
||||
// 2. Change the extensions attribute’s value to the extensions in use, if
|
||||
// it is not the null value.
|
||||
// https://datatracker.ietf.org/doc/html/rfc6455#section-9.1
|
||||
const extensions = response.headersList.get('sec-websocket-extensions')
|
||||
|
||||
if (extensions !== null) {
|
||||
this.#extensions = extensions
|
||||
}
|
||||
|
||||
// 3. Change the protocol attribute’s value to the subprotocol in use, if
|
||||
// it is not the null value.
|
||||
// https://datatracker.ietf.org/doc/html/rfc6455#section-1.9
|
||||
const protocol = response.headersList.get('sec-websocket-protocol')
|
||||
|
||||
if (protocol !== null) {
|
||||
this.#protocol = protocol
|
||||
}
|
||||
|
||||
// 4. Fire an event named open at the WebSocket object.
|
||||
fireEvent('open', this)
|
||||
}
|
||||
}
|
||||
|
||||
// https://websockets.spec.whatwg.org/#dom-websocket-connecting
|
||||
WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING
|
||||
// https://websockets.spec.whatwg.org/#dom-websocket-open
|
||||
WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN
|
||||
// https://websockets.spec.whatwg.org/#dom-websocket-closing
|
||||
WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING
|
||||
// https://websockets.spec.whatwg.org/#dom-websocket-closed
|
||||
WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED
|
||||
|
||||
Object.defineProperties(WebSocket.prototype, {
|
||||
CONNECTING: staticPropertyDescriptors,
|
||||
OPEN: staticPropertyDescriptors,
|
||||
CLOSING: staticPropertyDescriptors,
|
||||
CLOSED: staticPropertyDescriptors,
|
||||
url: kEnumerableProperty,
|
||||
readyState: kEnumerableProperty,
|
||||
bufferedAmount: kEnumerableProperty,
|
||||
onopen: kEnumerableProperty,
|
||||
onerror: kEnumerableProperty,
|
||||
onclose: kEnumerableProperty,
|
||||
close: kEnumerableProperty,
|
||||
onmessage: kEnumerableProperty,
|
||||
binaryType: kEnumerableProperty,
|
||||
send: kEnumerableProperty,
|
||||
extensions: kEnumerableProperty,
|
||||
protocol: kEnumerableProperty,
|
||||
[Symbol.toStringTag]: {
|
||||
value: 'WebSocket',
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
}
|
||||
})
|
||||
|
||||
Object.defineProperties(WebSocket, {
|
||||
CONNECTING: staticPropertyDescriptors,
|
||||
OPEN: staticPropertyDescriptors,
|
||||
CLOSING: staticPropertyDescriptors,
|
||||
CLOSED: staticPropertyDescriptors
|
||||
})
|
||||
|
||||
webidl.converters['sequence<DOMString>'] = webidl.sequenceConverter(
|
||||
webidl.converters.DOMString
|
||||
)
|
||||
|
||||
webidl.converters['DOMString or sequence<DOMString>'] = function (V) {
|
||||
if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) {
|
||||
return webidl.converters['sequence<DOMString>'](V)
|
||||
}
|
||||
|
||||
return webidl.converters.DOMString(V)
|
||||
}
|
||||
|
||||
// This implements the propsal made in https://github.com/whatwg/websockets/issues/42
|
||||
webidl.converters.WebSocketInit = webidl.dictionaryConverter([
|
||||
{
|
||||
key: 'protocols',
|
||||
converter: webidl.converters['DOMString or sequence<DOMString>'],
|
||||
get defaultValue () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'dispatcher',
|
||||
converter: (V) => V,
|
||||
get defaultValue () {
|
||||
return getGlobalDispatcher()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'headers',
|
||||
converter: webidl.nullableConverter(webidl.converters.HeadersInit)
|
||||
}
|
||||
])
|
||||
|
||||
webidl.converters['DOMString or sequence<DOMString> or WebSocketInit'] = function (V) {
|
||||
if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) {
|
||||
return webidl.converters.WebSocketInit(V)
|
||||
}
|
||||
|
||||
return { protocols: webidl.converters['DOMString or sequence<DOMString>'](V) }
|
||||
}
|
||||
|
||||
webidl.converters.WebSocketSendData = function (V) {
|
||||
if (webidl.util.Type(V) === 'Object') {
|
||||
if (isBlobLike(V)) {
|
||||
return webidl.converters.Blob(V, { strict: false })
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(V) || types.isArrayBuffer(V)) {
|
||||
return webidl.converters.BufferSource(V)
|
||||
}
|
||||
}
|
||||
|
||||
return webidl.converters.USVString(V)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WebSocket
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue