diff --git a/source_commit b/source_commit index 7e14d980..98fe7052 100644 --- a/source_commit +++ b/source_commit @@ -1 +1 @@ -279e47a116271f2b797d7365b1d7f27ca7ed9cc4 +7cb5dce27cd7daf1d8c88a172136ef52588f4840 diff --git a/uws.js b/uws.js index 24991207..72ce28ba 100644 --- a/uws.js +++ b/uws.js @@ -23,26 +23,37 @@ module.exports = (() => { } })(); +const MAX_U8 = Math.pow(2, 8) - 1; +const MAX_U32 = Math.pow(2, 32) - 1; +const textEncoder = new TextEncoder(); +const toArrayBuffer = (value) => { + if (typeof value === 'string') return textEncoder.encode(value); + else if (!value) return new Uint8Array(0); + else return value; +}; + module.exports.DeclarativeResponse = class DeclarativeResponse { constructor() { this.instructions = []; } - // Utility method to encode text and append instruction - _appendInstruction(opcode, ...text) { + // Append instruction and 1-byte length values + _appendInstruction(opcode, ...values) { this.instructions.push(opcode); - text.forEach(str => { - const bytes = (typeof str === 'string') ? new TextEncoder().encode(str) : str; - this.instructions.push(bytes.length, ...bytes); + values.forEach(value => { + const arrayBuffer = toArrayBuffer(value); + if (arrayBuffer.byteLength > MAX_U8) throw new RangeError('Data length exceeds '+ MAX_U8); + this.instructions.push(arrayBuffer.byteLength, ...arrayBuffer); }); } - // Utility method to append 2-byte length text in little-endian format - _appendInstructionWithLength(opcode, text) { - this.instructions.push(opcode); - const bytes = new TextEncoder().encode(text); - const length = bytes.length; - this.instructions.push(length & 0xff, (length >> 8) & 0xff, ...bytes); + // Append instruction and 4-byte length value + _appendInstructionWithLength(opcode, value) { + const arrayBuffer = toArrayBuffer(value); + if (arrayBuffer.byteLength > MAX_U32) throw new RangeError('Data length exceeds '+ MAX_U32); + const lengthBuffer = new Buffer.alloc(4); + lengthBuffer.writeUInt32LE(arrayBuffer.byteLength); + this.instructions.push(opcode, ...lengthBuffer, ...arrayBuffer); } writeHeader(key, value) { return this._appendInstruction(1, key, value), this; } @@ -51,11 +62,9 @@ module.exports.DeclarativeResponse = class DeclarativeResponse { writeHeaderValue(key) { return this._appendInstruction(4, key), this; } write(value) { return this._appendInstructionWithLength(5, value), this; } writeParameterValue(key) { return this._appendInstruction(6, key), this; } - - end(str) { - const bytes = (typeof str === 'string') ? new TextEncoder().encode(str) : str; - const length = bytes.length; - this.instructions.push(0, length & 0xff, (length >> 8) & 0xff, ...bytes); + writeStatus(status) { return this._appendInstruction(7, status), this; } + end(value) { + this._appendInstructionWithLength(0, value); return new Uint8Array(this.instructions).buffer; } } diff --git a/uws_linux_x64_115.node b/uws_linux_x64_115.node index cbc4ed18..434dc2d7 100644 Binary files a/uws_linux_x64_115.node and b/uws_linux_x64_115.node differ diff --git a/uws_linux_x64_127.node b/uws_linux_x64_127.node index 09c6be22..d10d0d1a 100644 Binary files a/uws_linux_x64_127.node and b/uws_linux_x64_127.node differ diff --git a/uws_linux_x64_137.node b/uws_linux_x64_137.node index a19ba564..b2b8a64b 100644 Binary files a/uws_linux_x64_137.node and b/uws_linux_x64_137.node differ diff --git a/uws_linux_x64_141.node b/uws_linux_x64_141.node index 84ba2b96..664a0acd 100644 Binary files a/uws_linux_x64_141.node and b/uws_linux_x64_141.node differ