@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
228 lines (225 loc) • 6.6 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 3.0.0
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
'use strict';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class WireError extends Error {
static {
__name(this, "WireError");
}
name = "WireError";
}
const WIRE_VARINT = 0;
const WIRE_BYTES = 2;
const WIRE_FIXED32 = 5;
const WIRE_START_GROUP = 3;
const WIRE_END_GROUP = 4;
const MAX_GROUP_DEPTH = 64;
function tag(fieldNumber, wireType) {
return fieldNumber << 3 | wireType;
}
__name(tag, "tag");
class Writer {
static {
__name(this, "Writer");
}
// A growing `Uint8Array`, not a `number[]`. The array version was measurably
// superlinear: each of the four nesting levels copied its child byte by byte
// through `push`, and `Uint8Array.from` then copied the lot again — 106 ms for
// a 1000-message batch against protobuf.js's 3.4 ms, and 267 ms for a 2 MB
// body. Irrelevant for the single-message batches this client usually sends,
// and a main-thread stall for the ones it occasionally does.
#buffer = new Uint8Array(64);
#length = 0;
get length() {
return this.#length;
}
#reserve(extra) {
const needed = this.#length + extra;
if (needed <= this.#buffer.length) {
return;
}
let size = this.#buffer.length * 2;
while (size < needed) {
size *= 2;
}
const grown = new Uint8Array(size);
grown.set(this.#buffer.subarray(0, this.#length));
this.#buffer = grown;
}
#push(byte) {
this.#reserve(1);
this.#buffer[this.#length++] = byte;
}
varint(value) {
let rest = value >>> 0;
while (rest > 127) {
this.#push(rest & 127 | 128);
rest >>>= 7;
}
this.#push(rest);
return this;
}
fixed32(value) {
const v = value >>> 0;
this.#reserve(4);
this.#buffer[this.#length++] = v & 255;
this.#buffer[this.#length++] = v >>> 8 & 255;
this.#buffer[this.#length++] = v >>> 16 & 255;
this.#buffer[this.#length++] = v >>> 24 & 255;
return this;
}
bytes(value) {
this.varint(value.length);
this.#reserve(value.length);
this.#buffer.set(value, this.#length);
this.#length += value.length;
return this;
}
string(value) {
return this.bytes(new TextEncoder().encode(value));
}
finish() {
return this.#buffer.slice(0, this.#length);
}
}
class Reader {
static {
__name(this, "Reader");
}
#view;
#pos = 0;
constructor(view) {
this.#view = view;
}
get done() {
return this.#pos >= this.#view.length;
}
/**
* A varint of up to ten bytes — protobuf's full legal width.
*
* The ceiling was 35 bits, which made this codec LESS forward-compatible than
* the library it replaces: an unknown `uint64` field above 2^35 threw, and
* because `extractProtobufMessages` swallows the throw, the whole frame was
* dropped where protobuf.js would have skipped the field and carried on. The
* symptom would have been "connected, no events".
*
* Above 2^53 the value is no longer exact. That is acceptable only because
* every caller either masks it (`uint32`) or discards it (`skip`); nothing in
* this schema is a 64-bit field.
*/
varint() {
let result = 0;
let shift = 0;
for (; ; ) {
if (this.done) {
throw new WireError("pull protobuf: truncated varint");
}
const byte = this.#view[this.#pos++];
result += (byte & 127) * 2 ** shift;
if ((byte & 128) === 0) {
return result;
}
shift += 7;
if (shift >= 70) {
throw new WireError("pull protobuf: varint longer than ten bytes");
}
}
}
/**
* A `uint32` field, truncated the way protobuf.js truncates it.
*
* Without the mask a wire value of 2^32 read back as 4294967296 where the
* library gives 0 — the two codecs disagreeing on a well-formed frame.
*/
uint32() {
return this.varint() >>> 0;
}
fixed32() {
if (this.#pos + 4 > this.#view.length) {
throw new WireError("pull protobuf: truncated fixed32");
}
const v = this.#view[this.#pos] | this.#view[this.#pos + 1] << 8 | this.#view[this.#pos + 2] << 16 | this.#view[this.#pos + 3] << 24;
this.#pos += 4;
return v >>> 0;
}
bytes() {
const length = this.varint();
if (this.#pos + length > this.#view.length) {
throw new WireError("pull protobuf: length-delimited field runs past the end");
}
const out = this.#view.subarray(this.#pos, this.#pos + length);
this.#pos += length;
return out;
}
string() {
return new TextDecoder().decode(this.bytes());
}
/**
* Skip a field this codec does not model — the statistics branches, and
* anything a future server adds. Unknown fields are ordinary protobuf, not an
* error: the vendored library ignored them silently and so must this.
*
* The throws below are not "give up". `readFields` catches them and stops
* reading that message, so a damaged tail costs the fields after it and
* nothing else. Throwing is how this reader says "I cannot go further", not
* how it reports a failure to its caller — and it is always a `WireError`,
* which is the only thing `readFields` catches.
*/
skip(wireType, depth = 0) {
switch (wireType) {
case WIRE_VARINT: {
this.varint();
break;
}
case WIRE_BYTES: {
this.bytes();
break;
}
case WIRE_FIXED32: {
this.fixed32();
break;
}
case 1: {
if (this.#pos + 8 > this.#view.length) {
throw new WireError("pull protobuf: truncated 64-bit field");
}
this.#pos += 8;
break;
}
case WIRE_START_GROUP: {
this.#skipGroup(depth);
break;
}
default: {
throw new WireError(`pull protobuf: unsupported wire type ${wireType}`);
}
}
}
#skipGroup(depth) {
if (depth >= MAX_GROUP_DEPTH) {
throw new WireError("pull protobuf: groups nested too deeply");
}
for (; ; ) {
const wireType = this.varint() & 7;
if (wireType === WIRE_END_GROUP) {
return;
}
this.skip(wireType, depth + 1);
}
}
}
exports.Reader = Reader;
exports.WIRE_BYTES = WIRE_BYTES;
exports.WIRE_FIXED32 = WIRE_FIXED32;
exports.WIRE_VARINT = WIRE_VARINT;
exports.WireError = WireError;
exports.Writer = Writer;
exports.tag = tag;
//# sourceMappingURL=wire.cjs.map