'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /** * Common Math expressions. * * @module math */ const floor = Math.floor; /** * @function * @param {number} a * @param {number} b * @return {number} The smaller element of a and b */ const min = (a, b) => a < b ? a : b; /** * @function * @param {number} a * @param {number} b * @return {number} The bigger element of a and b */ const max = (a, b) => a > b ? a : b; /* eslint-env browser */ const BIT8 = 128; const BITS7 = 127; /** * Utility helpers for working with numbers. * * @module number */ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER; /** * @param {string} str * @return {Uint8Array} */ const _encodeUtf8Polyfill = str => { const encodedString = unescape(encodeURIComponent(str)); const len = encodedString.length; const buf = new Uint8Array(len); for (let i = 0; i < len; i++) { buf[i] = /** @type {number} */ (encodedString.codePointAt(i)); } return buf }; /* c8 ignore next */ const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null); /** * @param {string} str * @return {Uint8Array} */ const _encodeUtf8Native = str => utf8TextEncoder.encode(str); /** * @param {string} str * @return {Uint8Array} */ /* c8 ignore next */ const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill; /* c8 ignore next */ let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }); /* c8 ignore start */ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) { // Safari doesn't handle BOM correctly. // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called. // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call // Another issue is that from then on no BOM chars are recognized anymore /* c8 ignore next */ utf8TextDecoder = null; } /** * Efficient schema-less binary encoding with support for variable length encoding. * * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function. * * Encodes numbers in little-endian order (least to most significant byte order) * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/) * which is also used in Protocol Buffers. * * ```js * // encoding step * const encoder = encoding.createEncoder() * encoding.writeVarUint(encoder, 256) * encoding.writeVarString(encoder, 'Hello world!') * const buf = encoding.toUint8Array(encoder) * ``` * * ```js * // decoding step * const decoder = decoding.createDecoder(buf) * decoding.readVarUint(decoder) // => 256 * decoding.readVarString(decoder) // => 'Hello world!' * decoding.hasContent(decoder) // => false - all data is read * ``` * * @module encoding */ /** * Write one byte to the encoder. * * @function * @param {Encoder} encoder * @param {number} num The byte that is to be encoded. */ const write = (encoder, num) => { const bufferLen = encoder.cbuf.length; if (encoder.cpos === bufferLen) { encoder.bufs.push(encoder.cbuf); encoder.cbuf = new Uint8Array(bufferLen * 2); encoder.cpos = 0; } encoder.cbuf[encoder.cpos++] = num; }; /** * Write a variable length unsigned integer. Max encodable integer is 2^53. * * @function * @param {Encoder} encoder * @param {number} num The number that is to be encoded. */ const writeVarUint = (encoder, num) => { while (num > BITS7) { write(encoder, BIT8 | (BITS7 & num)); num = floor(num / 128); // shift >>> 7 } write(encoder, BITS7 & num); }; /** * A cache to store strings temporarily */ const _strBuffer = new Uint8Array(30000); const _maxStrBSize = _strBuffer.length / 3; /** * Write a variable length string. * * @function * @param {Encoder} encoder * @param {String} str The string that is to be encoded. */ const _writeVarStringNative = (encoder, str) => { if (str.length < _maxStrBSize) { // We can encode the string into the existing buffer /* c8 ignore next */ const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0; writeVarUint(encoder, written); for (let i = 0; i < written; i++) { write(encoder, _strBuffer[i]); } } else { writeVarUint8Array(encoder, encodeUtf8(str)); } }; /** * Write a variable length string. * * @function * @param {Encoder} encoder * @param {String} str The string that is to be encoded. */ const _writeVarStringPolyfill = (encoder, str) => { const encodedString = unescape(encodeURIComponent(str)); const len = encodedString.length; writeVarUint(encoder, len); for (let i = 0; i < len; i++) { write(encoder, /** @type {number} */ (encodedString.codePointAt(i))); } }; /** * Write a variable length string. * * @function * @param {Encoder} encoder * @param {String} str The string that is to be encoded. */ /* c8 ignore next */ const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill; /** * Append fixed-length Uint8Array to the encoder. * * @function * @param {Encoder} encoder * @param {Uint8Array} uint8Array */ const writeUint8Array = (encoder, uint8Array) => { const bufferLen = encoder.cbuf.length; const cpos = encoder.cpos; const leftCopyLen = min(bufferLen - cpos, uint8Array.length); const rightCopyLen = uint8Array.length - leftCopyLen; encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos); encoder.cpos += leftCopyLen; if (rightCopyLen > 0) { // Still something to write, write right half.. // Append new buffer encoder.bufs.push(encoder.cbuf); // must have at least size of remaining buffer encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen)); // copy array encoder.cbuf.set(uint8Array.subarray(leftCopyLen)); encoder.cpos = rightCopyLen; } }; /** * Append an Uint8Array to Encoder. * * @function * @param {Encoder} encoder * @param {Uint8Array} uint8Array */ const writeVarUint8Array = (encoder, uint8Array) => { writeVarUint(encoder, uint8Array.byteLength); writeUint8Array(encoder, uint8Array); }; /** * Error helpers. * * @module error */ /** * @param {string} s * @return {Error} */ /* c8 ignore next */ const create = s => new Error(s); /** * Efficient schema-less binary decoding with support for variable length encoding. * * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function. * * Encodes numbers in little-endian order (least to most significant byte order) * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/) * which is also used in Protocol Buffers. * * ```js * // encoding step * const encoder = encoding.createEncoder() * encoding.writeVarUint(encoder, 256) * encoding.writeVarString(encoder, 'Hello world!') * const buf = encoding.toUint8Array(encoder) * ``` * * ```js * // decoding step * const decoder = decoding.createDecoder(buf) * decoding.readVarUint(decoder) // => 256 * decoding.readVarString(decoder) // => 'Hello world!' * decoding.hasContent(decoder) // => false - all data is read * ``` * * @module decoding */ const errorUnexpectedEndOfArray = create('Unexpected end of array'); const errorIntegerOutOfRange = create('Integer out of Range'); /** * Create an Uint8Array view of the next `len` bytes and advance the position by `len`. * * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks. * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array. * * @function * @param {Decoder} decoder The decoder instance * @param {number} len The length of bytes to read * @return {Uint8Array} */ const readUint8Array = (decoder, len) => { const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len); decoder.pos += len; return view }; /** * Read variable length Uint8Array. * * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks. * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array. * * @function * @param {Decoder} decoder * @return {Uint8Array} */ const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder)); /** * Read one byte as unsigned integer. * @function * @param {Decoder} decoder The decoder instance * @return {number} Unsigned 8-bit integer */ const readUint8 = decoder => decoder.arr[decoder.pos++]; /** * Read unsigned integer (32bit) with variable length. * 1/8th of the storage is used as encoding overhead. * * numbers < 2^7 is stored in one bytlength * * numbers < 2^14 is stored in two bylength * * @function * @param {Decoder} decoder * @return {number} An unsigned integer.length */ const readVarUint = decoder => { let num = 0; let mult = 1; const len = decoder.arr.length; while (decoder.pos < len) { const r = decoder.arr[decoder.pos++]; // num = num | ((r & binary.BITS7) << len) num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num mult *= 128; // next iteration, shift 7 "more" to the left if (r < BIT8) { return num } /* c8 ignore start */ if (num > MAX_SAFE_INTEGER) { throw errorIntegerOutOfRange } /* c8 ignore stop */ } throw errorUnexpectedEndOfArray }; /** * We don't test this function anymore as we use native decoding/encoding by default now. * Better not modify this anymore.. * * Transforming utf8 to a string is pretty expensive. The code performs 10x better * when String.fromCodePoint is fed with all characters as arguments. * But most environments have a maximum number of arguments per functions. * For effiency reasons we apply a maximum of 10000 characters at once. * * @function * @param {Decoder} decoder * @return {String} The read String. */ /* c8 ignore start */ const _readVarStringPolyfill = decoder => { let remainingLen = readVarUint(decoder); if (remainingLen === 0) { return '' } else { let encodedString = String.fromCodePoint(readUint8(decoder)); // remember to decrease remainingLen if (--remainingLen < 100) { // do not create a Uint8Array for small strings while (remainingLen--) { encodedString += String.fromCodePoint(readUint8(decoder)); } } else { while (remainingLen > 0) { const nextLen = remainingLen < 10000 ? remainingLen : 10000; // this is dangerous, we create a fresh array view from the existing buffer const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen); decoder.pos += nextLen; // Starting with ES5.1 we can supply a generic array-like object as arguments encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes)); remainingLen -= nextLen; } } return decodeURIComponent(escape(encodedString)) } }; /* c8 ignore stop */ /** * @function * @param {Decoder} decoder * @return {String} The read String */ const _readVarStringNative = decoder => /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder)); /** * Read string of variable length * * varUint is used to store the length of the string * * @function * @param {Decoder} decoder * @return {String} The read String * */ /* c8 ignore next */ const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill; var AuthMessageType; (function (AuthMessageType) { AuthMessageType[AuthMessageType["Token"] = 0] = "Token"; AuthMessageType[AuthMessageType["PermissionDenied"] = 1] = "PermissionDenied"; AuthMessageType[AuthMessageType["Authenticated"] = 2] = "Authenticated"; })(AuthMessageType || (AuthMessageType = {})); const writeAuthentication = (encoder, auth) => { writeVarUint(encoder, AuthMessageType.Token); writeVarString(encoder, auth); }; const writePermissionDenied = (encoder, reason) => { writeVarUint(encoder, AuthMessageType.PermissionDenied); writeVarString(encoder, reason); }; const writeAuthenticated = (encoder, scope) => { writeVarUint(encoder, AuthMessageType.Authenticated); writeVarString(encoder, scope); }; const readAuthMessage = (decoder, permissionDeniedHandler, authenticatedHandler) => { switch (readVarUint(decoder)) { case AuthMessageType.PermissionDenied: { permissionDeniedHandler(readVarString(decoder)); break; } case AuthMessageType.Authenticated: { authenticatedHandler(readVarString(decoder)); break; } } }; /** * The server is terminating the connection because a data frame was received * that is too large. * See: https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code */ const MessageTooBig = { code: 1009, reason: 'Message Too Big', }; /** * The server successfully processed the request, asks that the requester reset * its document view, and is not returning any content. */ const ResetConnection = { code: 4205, reason: 'Reset Connection', }; /** * Similar to Forbidden, but specifically for use when authentication is required and has * failed or has not yet been provided. */ const Unauthorized = { code: 4401, reason: 'Unauthorized', }; /** * The request contained valid data and was understood by the server, but the server * is refusing action. */ const Forbidden = { code: 4403, reason: 'Forbidden', }; /** * The server timed out waiting for the request. */ const ConnectionTimeout = { code: 4408, reason: 'Connection Timeout', }; const awarenessStatesToArray = (states) => { return Array.from(states.entries()).map(([key, value]) => { return { clientId: key, ...value, }; }); }; /** * State of the WebSocket connection. * https://developer.mozilla.org/de/docs/Web/API/WebSocket/readyState */ exports.WsReadyStates = void 0; (function (WsReadyStates) { WsReadyStates[WsReadyStates["Connecting"] = 0] = "Connecting"; WsReadyStates[WsReadyStates["Open"] = 1] = "Open"; WsReadyStates[WsReadyStates["Closing"] = 2] = "Closing"; WsReadyStates[WsReadyStates["Closed"] = 3] = "Closed"; })(exports.WsReadyStates || (exports.WsReadyStates = {})); exports.ConnectionTimeout = ConnectionTimeout; exports.Forbidden = Forbidden; exports.MessageTooBig = MessageTooBig; exports.ResetConnection = ResetConnection; exports.Unauthorized = Unauthorized; exports.awarenessStatesToArray = awarenessStatesToArray; exports.readAuthMessage = readAuthMessage; exports.writeAuthenticated = writeAuthenticated; exports.writeAuthentication = writeAuthentication; exports.writePermissionDenied = writePermissionDenied; //# sourceMappingURL=hocuspocus-common.cjs.map