Skip to content

Commit

Permalink
fix: implement writing completely
Browse files Browse the repository at this point in the history
  • Loading branch information
KhafraDev committed Mar 6, 2024
1 parent f983336 commit ae7a600
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 13 deletions.
5 changes: 5 additions & 0 deletions lib/web/fetch/webidl.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const webidl = {}
webidl.converters = {}
webidl.util = {}
webidl.errors = {}
webidl.is = {}

webidl.errors.exception = function (message) {
return new TypeError(`${message.header}: ${message.message}`)
Expand Down Expand Up @@ -675,6 +676,10 @@ webidl.converters['record<ByteString, ByteString>'] = webidl.recordConverter(
webidl.converters.ByteString
)

webidl.is.BufferSource = function (V) {
return ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)
}

module.exports = {
webidl
}
63 changes: 50 additions & 13 deletions lib/websocket/stream/websocketstream.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const {
isEstablished,
failWebsocketConnection,
closeWebSocket,
getURLRecord
getURLRecord,
isClosing
} = require('../util')
const { kReadyState, kResponse, kByteParser, kController, kPromises } = require('../symbols')
const { states, opcodes } = require('../constants')
Expand Down Expand Up @@ -223,18 +224,7 @@ class WebSocketStream {
// 12. Let writable be a new WritableStream .
// 13. Set up writable with writeAlgorithm , closeAlgorithm , and abortAlgorithm .
const writable = new WritableStream({
write (chunk) {
if (response.socket.writable) {
// TODO: allow other chunk types
// TODO: why isn't this mentioned in the spec?

const value = Buffer.from(chunk)
const frame = new WebsocketFrameSend(value)
const buffer = frame.createFrame(opcodes.TEXT)

response.socket.write(buffer)
}
},
write: (chunk) => this.#write(chunk),
close: () => closeWebSocket(this),
abort: (reason) => this.#closeWithReason(reason)
}, new ByteLengthQueuingStrategy({ highWaterMark: 16384 }))
Expand Down Expand Up @@ -289,6 +279,53 @@ class WebSocketStream {
// discard code and reasonString and close the WebSocket with stream .
closeWebSocket(this, code, reasonString)
}

/**
* @see https://whatpr.org/websockets/48/7b748d3...7b81f79.html#write
* @param {any} chunk
*/
#write (chunk) {
// 1. Let promise be a new promise created in stream ’s relevant realm .

let data
let opcode

// 2. If chunk is a BufferSource ,
if (webidl.is.BufferSource(chunk)) {
// 2.1. Let data be a copy of the bytes given chunk .
data = Buffer.from(chunk, chunk.byteOffset, chunk.byteLength)

// 2.2. Let opcode be a binary frame opcode.
opcode = opcodes.BINARY
} else {
// 3. Otherwise,

// 3.1. Let string be the result of converting chunk to an IDL USVString .
// If this throws an exception, return a promise rejected with the exception.
// 3.2. Let data be the result of UTF-8 encoding string .
data = new TextEncoder().encode(webidl.converters.USVString(chunk))

// 3.3. Let opcode be a text frame opcode.
opcode = opcodes.TEXT
}

// 4. In parallel,
// 4.1. Wait until there is sufficient buffer space in stream to send the message.
// 4.2. If the closing handshake has not yet started , Send a WebSocket Message to
// stream comprised of data using opcode .
// 4.3. Queue a global task on the WebSocket task source given stream ’s relevant
// global object to resolve promise with undefined.
if (!isClosing(this)) {
const frame = new WebsocketFrameSend(data)
const buffer = frame.createFrame(opcode)

this[kResponse].socket.write(buffer, () => {
// TODO: what if error?
})
}

// 5. Return promise .
}
}

Object.defineProperties(WebSocketStream.prototype, {
Expand Down
5 changes: 5 additions & 0 deletions types/webidl.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,15 @@ interface WebidlConverters {
[Key: string]: (...args: any[]) => unknown
}

interface WebidlIs {
BufferSource(V: any): V is NodeJS.TypedArray | DataView | ArrayBuffer
}

export interface Webidl {
errors: WebidlErrors
util: WebidlUtil
converters: WebidlConverters
is: WebidlIs

/**
* @description Performs a brand-check on {@param V} to ensure it is a
Expand Down

0 comments on commit ae7a600

Please sign in to comment.