UNPKG

recoder-code

Version:

🚀 AI-powered development platform - Chat with 32+ models, build projects, automate workflows. Free models included!

1,537 lines (1,493 loc) • 110 kB
'use strict'; var stream = require('stream'); var module$1 = require('module'); var decoder; try { decoder = new TextDecoder(); } catch(error) {} var src; var srcEnd; var position$1 = 0; const EMPTY_ARRAY = []; var strings = EMPTY_ARRAY; var stringPosition = 0; var currentUnpackr = {}; var currentStructures; var srcString; var srcStringStart = 0; var srcStringEnd = 0; var bundledStrings$1; var referenceMap; var currentExtensions = []; var dataView; var defaultOptions = { useRecords: false, mapsAsObjects: true }; class C1Type {} const C1 = new C1Type(); C1.name = 'MessagePack 0xC1'; var sequentialMode = false; var inlineObjectReadThreshold = 2; var readStruct$1, onLoadedStructures$1, onSaveState; // no-eval build try { new Function(''); } catch(error) { // if eval variants are not supported, do not create inline object readers ever inlineObjectReadThreshold = Infinity; } class Unpackr { constructor(options) { if (options) { if (options.useRecords === false && options.mapsAsObjects === undefined) options.mapsAsObjects = true; if (options.sequential && options.trusted !== false) { options.trusted = true; if (!options.structures && options.useRecords != false) { options.structures = []; if (!options.maxSharedStructures) options.maxSharedStructures = 0; } } if (options.structures) options.structures.sharedLength = options.structures.length; else if (options.getStructures) { (options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures options.structures.sharedLength = 0; } if (options.int64AsNumber) { options.int64AsType = 'number'; } } Object.assign(this, options); } unpack(source, options) { if (src) { // re-entrant execution, save the state and restore it after we do this unpack return saveState$1(() => { clearSource(); return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options) }) } if (!source.buffer && source.constructor === ArrayBuffer) source = typeof Buffer !== 'undefined' ? Buffer.from(source) : new Uint8Array(source); if (typeof options === 'object') { srcEnd = options.end || source.length; position$1 = options.start || 0; } else { position$1 = 0; srcEnd = options > -1 ? options : source.length; } stringPosition = 0; srcStringEnd = 0; srcString = null; strings = EMPTY_ARRAY; bundledStrings$1 = null; src = source; // this provides cached access to the data view for a buffer if it is getting reused, which is a recommend // technique for getting data from a database where it can be copied into an existing buffer instead of creating // new ones try { dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength)); } catch(error) { // if it doesn't have a buffer, maybe it is the wrong type of object src = null; if (source instanceof Uint8Array) throw error throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source)) } if (this instanceof Unpackr) { currentUnpackr = this; if (this.structures) { currentStructures = this.structures; return checkedRead(options) } else if (!currentStructures || currentStructures.length > 0) { currentStructures = []; } } else { currentUnpackr = defaultOptions; if (!currentStructures || currentStructures.length > 0) currentStructures = []; } return checkedRead(options) } unpackMultiple(source, forEach) { let values, lastPosition = 0; try { sequentialMode = true; let size = source.length; let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size); if (forEach) { if (forEach(value, lastPosition, position$1) === false) return; while(position$1 < size) { lastPosition = position$1; if (forEach(checkedRead(), lastPosition, position$1) === false) { return } } } else { values = [ value ]; while(position$1 < size) { lastPosition = position$1; values.push(checkedRead()); } return values } } catch(error) { error.lastPosition = lastPosition; error.values = values; throw error } finally { sequentialMode = false; clearSource(); } } _mergeStructures(loadedStructures, existingStructures) { if (onLoadedStructures$1) loadedStructures = onLoadedStructures$1.call(this, loadedStructures); loadedStructures = loadedStructures || []; if (Object.isFrozen(loadedStructures)) loadedStructures = loadedStructures.map(structure => structure.slice(0)); for (let i = 0, l = loadedStructures.length; i < l; i++) { let structure = loadedStructures[i]; if (structure) { structure.isShared = true; if (i >= 32) structure.highByte = (i - 32) >> 5; } } loadedStructures.sharedLength = loadedStructures.length; for (let id in existingStructures || []) { if (id >= 0) { let structure = loadedStructures[id]; let existing = existingStructures[id]; if (existing) { if (structure) (loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure; loadedStructures[id] = existing; } } } return this.structures = loadedStructures } decode(source, options) { return this.unpack(source, options) } } function checkedRead(options) { try { if (!currentUnpackr.trusted && !sequentialMode) { let sharedLength = currentStructures.sharedLength || 0; if (sharedLength < currentStructures.length) currentStructures.length = sharedLength; } let result; if (currentUnpackr.randomAccessStructure && src[position$1] < 0x40 && src[position$1] >= 0x20 && readStruct$1) { result = readStruct$1(src, position$1, srcEnd, currentUnpackr); src = null; // dispose of this so that recursive unpack calls don't save state if (!(options && options.lazy) && result) result = result.toJSON(); position$1 = srcEnd; } else result = read(); if (bundledStrings$1) { // bundled strings to skip past position$1 = bundledStrings$1.postBundlePosition; bundledStrings$1 = null; } if (sequentialMode) // we only need to restore the structures if there was an error, but if we completed a read, // we can clear this out and keep the structures we read currentStructures.restoreStructures = null; if (position$1 == srcEnd) { // finished reading this source, cleanup references if (currentStructures && currentStructures.restoreStructures) restoreStructures(); currentStructures = null; src = null; if (referenceMap) referenceMap = null; } else if (position$1 > srcEnd) { // over read throw new Error('Unexpected end of MessagePack data') } else if (!sequentialMode) { let jsonView; try { jsonView = JSON.stringify(result, (_, value) => typeof value === "bigint" ? `${value}n` : value).slice(0, 100); } catch(error) { jsonView = '(JSON view not available ' + error + ')'; } throw new Error('Data read, but end of buffer not reached ' + jsonView) } // else more to read, but we are reading sequentially, so don't clear source yet return result } catch(error) { if (currentStructures && currentStructures.restoreStructures) restoreStructures(); clearSource(); if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position$1 > srcEnd) { error.incomplete = true; } throw error } } function restoreStructures() { for (let id in currentStructures.restoreStructures) { currentStructures[id] = currentStructures.restoreStructures[id]; } currentStructures.restoreStructures = null; } function read() { let token = src[position$1++]; if (token < 0xa0) { if (token < 0x80) { if (token < 0x40) return token else { let structure = currentStructures[token & 0x3f] || currentUnpackr.getStructures && loadStructures()[token & 0x3f]; if (structure) { if (!structure.read) { structure.read = createStructureReader(structure, token & 0x3f); } return structure.read() } else return token } } else if (token < 0x90) { // map token -= 0x80; if (currentUnpackr.mapsAsObjects) { let object = {}; for (let i = 0; i < token; i++) { let key = readKey(); if (key === '__proto__') key = '__proto_'; object[key] = read(); } return object } else { let map = new Map(); for (let i = 0; i < token; i++) { map.set(read(), read()); } return map } } else { token -= 0x90; let array = new Array(token); for (let i = 0; i < token; i++) { array[i] = read(); } if (currentUnpackr.freezeData) return Object.freeze(array) return array } } else if (token < 0xc0) { // fixstr let length = token - 0xa0; if (srcStringEnd >= position$1) { return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart) } if (srcStringEnd == 0 && srcEnd < 140) { // for small blocks, avoiding the overhead of the extract call is helpful let string = length < 16 ? shortStringInJS(length) : longStringInJS(length); if (string != null) return string } return readFixedString(length) } else { let value; switch (token) { case 0xc0: return null case 0xc1: if (bundledStrings$1) { value = read(); // followed by the length of the string in characters (not bytes!) if (value > 0) return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value) else return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value) } return C1; // "never-used", return special object to denote that case 0xc2: return false case 0xc3: return true case 0xc4: // bin 8 value = src[position$1++]; if (value === undefined) throw new Error('Unexpected end of buffer') return readBin(value) case 0xc5: // bin 16 value = dataView.getUint16(position$1); position$1 += 2; return readBin(value) case 0xc6: // bin 32 value = dataView.getUint32(position$1); position$1 += 4; return readBin(value) case 0xc7: // ext 8 return readExt(src[position$1++]) case 0xc8: // ext 16 value = dataView.getUint16(position$1); position$1 += 2; return readExt(value) case 0xc9: // ext 32 value = dataView.getUint32(position$1); position$1 += 4; return readExt(value) case 0xca: value = dataView.getFloat32(position$1); if (currentUnpackr.useFloat32 > 2) { // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved let multiplier = mult10[((src[position$1] & 0x7f) << 1) | (src[position$1 + 1] >> 7)]; position$1 += 4; return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier } position$1 += 4; return value case 0xcb: value = dataView.getFloat64(position$1); position$1 += 8; return value // uint handlers case 0xcc: return src[position$1++] case 0xcd: value = dataView.getUint16(position$1); position$1 += 2; return value case 0xce: value = dataView.getUint32(position$1); position$1 += 4; return value case 0xcf: if (currentUnpackr.int64AsType === 'number') { value = dataView.getUint32(position$1) * 0x100000000; value += dataView.getUint32(position$1 + 4); } else if (currentUnpackr.int64AsType === 'string') { value = dataView.getBigUint64(position$1).toString(); } else if (currentUnpackr.int64AsType === 'auto') { value = dataView.getBigUint64(position$1); if (value<=BigInt(2)<<BigInt(52)) value=Number(value); } else value = dataView.getBigUint64(position$1); position$1 += 8; return value // int handlers case 0xd0: return dataView.getInt8(position$1++) case 0xd1: value = dataView.getInt16(position$1); position$1 += 2; return value case 0xd2: value = dataView.getInt32(position$1); position$1 += 4; return value case 0xd3: if (currentUnpackr.int64AsType === 'number') { value = dataView.getInt32(position$1) * 0x100000000; value += dataView.getUint32(position$1 + 4); } else if (currentUnpackr.int64AsType === 'string') { value = dataView.getBigInt64(position$1).toString(); } else if (currentUnpackr.int64AsType === 'auto') { value = dataView.getBigInt64(position$1); if (value>=BigInt(-2)<<BigInt(52)&&value<=BigInt(2)<<BigInt(52)) value=Number(value); } else value = dataView.getBigInt64(position$1); position$1 += 8; return value case 0xd4: // fixext 1 value = src[position$1++]; if (value == 0x72) { return recordDefinition(src[position$1++] & 0x3f) } else { let extension = currentExtensions[value]; if (extension) { if (extension.read) { position$1++; // skip filler byte return extension.read(read()) } else if (extension.noBuffer) { position$1++; // skip filler byte return extension() } else return extension(src.subarray(position$1, ++position$1)) } else throw new Error('Unknown extension ' + value) } case 0xd5: // fixext 2 value = src[position$1]; if (value == 0x72) { position$1++; return recordDefinition(src[position$1++] & 0x3f, src[position$1++]) } else return readExt(2) case 0xd6: // fixext 4 return readExt(4) case 0xd7: // fixext 8 return readExt(8) case 0xd8: // fixext 16 return readExt(16) case 0xd9: // str 8 value = src[position$1++]; if (srcStringEnd >= position$1) { return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart) } return readString8(value) case 0xda: // str 16 value = dataView.getUint16(position$1); position$1 += 2; if (srcStringEnd >= position$1) { return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart) } return readString16(value) case 0xdb: // str 32 value = dataView.getUint32(position$1); position$1 += 4; if (srcStringEnd >= position$1) { return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart) } return readString32(value) case 0xdc: // array 16 value = dataView.getUint16(position$1); position$1 += 2; return readArray(value) case 0xdd: // array 32 value = dataView.getUint32(position$1); position$1 += 4; return readArray(value) case 0xde: // map 16 value = dataView.getUint16(position$1); position$1 += 2; return readMap(value) case 0xdf: // map 32 value = dataView.getUint32(position$1); position$1 += 4; return readMap(value) default: // negative int if (token >= 0xe0) return token - 0x100 if (token === undefined) { let error = new Error('Unexpected end of MessagePack data'); error.incomplete = true; throw error } throw new Error('Unknown MessagePack token ' + token) } } } const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/; function createStructureReader(structure, firstId) { function readObject() { // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function if (readObject.count++ > inlineObjectReadThreshold) { let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') + '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read); if (structure.highByte === 0) structure.read = createSecondByteReader(firstId, structure.read); return readObject() // second byte is already read, if there is one so immediately read object } let object = {}; for (let i = 0, l = structure.length; i < l; i++) { let key = structure[i]; if (key === '__proto__') key = '__proto_'; object[key] = read(); } if (currentUnpackr.freezeData) return Object.freeze(object); return object } readObject.count = 0; if (structure.highByte === 0) { return createSecondByteReader(firstId, readObject) } return readObject } const createSecondByteReader = (firstId, read0) => { return function() { let highByte = src[position$1++]; if (highByte === 0) return read0() let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5); let structure = currentStructures[id] || loadStructures()[id]; if (!structure) { throw new Error('Record id is not defined for ' + id) } if (!structure.read) structure.read = createStructureReader(structure, firstId); return structure.read() } }; function loadStructures() { let loadedStructures = saveState$1(() => { // save the state in case getStructures modifies our buffer src = null; return currentUnpackr.getStructures() }); return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures) } var readFixedString = readStringJS; var readString8 = readStringJS; var readString16 = readStringJS; var readString32 = readStringJS; exports.isNativeAccelerationEnabled = false; function setExtractor(extractStrings) { exports.isNativeAccelerationEnabled = true; readFixedString = readString(1); readString8 = readString(2); readString16 = readString(3); readString32 = readString(5); function readString(headerLength) { return function readString(length) { let string = strings[stringPosition++]; if (string == null) { if (bundledStrings$1) return readStringJS(length) let byteOffset = src.byteOffset; let extraction = extractStrings(position$1 - headerLength + byteOffset, srcEnd + byteOffset, src.buffer); if (typeof extraction == 'string') { string = extraction; strings = EMPTY_ARRAY; } else { strings = extraction; stringPosition = 1; srcStringEnd = 1; // even if a utf-8 string was decoded, must indicate we are in the midst of extracted strings and can't skip strings string = strings[0]; if (string === undefined) throw new Error('Unexpected end of buffer') } } let srcStringLength = string.length; if (srcStringLength <= length) { position$1 += length; return string } srcString = string; srcStringStart = position$1; srcStringEnd = position$1 + srcStringLength; position$1 += length; return string.slice(0, length) // we know we just want the beginning } } } function readStringJS(length) { let result; if (length < 16) { if (result = shortStringInJS(length)) return result } if (length > 64 && decoder) return decoder.decode(src.subarray(position$1, position$1 += length)) const end = position$1 + length; const units = []; result = ''; while (position$1 < end) { const byte1 = src[position$1++]; if ((byte1 & 0x80) === 0) { // 1 byte units.push(byte1); } else if ((byte1 & 0xe0) === 0xc0) { // 2 bytes const byte2 = src[position$1++] & 0x3f; units.push(((byte1 & 0x1f) << 6) | byte2); } else if ((byte1 & 0xf0) === 0xe0) { // 3 bytes const byte2 = src[position$1++] & 0x3f; const byte3 = src[position$1++] & 0x3f; units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3); } else if ((byte1 & 0xf8) === 0xf0) { // 4 bytes const byte2 = src[position$1++] & 0x3f; const byte3 = src[position$1++] & 0x3f; const byte4 = src[position$1++] & 0x3f; let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; if (unit > 0xffff) { unit -= 0x10000; units.push(((unit >>> 10) & 0x3ff) | 0xd800); unit = 0xdc00 | (unit & 0x3ff); } units.push(unit); } else { units.push(byte1); } if (units.length >= 0x1000) { result += fromCharCode.apply(String, units); units.length = 0; } } if (units.length > 0) { result += fromCharCode.apply(String, units); } return result } function readString(source, start, length) { let existingSrc = src; src = source; position$1 = start; try { return readStringJS(length); } finally { src = existingSrc; } } function readArray(length) { let array = new Array(length); for (let i = 0; i < length; i++) { array[i] = read(); } if (currentUnpackr.freezeData) return Object.freeze(array) return array } function readMap(length) { if (currentUnpackr.mapsAsObjects) { let object = {}; for (let i = 0; i < length; i++) { let key = readKey(); if (key === '__proto__') key = '__proto_'; object[key] = read(); } return object } else { let map = new Map(); for (let i = 0; i < length; i++) { map.set(read(), read()); } return map } } var fromCharCode = String.fromCharCode; function longStringInJS(length) { let start = position$1; let bytes = new Array(length); for (let i = 0; i < length; i++) { const byte = src[position$1++]; if ((byte & 0x80) > 0) { position$1 = start; return } bytes[i] = byte; } return fromCharCode.apply(String, bytes) } function shortStringInJS(length) { if (length < 4) { if (length < 2) { if (length === 0) return '' else { let a = src[position$1++]; if ((a & 0x80) > 1) { position$1 -= 1; return } return fromCharCode(a) } } else { let a = src[position$1++]; let b = src[position$1++]; if ((a & 0x80) > 0 || (b & 0x80) > 0) { position$1 -= 2; return } if (length < 3) return fromCharCode(a, b) let c = src[position$1++]; if ((c & 0x80) > 0) { position$1 -= 3; return } return fromCharCode(a, b, c) } } else { let a = src[position$1++]; let b = src[position$1++]; let c = src[position$1++]; let d = src[position$1++]; if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) { position$1 -= 4; return } if (length < 6) { if (length === 4) return fromCharCode(a, b, c, d) else { let e = src[position$1++]; if ((e & 0x80) > 0) { position$1 -= 5; return } return fromCharCode(a, b, c, d, e) } } else if (length < 8) { let e = src[position$1++]; let f = src[position$1++]; if ((e & 0x80) > 0 || (f & 0x80) > 0) { position$1 -= 6; return } if (length < 7) return fromCharCode(a, b, c, d, e, f) let g = src[position$1++]; if ((g & 0x80) > 0) { position$1 -= 7; return } return fromCharCode(a, b, c, d, e, f, g) } else { let e = src[position$1++]; let f = src[position$1++]; let g = src[position$1++]; let h = src[position$1++]; if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) { position$1 -= 8; return } if (length < 10) { if (length === 8) return fromCharCode(a, b, c, d, e, f, g, h) else { let i = src[position$1++]; if ((i & 0x80) > 0) { position$1 -= 9; return } return fromCharCode(a, b, c, d, e, f, g, h, i) } } else if (length < 12) { let i = src[position$1++]; let j = src[position$1++]; if ((i & 0x80) > 0 || (j & 0x80) > 0) { position$1 -= 10; return } if (length < 11) return fromCharCode(a, b, c, d, e, f, g, h, i, j) let k = src[position$1++]; if ((k & 0x80) > 0) { position$1 -= 11; return } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k) } else { let i = src[position$1++]; let j = src[position$1++]; let k = src[position$1++]; let l = src[position$1++]; if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) { position$1 -= 12; return } if (length < 14) { if (length === 12) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l) else { let m = src[position$1++]; if ((m & 0x80) > 0) { position$1 -= 13; return } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m) } } else { let m = src[position$1++]; let n = src[position$1++]; if ((m & 0x80) > 0 || (n & 0x80) > 0) { position$1 -= 14; return } if (length < 15) return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n) let o = src[position$1++]; if ((o & 0x80) > 0) { position$1 -= 15; return } return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) } } } } } function readOnlyJSString() { let token = src[position$1++]; let length; if (token < 0xc0) { // fixstr length = token - 0xa0; } else { switch(token) { case 0xd9: // str 8 length = src[position$1++]; break case 0xda: // str 16 length = dataView.getUint16(position$1); position$1 += 2; break case 0xdb: // str 32 length = dataView.getUint32(position$1); position$1 += 4; break default: throw new Error('Expected string') } } return readStringJS(length) } function readBin(length) { return currentUnpackr.copyBuffers ? // specifically use the copying slice (not the node one) Uint8Array.prototype.slice.call(src, position$1, position$1 += length) : src.subarray(position$1, position$1 += length) } function readExt(length) { let type = src[position$1++]; if (currentExtensions[type]) { let end; return currentExtensions[type](src.subarray(position$1, end = (position$1 += length)), (readPosition) => { position$1 = readPosition; try { return read(); } finally { position$1 = end; } }) } else throw new Error('Unknown extension type ' + type) } var keyCache = new Array(4096); function readKey() { let length = src[position$1++]; if (length >= 0xa0 && length < 0xc0) { // fixstr, potentially use key cache length = length - 0xa0; if (srcStringEnd >= position$1) // if it has been extracted, must use it (and faster anyway) return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart) else if (!(srcStringEnd == 0 && srcEnd < 180)) return readFixedString(length) } else { // not cacheable, go back and do a standard read position$1--; return asSafeString(read()) } let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff; let entry = keyCache[key]; let checkPosition = position$1; let end = position$1 + length - 3; let chunk; let i = 0; if (entry && entry.bytes == length) { while (checkPosition < end) { chunk = dataView.getUint32(checkPosition); if (chunk != entry[i++]) { checkPosition = 0x70000000; break } checkPosition += 4; } end += 3; while (checkPosition < end) { chunk = src[checkPosition++]; if (chunk != entry[i++]) { checkPosition = 0x70000000; break } } if (checkPosition === end) { position$1 = checkPosition; return entry.string } end -= 3; checkPosition = position$1; } entry = []; keyCache[key] = entry; entry.bytes = length; while (checkPosition < end) { chunk = dataView.getUint32(checkPosition); entry.push(chunk); checkPosition += 4; } end += 3; while (checkPosition < end) { chunk = src[checkPosition++]; entry.push(chunk); } // for small blocks, avoiding the overhead of the extract call is helpful let string = length < 16 ? shortStringInJS(length) : longStringInJS(length); if (string != null) return entry.string = string return entry.string = readFixedString(length) } function asSafeString(property) { // protect against expensive (DoS) string conversions if (typeof property === 'string') return property; if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString(); if (property == null) return property + ''; if (currentUnpackr.allowArraysInMapKeys && Array.isArray(property) && property.flat().every(item => ['string', 'number', 'boolean', 'bigint'].includes(typeof item))) { return property.flat().toString(); } throw new Error(`Invalid property type for record: ${typeof property}`); } // the registration of the record definition extension (as "r") const recordDefinition = (id, highByte) => { let structure = read().map(asSafeString); // ensure that all keys are strings and // that the array is mutable let firstByte = id; if (highByte !== undefined) { id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id); structure.highByte = highByte; } let existingStructure = currentStructures[id]; // If it is a shared structure, we need to restore any changes after reading. // Also in sequential mode, we may get incomplete reads and thus errors, and we need to restore // to the state prior to an incomplete read in order to properly resume. if (existingStructure && (existingStructure.isShared || sequentialMode)) { (currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure; } currentStructures[id] = structure; structure.read = createStructureReader(structure, firstByte); return structure.read() }; currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here currentExtensions[0].noBuffer = true; currentExtensions[0x42] = data => { let headLength = (data.byteLength % 8) || 8; let head = BigInt(data[0] & 0x80 ? data[0] - 0x100 : data[0]); for (let i = 1; i < headLength; i++) { head <<= BigInt(8); head += BigInt(data[i]); } if (data.byteLength !== headLength) { let view = new DataView(data.buffer, data.byteOffset, data.byteLength); let decode = (start, end) => { let length = end - start; if (length <= 40) { let out = view.getBigUint64(start); for (let i = start + 8; i < end; i += 8) { out <<= BigInt(64n); out |= view.getBigUint64(i); } return out } // if (length === 8) return view.getBigUint64(start) let middle = start + (length >> 4 << 3); let left = decode(start, middle); let right = decode(middle, end); return (left << BigInt((end - middle) * 8)) | right }; head = (head << BigInt((view.byteLength - headLength) * 8)) | decode(headLength, view.byteLength); } return head }; let errors = { Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, AggregateError: typeof AggregateError === 'function' ? AggregateError : null, }; currentExtensions[0x65] = () => { let data = read(); if (!errors[data[0]]) { let error = Error(data[1], { cause: data[2] }); error.name = data[0]; return error } return errors[data[0]](data[1], { cause: data[2] }) }; currentExtensions[0x69] = (data) => { // id extension (for structured clones) if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled') let id = dataView.getUint32(position$1 - 4); if (!referenceMap) referenceMap = new Map(); let token = src[position$1]; let target; // TODO: handle any other types that can cycle and make the code more robust if there are other extensions if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd) target = []; else if (token >= 0x80 && token < 0x90 || token == 0xde || token == 0xdf) target = new Map(); else if ((token >= 0xc7 && token <= 0xc9 || token >= 0xd4 && token <= 0xd8) && src[position$1 + 1] === 0x73) target = new Set(); else target = {}; let refEntry = { target }; // a placeholder object referenceMap.set(id, refEntry); let targetProperties = read(); // read the next value as the target object to id if (!refEntry.used) { // no cycle, can just use the returned read object return refEntry.target = targetProperties // replace the placeholder with the real one } else { // there is a cycle, so we have to assign properties to original target Object.assign(target, targetProperties); } // copy over map/set entries if we're able to if (target instanceof Map) for (let [k, v] of targetProperties.entries()) target.set(k, v); if (target instanceof Set) for (let i of Array.from(targetProperties)) target.add(i); return target }; currentExtensions[0x70] = (data) => { // pointer extension (for structured clones) if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled') let id = dataView.getUint32(position$1 - 4); let refEntry = referenceMap.get(id); refEntry.used = true; return refEntry.target }; currentExtensions[0x73] = () => new Set(read()); const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array'); let glbl = typeof globalThis === 'object' ? globalThis : window; currentExtensions[0x74] = (data) => { let typeCode = data[0]; // we always have to slice to get a new ArrayBuffer that is aligned let buffer = Uint8Array.prototype.slice.call(data, 1).buffer; let typedArrayName = typedArrays[typeCode]; if (!typedArrayName) { if (typeCode === 16) return buffer if (typeCode === 17) return new DataView(buffer) throw new Error('Could not find typed array for code ' + typeCode) } return new glbl[typedArrayName](buffer) }; currentExtensions[0x78] = () => { let data = read(); return new RegExp(data[0], data[1]) }; const TEMP_BUNDLE = []; currentExtensions[0x62] = (data) => { let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]; let dataPosition = position$1; position$1 += dataSize - data.length; bundledStrings$1 = TEMP_BUNDLE; bundledStrings$1 = [readOnlyJSString(), readOnlyJSString()]; bundledStrings$1.position0 = 0; bundledStrings$1.position1 = 0; bundledStrings$1.postBundlePosition = position$1; position$1 = dataPosition; return read() }; currentExtensions[0xff] = (data) => { // 32-bit date extension if (data.length == 4) return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000) else if (data.length == 8) return new Date( ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 + ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000) else if (data.length == 12) return new Date( ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 + (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000) else return new Date('invalid') }; // registration of bulk record definition? // currentExtensions[0x52] = () => function saveState$1(callback) { if (onSaveState) onSaveState(); let savedSrcEnd = srcEnd; let savedPosition = position$1; let savedStringPosition = stringPosition; let savedSrcStringStart = srcStringStart; let savedSrcStringEnd = srcStringEnd; let savedSrcString = srcString; let savedStrings = strings; let savedReferenceMap = referenceMap; let savedBundledStrings = bundledStrings$1; // TODO: We may need to revisit this if we do more external calls to user code (since it could be slow) let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed let savedStructures = currentStructures; let savedStructuresContents = currentStructures.slice(0, currentStructures.length); let savedPackr = currentUnpackr; let savedSequentialMode = sequentialMode; let value = callback(); srcEnd = savedSrcEnd; position$1 = savedPosition; stringPosition = savedStringPosition; srcStringStart = savedSrcStringStart; srcStringEnd = savedSrcStringEnd; srcString = savedSrcString; strings = savedStrings; referenceMap = savedReferenceMap; bundledStrings$1 = savedBundledStrings; src = savedSrc; sequentialMode = savedSequentialMode; currentStructures = savedStructures; currentStructures.splice(0, currentStructures.length, ...savedStructuresContents); currentUnpackr = savedPackr; dataView = new DataView(src.buffer, src.byteOffset, src.byteLength); return value } function clearSource() { src = null; referenceMap = null; currentStructures = null; } function addExtension$1(extension) { if (extension.unpack) currentExtensions[extension.type] = extension.unpack; else currentExtensions[extension.type] = extension; } const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding for (let i = 0; i < 256; i++) { mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103)); } const Decoder = Unpackr; var defaultUnpackr = new Unpackr({ useRecords: false }); const unpack = defaultUnpackr.unpack; const unpackMultiple = defaultUnpackr.unpackMultiple; const decode = defaultUnpackr.unpack; const FLOAT32_OPTIONS = { NEVER: 0, ALWAYS: 1, DECIMAL_ROUND: 3, DECIMAL_FIT: 4 }; let f32Array = new Float32Array(1); let u8Array = new Uint8Array(f32Array.buffer, 0, 4); function roundFloat32(float32Number) { f32Array[0] = float32Number; let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)]; return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier } function setReadStruct(updatedReadStruct, loadedStructs, saveState) { readStruct$1 = updatedReadStruct; onLoadedStructures$1 = loadedStructs; onSaveState = saveState; } let textEncoder$1; try { textEncoder$1 = new TextEncoder(); } catch (error) {} let extensions, extensionClasses; const hasNodeBuffer$1 = typeof Buffer !== 'undefined'; const ByteArrayAllocate = hasNodeBuffer$1 ? function(length) { return Buffer.allocUnsafeSlow(length) } : Uint8Array; const ByteArray = hasNodeBuffer$1 ? Buffer : Uint8Array; const MAX_BUFFER_SIZE = hasNodeBuffer$1 ? 0x100000000 : 0x7fd00000; let target, keysTarget; let targetView; let position = 0; let safeEnd; let bundledStrings = null; let writeStructSlots; const MAX_BUNDLE_SIZE = 0x5500; // maximum characters such that the encoded bytes fits in 16 bits. const hasNonLatin = /[\u0080-\uFFFF]/; const RECORD_SYMBOL = Symbol('record-id'); class Packr extends Unpackr { constructor(options) { super(options); this.offset = 0; let start; let hasSharedUpdate; let structures; let referenceMap; let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) { return target.utf8Write(string, position, target.byteLength - position) } : (textEncoder$1 && textEncoder$1.encodeInto) ? function(string, position) { return textEncoder$1.encodeInto(string, target.subarray(position)).written } : false; let packr = this; if (!options) options = {}; let isSequential = options && options.sequential; let hasSharedStructures = options.structures || options.saveStructures; let maxSharedStructures = options.maxSharedStructures; if (maxSharedStructures == null) maxSharedStructures = hasSharedStructures ? 32 : 0; if (maxSharedStructures > 8160) throw new Error('Maximum maxSharedStructure is 8160') if (options.structuredClone && options.moreTypes == undefined) { this.moreTypes = true; } let maxOwnStructures = options.maxOwnStructures; if (maxOwnStructures == null) maxOwnStructures = hasSharedStructures ? 32 : 64; if (!this.structures && options.useRecords != false) this.structures = []; // two byte record ids for shared structures let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64); let sharedLimitId = maxSharedStructures + 0x40; let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40; if (maxStructureId > 8256) { throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192') } let recordIdsToRemove = []; let transitionsCount = 0; let serializationsSinceTransitionRebuild = 0; this.pack = this.encode = function(value, encodeOptions) { if (!target) { target = new ByteArrayAllocate(8192); targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, 8192)); position = 0; } safeEnd = target.length - 10; if (safeEnd - position < 0x800) { // don't start too close to the end, target = new ByteArrayAllocate(target.length); targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length)); safeEnd = target.length - 10; position = 0; } else position = (position + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster start = position; if (encodeOptions & RESERVE_START_SPACE) position += (encodeOptions & 0xff); referenceMap = packr.structuredClone ? new Map() : null; if (packr.bundleStrings && typeof value !== 'string') { bundledStrings = []; bundledStrings.size = Infinity; // force a new bundle start on first string } else bundledStrings = null; structures = packr.structures; if (structures) { if (structures.uninitialized) structures = packr._mergeStructures(packr.getStructures()); let sharedLength = structures.sharedLength || 0; if (sharedLength > maxSharedStructures) { //if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength) } if (!structures.transitions) { // rebuild our structure transitions structures.transitions = Object.create(null); for (let i = 0; i < sharedLength; i++) { let keys = structures[i]; if (!keys) continue let nextTransition, transition = structures.transitions; for (let j = 0, l = keys.length; j < l; j++) { let key = keys[j]; nextTransition = transition[key]; if (!nextTransition) { nextTransition = transition[key] = Object.create(null); } transition = nextTransition; } transition[RECORD_SYMBOL] = i + 0x40; } this.lastNamedStructuresLength = sharedLength; } if (!isSequential) { structures.nextId = sharedLength + 0x40; } } if (hasSharedUpdate) hasSharedUpdate = false; let encodingError; try { if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object) writeStruct(value); else pack(value); let lastBundle = bundledStrings; if (bundledStrings) writeBundles(start, pack, 0); if (referenceMap && referenceMap.idsToInsert) { let idsToInsert = referenceMap.idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1); let i = idsToInsert.length; let incrementPosition = -1; while (lastBundle && i > 0) { let insertionPoint = idsToInsert[--i].offset + start; if (insertionPoint < (lastBundle.stringsPosition + start) && incrementPosition === -1) incrementPosition = 0; if (insertionPoint > (lastBundle.position + start)) { if (incrementPosition >= 0) incrementPosition += 6; } else { if (incrementPosition >= 0) { // update the bundle reference now targetView.setUint32(lastBundle.position + start, targetView.getUint32(lastBundle.position + start) + incrementPosition); incrementPosition = -1; // reset } lastBundle = lastBundle.previous; i++; } } if (incrementPosition >= 0 && lastBundle) { // update the bundle reference now targetView.setUint32(lastBundle.position + start, targetView.getUint32(lastBundle.position + start) + incrementPosition); } position += idsToInsert.length * 6; if (position > safeEnd) makeRoom(position); packr.offset = position; let serialized = insertIds(target.subarray(start, position), idsToInsert); referenceMap = null; return serialized } packr.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially if (encodeOptions & REUSE_BUFFER_MODE) { target.start = start; target.end = position; return target } return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now } catch(error) { encodingError = error; throw error; } finally { if (structures) { resetStructures(); if (hasSharedUpdate && packr.saveStructures) { let sharedLength = structures.sharedLength || 0; // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save let returnBuffer = target.subarray(start, position); let newSharedData = prepareStructures$1(structures, packr); if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) { // get updated structures and try again if the update failed return packr.pack(value, encodeOptions) } packr.lastNamedStructuresLength = sharedLength; // don't keep large buffers around if (target.length > 0x40000000) target = null; return returnBuffer } } } // don't keep large buffers around, they take too much memory and cause problems (limit at 1GB) if (target.length > 0x40000000) target = null; if (encodeOptions & RESET_BUFFER_MODE) position = start; } }; const resetStructures = () => { if (serializationsSinceTransitionRebuild < 10) serializationsSinceTransitionRebuild++; let sharedLength = structures.sharedLength || 0; if (structures.length > sharedLength && !isSequential) structures.length = sharedLength; if (transitionsCount > 10000) { // force a rebuild occasionally after a lot of transitions so it can get cleaned up structures.transitions = null; serializationsSinceTransitionRebuild = 0; transitionsCount = 0; if (recordIdsToRemove.length > 0) recordIdsToRemove = []; } else if (recordIdsToRemove.length > 0 && !isSequential) { for (let i = 0, l = recordIdsToRemove.length; i < l; i++) { recordIdsToRemove[i][RECORD_SYMBOL] = 0; } recordIdsToRemove = []; } }; const packArray = (value) => { var length = value.length; if (length < 0x10) { target[position++] = 0x90 | length; } else if (length < 0x10000) { target[position++] = 0xdc; target[position++] = length >> 8; target[position++] = length & 0xff; } else { target[position++] = 0xdd; targetView.setUint32(position, length); position += 4; } for (let i = 0; i < length; i++) { pack(value[i]); } }; const pack = (value) => { if (position > safeEnd) target = makeRoom(position); var type = typeof value; var length; if (type === 'string') { let strLength = value.length; if (bundledStrings && strLength >= 4 && strLength < 0x1000) { if ((bundledStrings.size += strLength) > MAX_BUNDLE_SIZE) { let extStart; let maxBytes = (bundledStrings[0] ? bundledStrings[0].length * 3 + bundledStrings[1].length : 0) + 10; if (position + maxBytes > safeEnd) target = makeRoom(position + maxBytes); let lastBundle; if (bundledStrings.position) { // here we use the 0x62 extension to write the last bundle and reserve space for the reference pointer to the next/current bundle lastBundle = bundledStrings; target[position] = 0xc8; // ext 16 position += 3; // reserve for the writing bundle size target[position++] = 0x62; // 'b' extStart = position - start; position += 4; // reserve for writing bundle reference writeBundles(start, pack, 0); // write the last bundles targetView.setUint16(extStart + start - 3, position - start - extStart); } else { // here we use the 0x62 extension just to reserve the space for the reference pointer to the bundle (will be updated once the bundle is written) target[position++] = 0xd6; // fixext 4 target[position++] = 0x62; // 'b' extStart = position - start; position += 4; // reserve for writing bundle reference } bundledStrings = ['', '']; // create new ones bundledStrings.previous = lastBundle; bundledStrings.size = 0; bundledStrings.position = extStart; } let twoByte = hasNonLatin.test(value); bundledStrings[twoByte ? 0 : 1] += value; target[position++] = 0xc1; pack(twoByte ? -strLength : strLength); return } let headerSize; // first we estimate the header size, so we can write to the correct location if (strLength < 0x20) { headerSize = 1; } else if (strLength < 0x100) { headerSize = 2; } else if (strLength < 0x10000) { headerSize = 3; } else { headerSize = 5; } let maxBytes = strLength * 3; if (position + maxBytes > safeEnd) target = makeRoom(position + maxBytes); if (strLength < 0x40 || !encodeUtf8) { let i, c1, c2, strPosition = position + headerSize; for (i = 0; i < strLength; i++) { c1 = value.charCodeAt(i); if (c1 < 0x80) { target[strPosition++] = c1; } else if (c1 < 0x800) { target[strPosition++] = c1 >> 6 | 0xc0; target[strPosition++] = c1 & 0x3f | 0x80; } else if ( (c1 & 0xfc00) === 0xd800 && ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00 ) { c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff); i++; target[strPosition++] = c1 >> 18 | 0xf0; target[strPosition++] = c1 >> 12 & 0x3f | 0x80; target[strPosition++] = c1 >> 6 & 0x3f | 0x80; target[strPosition++] = c1 & 0x3f | 0x80; } else { target[strPosition++] = c1