Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@bnaya/objectbuffer

Package Overview
Dependencies
Maintainers
1
Versions
122
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bnaya/objectbuffer - npm Package Compare versions

Comparing version 0.1.4 to 0.2.0

dist/internal/api.d.ts

6

dist/index.d.ts

@@ -1,4 +0,4 @@

export declare function createObjectBuffer<T = any>(textDecoder: any, textEncoder: any, size: number, initialValue: T): T;
export declare function getUnderlyingArrayBuffer(objectBuffer: any): ArrayBuffer;
export declare function createObjectBufferFromArrayBuffer<T = any>(textDecoder: any, textEncoder: any, arrayBuffer: ArrayBuffer, shouldInitializeArrayBuffer?: boolean): T;
export * from "./internal/api";
import * as locks from "./internal/locks";
export { locks };
//# sourceMappingURL=index.d.ts.map

@@ -1,20 +0,3 @@

import { initializeArrayBuffer } from "./internal/store";
import { objectSaver } from "./internal/objectSaver";
import { createObjectWrapper, GET_UNDERLYING_ARRAY_BUFFER_SYMBOL } from "./internal/objectWrapper";
export function createObjectBuffer(textDecoder, textEncoder, size, initialValue) {
const arrayBuffer = new ArrayBuffer(size);
const dataView = initializeArrayBuffer(arrayBuffer);
const {
start
} = objectSaver(textEncoder, dataView, initialValue);
dataView.setUint32(8, start);
return createObjectWrapper(dataView, start, textDecoder, textEncoder, true);
}
export function getUnderlyingArrayBuffer(objectBuffer) {
return objectBuffer[GET_UNDERLYING_ARRAY_BUFFER_SYMBOL];
}
export function createObjectBufferFromArrayBuffer(textDecoder, textEncoder, arrayBuffer, // set to true if the give array buffer is not one from `getUnderlyingArrayBuffer`
shouldInitializeArrayBuffer = false) {
const dataView = shouldInitializeArrayBuffer ? initializeArrayBuffer(arrayBuffer) : new DataView(arrayBuffer);
return createObjectWrapper(dataView, dataView.getUint32(8), textDecoder, textEncoder);
}
export * from "./internal/api";
import * as locks from "./internal/locks";
export { locks };
export declare enum ENTRY_TYPE {
NULL = 0,
UNDEFINED = 1,
UNDEFINED = 0,
NULL = 1,
NUMBER = 2,

@@ -18,3 +18,3 @@ BIGINT = 3,

export declare const PRIMITIVE_TYPES: readonly [ENTRY_TYPE.NULL, ENTRY_TYPE.UNDEFINED, ENTRY_TYPE.NUMBER, ENTRY_TYPE.BIGINT, ENTRY_TYPE.UBIGINT, ENTRY_TYPE.BOOLEAN, ENTRY_TYPE.STRING];
export declare const isPrimitiveEntryType: (v: unknown) => v is ENTRY_TYPE.NULL | ENTRY_TYPE.UNDEFINED | ENTRY_TYPE.NUMBER | ENTRY_TYPE.BIGINT | ENTRY_TYPE.UBIGINT | ENTRY_TYPE.STRING | ENTRY_TYPE.BOOLEAN;
export declare const isPrimitiveEntryType: (v: unknown) => v is ENTRY_TYPE.UNDEFINED | ENTRY_TYPE.NULL | ENTRY_TYPE.NUMBER | ENTRY_TYPE.BIGINT | ENTRY_TYPE.UBIGINT | ENTRY_TYPE.STRING | ENTRY_TYPE.BOOLEAN;
//# sourceMappingURL=entry-types.d.ts.map

@@ -5,4 +5,4 @@ import { createKnownTypeGuard } from "./utils";

(function (ENTRY_TYPE) {
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 0] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 1] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 0] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 1] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["NUMBER"] = 2] = "NUMBER";

@@ -9,0 +9,0 @@ ENTRY_TYPE[ENTRY_TYPE["BIGINT"] = 3] = "BIGINT";

import { ENTRY_TYPE } from "./entry-types";
export declare type primitive = string | number | bigint | boolean | undefined | null;
export declare type Entry = NullEntry | NullUndefined | BooleanEntry | StringEntry | NumberEntry | BigIntEntry | UBigIntEntry | ObjectEntry | ObjectPropEntry | ArrayEntry | ArrayItemEntry;
export declare type Entry = NullEntry | NullUndefined | BooleanEntry | StringEntry | NumberEntry | BigIntEntry | UBigIntEntry | ObjectEntry | ObjectPropEntry | ArrayEntry;
export interface NullEntry {

@@ -57,10 +57,5 @@ type: ENTRY_TYPE.NULL;

value: number;
length: number;
allocatedLength: number;
}
export interface ArrayItemEntry {
type: ENTRY_TYPE.ARRAY_ITEM;
value: {
value: number;
next: number;
};
}
//# sourceMappingURL=interfaces.d.ts.map

@@ -1,2 +0,2 @@

export declare function objectSaver(textEncoder: any, dataView: DataView, objectToSave: any): {
export declare function objectSaver(textEncoder: any, dataView: DataView, arrayAdditionalAllocation: number, objectToSave: any): {
start: number;

@@ -3,0 +3,0 @@ length: number;

@@ -6,3 +6,3 @@ // import { isPrimitive, primitiveValueToEntry } from "./utils";

export function objectSaver(textEncoder, dataView, objectToSave) {
export function objectSaver(textEncoder, dataView, arrayAdditionalAllocation, objectToSave) {
let totalWrittenBytes = 0; // const writtenLength = 0;

@@ -14,3 +14,3 @@

for (const [key, value] of objectEntries) {
const rOfValue = saveValue(textEncoder, dataView, value);
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
const objectPropEntry = {

@@ -17,0 +17,0 @@ type: ENTRY_TYPE.OBJECT_PROP,

@@ -8,3 +8,4 @@ export declare const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL: unique symbol;

private isTopLevel;
constructor(dataView: DataView, entryPointer: number, textDecoder: any, textEncoder: any, isTopLevel: boolean);
private arrayAdditionalAllocation;
constructor(dataView: DataView, entryPointer: number, textDecoder: any, textEncoder: any, isTopLevel: boolean, arrayAdditionalAllocation: number);
getUnderlyingArrayBuffer(): ArrayBuffer;

@@ -24,5 +25,5 @@ get(target: {}, p: PropertyKey): any;

setPrototypeOf(): boolean;
private readonly entry;
private get entry();
}
export declare function createObjectWrapper<T = any>(dataView: DataView, entryPointer: number, textDecoder: any, textEncoder: any, isTopLevel?: boolean): T;
export declare function createObjectWrapper<T = any>(dataView: DataView, entryPointer: number, textDecoder: any, textEncoder: any, isTopLevel?: boolean, arrayAdditionalAllocation?: number): T;
//# sourceMappingURL=objectWrapper.d.ts.map
import { readEntry, writeEntry, appendEntry } from "./store";
import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { ENTRY_TYPE } from "./entry-types";
import { findObjectPropertyEntry, getObjectPropertiesEntries, deleteObjectPropertyEntryByKey, findLastObjectPropertyEntry } from "./objectWrapperHelpers";
import { saveValue } from "./saveValue";
import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
export const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL = Symbol("GET_UNDERLYING_ARRAY_BUFFER_SYMBOL");
export class ObjectWrapper {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel) {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation) {
this.dataView = dataView;

@@ -13,2 +14,3 @@ this.entryPointer = entryPointer;

this.isTopLevel = isTopLevel;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
}

@@ -44,20 +46,3 @@

const [valueEntry] = readEntry(this.dataView, foundEntry[1].value.value, this.textDecoder);
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(this.dataView, foundEntry[1].value.value, this.textDecoder, this.textEncoder);
}
throw new Error("unsupported yet");
return entryToFinalJavaScriptValue(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, valueEntry, foundEntry[1].value.value);
}

@@ -102,3 +87,3 @@

start: newValueEntryPointer
} = saveValue(this.textEncoder, this.dataView, value);
} = saveValue(this.textEncoder, this.dataView, this.arrayAdditionalAllocation, value);
const foundPropEntry = findObjectPropertyEntry(this.dataView, this.entryPointer, p, this.textDecoder); // new prop

@@ -180,6 +165,6 @@

}
export function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false) {
export function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false, arrayAdditionalAllocation = 50) {
return new Proxy({
bla: 1
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel));
objectBufferWrapper: "objectBufferWrapper"
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation));
}

@@ -1,2 +0,2 @@

export declare function saveValue(textEncoder: any, dataView: DataView, value: any): {
export declare function saveValue(textEncoder: any, dataView: DataView, arrayAdditionalAllocation: number, value: any): {
start: number;

@@ -3,0 +3,0 @@ length: number;

import { primitiveValueToEntry, isPrimitive } from "./utils";
import { appendEntry } from "./store";
import { objectSaver } from "./objectSaver";
export function saveValue(textEncoder, dataView, value) {
import { arraySaver } from "./arraySaver";
export function saveValue(textEncoder, dataView, arrayAdditionalAllocation, value) {
let totalWrittenBytes = 0;

@@ -16,2 +17,9 @@ let valuePointer = 0;

totalWrittenBytes += length;
} else if (Array.isArray(value)) {
const {
start,
length
} = arraySaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;
totalWrittenBytes += length;
} else if (typeof value === "object") {

@@ -21,3 +29,3 @@ const {

length
} = objectSaver(textEncoder, dataView, value);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;

@@ -24,0 +32,0 @@ totalWrittenBytes += length;

@@ -26,2 +26,3 @@ import { Entry } from "./interfaces";

textDecoder: any): [Entry, number];
export declare function reserveMemory(dataView: DataView, length: number): number;
//# sourceMappingURL=store.d.ts.map
import { ENTRY_TYPE } from "./entry-types";
import { arrayBufferCopyTo } from "./utils";
const DEFAULT_ARRAY_BUFFER_SIZE = 10 ^ 6;

@@ -11,7 +12,9 @@ export class Store {

export function initializeArrayBuffer(arrayBuffer) {
const dataView = new DataView(arrayBuffer); // End of data pointer
const dataView = new DataView(arrayBuffer); // global lock
dataView.setUint32(0, 16); // first entry pointer
dataView.setInt32(0, 0); // End of data pointer / first free byte
dataView.setUint32(8, 16);
dataView.setUint32(8, 24); // first entry pointer
dataView.setUint32(16, 24);
return dataView;

@@ -93,3 +96,14 @@ }

case ENTRY_TYPE.ARRAY:
dataView.setUint32(cursor, entry.value);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.length);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.allocatedLength);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -106,5 +120,5 @@ }

// End of data pointer
const firstFreeByte = dataView.getUint32(0);
const firstFreeByte = dataView.getUint32(8);
const written = writeEntry(dataView, firstFreeByte, entry, textEncoder);
dataView.setUint32(0, firstFreeByte + written);
dataView.setUint32(8, firstFreeByte + written);
return {

@@ -148,6 +162,9 @@ start: firstFreeByte,

const stringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT;
entry.value = textDecoder.decode( // this wrapping is needed until:
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + stringLength)));
// eslint-disable-next-line no-case-declarations
const tempAB = new ArrayBuffer(stringLength);
arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0);
entry.value = textDecoder.decode(tempAB);
cursor += stringLength;

@@ -174,8 +191,11 @@ break;

const keyStringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT; // eslint-disable-next-line no-case-declarations
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB2 = new ArrayBuffer(keyStringLength);
arrayBufferCopyTo(dataView.buffer, cursor, keyStringLength, tempAB2, 0); // eslint-disable-next-line no-case-declarations
const objectPropsValue = {
key: textDecoder.decode( // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + keyStringLength))),
key: textDecoder.decode(tempAB2),
value: dataView.getUint32(cursor + keyStringLength),

@@ -188,2 +208,11 @@ next: dataView.getUint32(cursor + keyStringLength + Uint32Array.BYTES_PER_ELEMENT)

case ENTRY_TYPE.ARRAY:
entry.value = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:

@@ -194,2 +223,7 @@ throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");

return [entry, cursor - startingCursor];
}
export function reserveMemory(dataView, length) {
const firstFreeByte = dataView.getUint32(8);
dataView.setUint32(8, firstFreeByte + length);
return firstFreeByte;
}

@@ -6,2 +6,3 @@ import { primitive, Entry } from "./interfaces";

export declare function invariant(condition: boolean, message: string): void;
export declare function arrayBufferCopyTo(origin: ArrayBuffer, startByte: number, length: number, target: ArrayBuffer, toTargetByte: number): void;
//# sourceMappingURL=utils.d.ts.map

@@ -66,2 +66,10 @@ import { ENTRY_TYPE } from "./entry-types";

}
}
export function arrayBufferCopyTo(origin, startByte, length, target, toTargetByte) {
const copyFrom = new Uint8Array(origin);
const copyTo = new Uint8Array(target);
for (let i = 0; i < length; i += 1) {
copyTo[toTargetByte + i] = copyFrom[startByte + i];
}
}

@@ -1,4 +0,4 @@

export declare function createObjectBuffer<T = any>(textDecoder: any, textEncoder: any, size: number, initialValue: T): T;
export declare function getUnderlyingArrayBuffer(objectBuffer: any): ArrayBuffer;
export declare function createObjectBufferFromArrayBuffer<T = any>(textDecoder: any, textEncoder: any, arrayBuffer: ArrayBuffer, shouldInitializeArrayBuffer?: boolean): T;
export * from "./internal/api";
import * as locks from "./internal/locks";
export { locks };
//# sourceMappingURL=index.d.ts.map

@@ -70,8 +70,16 @@ 'use strict';

}
function arrayBufferCopyTo(origin, startByte, length, target, toTargetByte) {
const copyFrom = new Uint8Array(origin);
const copyTo = new Uint8Array(target);
for (let i = 0; i < length; i += 1) {
copyTo[toTargetByte + i] = copyFrom[startByte + i];
}
}
let ENTRY_TYPE;
(function (ENTRY_TYPE) {
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 0] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 1] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 0] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 1] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["NUMBER"] = 2] = "NUMBER";

@@ -95,7 +103,9 @@ ENTRY_TYPE[ENTRY_TYPE["BIGINT"] = 3] = "BIGINT";

function initializeArrayBuffer(arrayBuffer) {
const dataView = new DataView(arrayBuffer); // End of data pointer
const dataView = new DataView(arrayBuffer); // global lock
dataView.setUint32(0, 16); // first entry pointer
dataView.setInt32(0, 0); // End of data pointer / first free byte
dataView.setUint32(8, 16);
dataView.setUint32(8, 24); // first entry pointer
dataView.setUint32(16, 24);
return dataView;

@@ -177,3 +187,14 @@ }

case ENTRY_TYPE.ARRAY:
dataView.setUint32(cursor, entry.value);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.length);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.allocatedLength);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -190,5 +211,5 @@ }

// End of data pointer
const firstFreeByte = dataView.getUint32(0);
const firstFreeByte = dataView.getUint32(8);
const written = writeEntry(dataView, firstFreeByte, entry, textEncoder);
dataView.setUint32(0, firstFreeByte + written);
dataView.setUint32(8, firstFreeByte + written);
return {

@@ -232,6 +253,9 @@ start: firstFreeByte,

const stringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT;
entry.value = textDecoder.decode( // this wrapping is needed until:
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + stringLength)));
// eslint-disable-next-line no-case-declarations
const tempAB = new ArrayBuffer(stringLength);
arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0);
entry.value = textDecoder.decode(tempAB);
cursor += stringLength;

@@ -258,8 +282,11 @@ break;

const keyStringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT; // eslint-disable-next-line no-case-declarations
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB2 = new ArrayBuffer(keyStringLength);
arrayBufferCopyTo(dataView.buffer, cursor, keyStringLength, tempAB2, 0); // eslint-disable-next-line no-case-declarations
const objectPropsValue = {
key: textDecoder.decode( // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + keyStringLength))),
key: textDecoder.decode(tempAB2),
value: dataView.getUint32(cursor + keyStringLength),

@@ -272,2 +299,11 @@ next: dataView.getUint32(cursor + keyStringLength + Uint32Array.BYTES_PER_ELEMENT)

case ENTRY_TYPE.ARRAY:
entry.value = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:

@@ -279,5 +315,36 @@ throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");

}
function reserveMemory(dataView, length) {
const firstFreeByte = dataView.getUint32(8);
dataView.setUint32(8, firstFreeByte + length);
return firstFreeByte;
}
function saveValue(textEncoder, dataView, value) {
function arraySaver(textEncoder, dataView, arrayAdditionalAllocation, arrayToSave) {
let totalWrittenBytes = 0;
let memoryForPointersCursor = reserveMemory(dataView, (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT);
totalWrittenBytes += (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT;
const arrayStartEntry = {
type: ENTRY_TYPE.ARRAY,
value: memoryForPointersCursor,
allocatedLength: arrayToSave.length + arrayAdditionalAllocation,
length: arrayToSave.length
};
for (const item of arrayToSave) {
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, item);
dataView.setUint32(memoryForPointersCursor, rOfValue.start);
memoryForPointersCursor += Uint32Array.BYTES_PER_ELEMENT;
totalWrittenBytes += rOfValue.length;
}
const arrayEntryAppendResult = appendEntry(dataView, arrayStartEntry, textEncoder);
totalWrittenBytes += arrayEntryAppendResult.length;
return {
start: arrayEntryAppendResult.start,
length: totalWrittenBytes
};
}
function saveValue(textEncoder, dataView, arrayAdditionalAllocation, value) {
let totalWrittenBytes = 0;
let valuePointer = 0;

@@ -293,2 +360,9 @@

totalWrittenBytes += length;
} else if (Array.isArray(value)) {
const {
start,
length
} = arraySaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;
totalWrittenBytes += length;
} else if (typeof value === "object") {

@@ -298,3 +372,3 @@ const {

length
} = objectSaver(textEncoder, dataView, value);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;

@@ -314,3 +388,3 @@ totalWrittenBytes += length;

function objectSaver(textEncoder, dataView, objectToSave) {
function objectSaver(textEncoder, dataView, arrayAdditionalAllocation, objectToSave) {
let totalWrittenBytes = 0; // const writtenLength = 0;

@@ -322,3 +396,3 @@

for (const [key, value] of objectEntries) {
const rOfValue = saveValue(textEncoder, dataView, value);
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
const objectPropEntry = {

@@ -466,5 +540,274 @@ type: ENTRY_TYPE.OBJECT_PROP,

// isolated due to parser changes ts 3.7
// https://github.com/microsoft/TypeScript/pull/32695
// eslint-disable-next-line prettier/prettier
// export function assertNonNull<T>(v: T): asserts v is NonNullable<T> {
// if (v === undefined || v === null) {
// throw new Error("assertNonNull");
// }
// }
/**
* @template T
* @param {T} v
* @return {asserts v is NonNullable<T>}
*/
function assertNonNull(v) {
if (v === undefined || v === null) {
throw new Error("assertNonNull");
}
}
function arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry) {
const [arrayEntry] = readEntry(dataView, pointerToArrayEntry, textDecoder);
return arrayEntry;
}
function arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry); // out of bound
if (indexToGet >= metadata.length) {
return undefined;
}
const pointerToThePointer = metadata.value + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
const pointer = dataView.getUint32(pointerToThePointer);
return {
pointer,
pointerToThePointer
};
}
function getFinalValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToGet) {
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet);
if (pointers === undefined) {
return undefined;
}
const entry = readEntry(dataView, pointers.pointer, textDecoder);
return entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, entry[0], pointers.pointer);
}
function setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, pointerToEntry) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
if (indexToSet >= metadata.length) {
// we need to re-allocate the array in a new and bigger place
if (indexToSet >= metadata.allocatedLength) {
reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, indexToSet + 1 + arrayAdditionalAllocation, indexToSet + 1);
} else {
// no need to re-allocated, just push the length forward
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: indexToSet + 1
}, textEncoder);
}
}
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToSet);
assertNonNull(pointers);
dataView.setUint32(pointers.pointerToThePointer, pointerToEntry);
}
function setValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, value) {
const saveValueResult = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, saveValueResult.start);
}
function reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, newAllocatedLength, newLength) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
const newArrayValueLocation = reserveMemory(dataView, newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT);
for (let memoryToCopyIndex = 0; memoryToCopyIndex < metadata.length; memoryToCopyIndex += 1) {
dataView.setUint32(newArrayValueLocation + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT, dataView.getUint32(metadata.value + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT));
}
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: newArrayValueLocation,
allocatedLength: newAllocatedLength,
length: newLength
}, textEncoder);
}
class ArrayWrapper {
constructor(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
this.dataView = dataView;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
this.entryPointer = entryPointer;
this.textDecoder = textDecoder;
this.textEncoder = textEncoder;
}
get(target, p) {
if (p in this && p !== "constructor") {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return this[p];
}
if (p === "length") {
return arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
}
if (typeof p === "string" || typeof p === "number") {
const asInt = typeof p === "string" ? Number.parseInt(p, 10) : p;
if (Number.isSafeInteger(asInt)) {
return getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, asInt);
}
} // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return target[p];
}
deleteProperty(target, p) {
throw new Error("unsupported");
}
enumerate() {
throw new Error("unsupported");
}
ownKeys() {
const length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
return [...new Array(length).keys()];
}
getOwnPropertyDescriptor() {
return {
configurable: true,
enumerable: true
};
}
has(target, p) {
throw new Error("unsupported");
}
set(target, p, value) {
setValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, Number.parseInt(p, 10), value);
return true;
}
isExtensible() {
return true;
}
preventExtensions() {
throw new Error("unsupported");
}
setPrototypeOf() {
throw new Error("unsupported");
}
*entries() {
let index = 0;
let length = 0;
do {
yield [index, getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index)];
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*keys() {
let index = 0;
let length = 0;
do {
yield index;
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*values() {
let index = 0;
let length = 0;
do {
yield getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index);
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
get [Symbol.iterator]() {
return this.values;
} // in-place methods
shift() {
throw new Error("unsupported");
}
unshift() {
throw new Error("unsupported");
}
pop() {
throw new Error("unsupported");
}
push() {
throw new Error("unsupported");
}
sort() {
throw new Error("unsupported");
}
splice() {
throw new Error("unsupported");
} // // copy methods
// private concat() {
// throw new Error("unsupported");
// }
// private slice() {
// throw new Error("unsupported");
// }
// private map() {
// throw new Error("unsupported");
// }
// private reduce() {
// throw new Error("unsupported");
// }
}
function createArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
return new Proxy([], new ArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder));
}
function entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, valueEntry, pointerToEntry) {
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(dataView, pointerToEntry, textDecoder, textEncoder, false, arrayAdditionalAllocation);
}
if (valueEntry.type === ENTRY_TYPE.ARRAY) {
return createArrayWrapper(dataView, arrayAdditionalAllocation, pointerToEntry, textDecoder, textEncoder);
}
throw new Error("unsupported yet");
}
const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL = Symbol("GET_UNDERLYING_ARRAY_BUFFER_SYMBOL");
class ObjectWrapper {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel) {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation) {
this.dataView = dataView;

@@ -475,2 +818,3 @@ this.entryPointer = entryPointer;

this.isTopLevel = isTopLevel;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
}

@@ -506,20 +850,3 @@

const [valueEntry] = readEntry(this.dataView, foundEntry[1].value.value, this.textDecoder);
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(this.dataView, foundEntry[1].value.value, this.textDecoder, this.textEncoder);
}
throw new Error("unsupported yet");
return entryToFinalJavaScriptValue(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, valueEntry, foundEntry[1].value.value);
}

@@ -564,3 +891,3 @@

start: newValueEntryPointer
} = saveValue(this.textEncoder, this.dataView, value);
} = saveValue(this.textEncoder, this.dataView, this.arrayAdditionalAllocation, value);
const foundPropEntry = findObjectPropertyEntry(this.dataView, this.entryPointer, p, this.textDecoder); // new prop

@@ -642,15 +969,21 @@

}
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false) {
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false, arrayAdditionalAllocation = 50) {
return new Proxy({
bla: 1
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel));
objectBufferWrapper: "objectBufferWrapper"
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation));
}
function createObjectBuffer(textDecoder, textEncoder, size, initialValue) {
const arrayBuffer = new ArrayBuffer(size);
function createObjectBuffer(textDecoder, textEncoder, size, initialValue, {
arrayAdditionalAllocation,
useSharedArrayBuffer
} = {
arrayAdditionalAllocation: 0,
useSharedArrayBuffer: false
}) {
const arrayBuffer = new (useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer)(size);
const dataView = initializeArrayBuffer(arrayBuffer);
const {
start
} = objectSaver(textEncoder, dataView, initialValue);
dataView.setUint32(8, start);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation || 0, initialValue);
dataView.setUint32(16, start);
return createObjectWrapper(dataView, start, textDecoder, textEncoder, true);

@@ -662,9 +995,63 @@ }

function createObjectBufferFromArrayBuffer(textDecoder, textEncoder, arrayBuffer, // set to true if the give array buffer is not one from `getUnderlyingArrayBuffer`
shouldInitializeArrayBuffer = false) {
shouldInitializeArrayBuffer = false, {
arrayAdditionalAllocation
} = {
arrayAdditionalAllocation: 0
}) {
const dataView = shouldInitializeArrayBuffer ? initializeArrayBuffer(arrayBuffer) : new DataView(arrayBuffer);
return createObjectWrapper(dataView, dataView.getUint32(8), textDecoder, textEncoder);
return createObjectWrapper(dataView, dataView.getUint32(16), textDecoder, textEncoder, true, arrayAdditionalAllocation);
}
/* global Atomics */
// I have no idea if its really works as i think it should
function getLock(playerId, sab) {
invariant(playerId > 0, "playerId must be more than 0");
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
return oldValue === 0;
}
function releaseLock(playerId, sab) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, playerId, 0); // we've released a lock. lets tell them about it
if (oldValue === playerId) {
Atomics.notify(int32, 0, +Infinity);
return true;
}
return false;
}
function waitForLock(playerId, sab, timeout) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
if (oldValue === 0) {
return "have-lock";
}
const r = Atomics.wait(int32, 0, oldValue, timeout);
if (r === "not-equal") {
if (Atomics.compareExchange(int32, 0, 0, playerId) === 0) {
return "have-lock";
} else {
return "miss-lock";
}
} else if (r === "timed-out") {
return "timed-out";
} else {
return "no-lock";
}
}
var locks = /*#__PURE__*/Object.freeze({
getLock: getLock,
releaseLock: releaseLock,
waitForLock: waitForLock
});
exports.createObjectBuffer = createObjectBuffer;
exports.createObjectBufferFromArrayBuffer = createObjectBufferFromArrayBuffer;
exports.getUnderlyingArrayBuffer = getUnderlyingArrayBuffer;
exports.locks = locks;

@@ -66,8 +66,16 @@ const primitives = ["string", "number", "bigint", "boolean", "undefined"];

}
function arrayBufferCopyTo(origin, startByte, length, target, toTargetByte) {
const copyFrom = new Uint8Array(origin);
const copyTo = new Uint8Array(target);
for (let i = 0; i < length; i += 1) {
copyTo[toTargetByte + i] = copyFrom[startByte + i];
}
}
let ENTRY_TYPE;
(function (ENTRY_TYPE) {
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 0] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 1] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 0] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 1] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["NUMBER"] = 2] = "NUMBER";

@@ -91,7 +99,9 @@ ENTRY_TYPE[ENTRY_TYPE["BIGINT"] = 3] = "BIGINT";

function initializeArrayBuffer(arrayBuffer) {
const dataView = new DataView(arrayBuffer); // End of data pointer
const dataView = new DataView(arrayBuffer); // global lock
dataView.setUint32(0, 16); // first entry pointer
dataView.setInt32(0, 0); // End of data pointer / first free byte
dataView.setUint32(8, 16);
dataView.setUint32(8, 24); // first entry pointer
dataView.setUint32(16, 24);
return dataView;

@@ -173,3 +183,14 @@ }

case ENTRY_TYPE.ARRAY:
dataView.setUint32(cursor, entry.value);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.length);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.allocatedLength);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -186,5 +207,5 @@ }

// End of data pointer
const firstFreeByte = dataView.getUint32(0);
const firstFreeByte = dataView.getUint32(8);
const written = writeEntry(dataView, firstFreeByte, entry, textEncoder);
dataView.setUint32(0, firstFreeByte + written);
dataView.setUint32(8, firstFreeByte + written);
return {

@@ -228,6 +249,9 @@ start: firstFreeByte,

const stringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT;
entry.value = textDecoder.decode( // this wrapping is needed until:
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + stringLength)));
// eslint-disable-next-line no-case-declarations
const tempAB = new ArrayBuffer(stringLength);
arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0);
entry.value = textDecoder.decode(tempAB);
cursor += stringLength;

@@ -254,8 +278,11 @@ break;

const keyStringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT; // eslint-disable-next-line no-case-declarations
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB2 = new ArrayBuffer(keyStringLength);
arrayBufferCopyTo(dataView.buffer, cursor, keyStringLength, tempAB2, 0); // eslint-disable-next-line no-case-declarations
const objectPropsValue = {
key: textDecoder.decode( // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + keyStringLength))),
key: textDecoder.decode(tempAB2),
value: dataView.getUint32(cursor + keyStringLength),

@@ -268,2 +295,11 @@ next: dataView.getUint32(cursor + keyStringLength + Uint32Array.BYTES_PER_ELEMENT)

case ENTRY_TYPE.ARRAY:
entry.value = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:

@@ -275,5 +311,36 @@ throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");

}
function reserveMemory(dataView, length) {
const firstFreeByte = dataView.getUint32(8);
dataView.setUint32(8, firstFreeByte + length);
return firstFreeByte;
}
function saveValue(textEncoder, dataView, value) {
function arraySaver(textEncoder, dataView, arrayAdditionalAllocation, arrayToSave) {
let totalWrittenBytes = 0;
let memoryForPointersCursor = reserveMemory(dataView, (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT);
totalWrittenBytes += (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT;
const arrayStartEntry = {
type: ENTRY_TYPE.ARRAY,
value: memoryForPointersCursor,
allocatedLength: arrayToSave.length + arrayAdditionalAllocation,
length: arrayToSave.length
};
for (const item of arrayToSave) {
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, item);
dataView.setUint32(memoryForPointersCursor, rOfValue.start);
memoryForPointersCursor += Uint32Array.BYTES_PER_ELEMENT;
totalWrittenBytes += rOfValue.length;
}
const arrayEntryAppendResult = appendEntry(dataView, arrayStartEntry, textEncoder);
totalWrittenBytes += arrayEntryAppendResult.length;
return {
start: arrayEntryAppendResult.start,
length: totalWrittenBytes
};
}
function saveValue(textEncoder, dataView, arrayAdditionalAllocation, value) {
let totalWrittenBytes = 0;
let valuePointer = 0;

@@ -289,2 +356,9 @@

totalWrittenBytes += length;
} else if (Array.isArray(value)) {
const {
start,
length
} = arraySaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;
totalWrittenBytes += length;
} else if (typeof value === "object") {

@@ -294,3 +368,3 @@ const {

length
} = objectSaver(textEncoder, dataView, value);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;

@@ -310,3 +384,3 @@ totalWrittenBytes += length;

function objectSaver(textEncoder, dataView, objectToSave) {
function objectSaver(textEncoder, dataView, arrayAdditionalAllocation, objectToSave) {
let totalWrittenBytes = 0; // const writtenLength = 0;

@@ -318,3 +392,3 @@

for (const [key, value] of objectEntries) {
const rOfValue = saveValue(textEncoder, dataView, value);
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
const objectPropEntry = {

@@ -462,5 +536,274 @@ type: ENTRY_TYPE.OBJECT_PROP,

// isolated due to parser changes ts 3.7
// https://github.com/microsoft/TypeScript/pull/32695
// eslint-disable-next-line prettier/prettier
// export function assertNonNull<T>(v: T): asserts v is NonNullable<T> {
// if (v === undefined || v === null) {
// throw new Error("assertNonNull");
// }
// }
/**
* @template T
* @param {T} v
* @return {asserts v is NonNullable<T>}
*/
function assertNonNull(v) {
if (v === undefined || v === null) {
throw new Error("assertNonNull");
}
}
function arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry) {
const [arrayEntry] = readEntry(dataView, pointerToArrayEntry, textDecoder);
return arrayEntry;
}
function arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry); // out of bound
if (indexToGet >= metadata.length) {
return undefined;
}
const pointerToThePointer = metadata.value + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
const pointer = dataView.getUint32(pointerToThePointer);
return {
pointer,
pointerToThePointer
};
}
function getFinalValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToGet) {
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet);
if (pointers === undefined) {
return undefined;
}
const entry = readEntry(dataView, pointers.pointer, textDecoder);
return entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, entry[0], pointers.pointer);
}
function setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, pointerToEntry) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
if (indexToSet >= metadata.length) {
// we need to re-allocate the array in a new and bigger place
if (indexToSet >= metadata.allocatedLength) {
reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, indexToSet + 1 + arrayAdditionalAllocation, indexToSet + 1);
} else {
// no need to re-allocated, just push the length forward
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: indexToSet + 1
}, textEncoder);
}
}
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToSet);
assertNonNull(pointers);
dataView.setUint32(pointers.pointerToThePointer, pointerToEntry);
}
function setValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, value) {
const saveValueResult = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, saveValueResult.start);
}
function reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, newAllocatedLength, newLength) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
const newArrayValueLocation = reserveMemory(dataView, newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT);
for (let memoryToCopyIndex = 0; memoryToCopyIndex < metadata.length; memoryToCopyIndex += 1) {
dataView.setUint32(newArrayValueLocation + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT, dataView.getUint32(metadata.value + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT));
}
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: newArrayValueLocation,
allocatedLength: newAllocatedLength,
length: newLength
}, textEncoder);
}
class ArrayWrapper {
constructor(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
this.dataView = dataView;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
this.entryPointer = entryPointer;
this.textDecoder = textDecoder;
this.textEncoder = textEncoder;
}
get(target, p) {
if (p in this && p !== "constructor") {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return this[p];
}
if (p === "length") {
return arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
}
if (typeof p === "string" || typeof p === "number") {
const asInt = typeof p === "string" ? Number.parseInt(p, 10) : p;
if (Number.isSafeInteger(asInt)) {
return getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, asInt);
}
} // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return target[p];
}
deleteProperty(target, p) {
throw new Error("unsupported");
}
enumerate() {
throw new Error("unsupported");
}
ownKeys() {
const length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
return [...new Array(length).keys()];
}
getOwnPropertyDescriptor() {
return {
configurable: true,
enumerable: true
};
}
has(target, p) {
throw new Error("unsupported");
}
set(target, p, value) {
setValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, Number.parseInt(p, 10), value);
return true;
}
isExtensible() {
return true;
}
preventExtensions() {
throw new Error("unsupported");
}
setPrototypeOf() {
throw new Error("unsupported");
}
*entries() {
let index = 0;
let length = 0;
do {
yield [index, getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index)];
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*keys() {
let index = 0;
let length = 0;
do {
yield index;
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*values() {
let index = 0;
let length = 0;
do {
yield getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index);
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
get [Symbol.iterator]() {
return this.values;
} // in-place methods
shift() {
throw new Error("unsupported");
}
unshift() {
throw new Error("unsupported");
}
pop() {
throw new Error("unsupported");
}
push() {
throw new Error("unsupported");
}
sort() {
throw new Error("unsupported");
}
splice() {
throw new Error("unsupported");
} // // copy methods
// private concat() {
// throw new Error("unsupported");
// }
// private slice() {
// throw new Error("unsupported");
// }
// private map() {
// throw new Error("unsupported");
// }
// private reduce() {
// throw new Error("unsupported");
// }
}
function createArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
return new Proxy([], new ArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder));
}
function entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, valueEntry, pointerToEntry) {
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(dataView, pointerToEntry, textDecoder, textEncoder, false, arrayAdditionalAllocation);
}
if (valueEntry.type === ENTRY_TYPE.ARRAY) {
return createArrayWrapper(dataView, arrayAdditionalAllocation, pointerToEntry, textDecoder, textEncoder);
}
throw new Error("unsupported yet");
}
const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL = Symbol("GET_UNDERLYING_ARRAY_BUFFER_SYMBOL");
class ObjectWrapper {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel) {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation) {
this.dataView = dataView;

@@ -471,2 +814,3 @@ this.entryPointer = entryPointer;

this.isTopLevel = isTopLevel;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
}

@@ -502,20 +846,3 @@

const [valueEntry] = readEntry(this.dataView, foundEntry[1].value.value, this.textDecoder);
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(this.dataView, foundEntry[1].value.value, this.textDecoder, this.textEncoder);
}
throw new Error("unsupported yet");
return entryToFinalJavaScriptValue(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, valueEntry, foundEntry[1].value.value);
}

@@ -560,3 +887,3 @@

start: newValueEntryPointer
} = saveValue(this.textEncoder, this.dataView, value);
} = saveValue(this.textEncoder, this.dataView, this.arrayAdditionalAllocation, value);
const foundPropEntry = findObjectPropertyEntry(this.dataView, this.entryPointer, p, this.textDecoder); // new prop

@@ -638,15 +965,21 @@

}
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false) {
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false, arrayAdditionalAllocation = 50) {
return new Proxy({
bla: 1
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel));
objectBufferWrapper: "objectBufferWrapper"
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation));
}
function createObjectBuffer(textDecoder, textEncoder, size, initialValue) {
const arrayBuffer = new ArrayBuffer(size);
function createObjectBuffer(textDecoder, textEncoder, size, initialValue, {
arrayAdditionalAllocation,
useSharedArrayBuffer
} = {
arrayAdditionalAllocation: 0,
useSharedArrayBuffer: false
}) {
const arrayBuffer = new (useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer)(size);
const dataView = initializeArrayBuffer(arrayBuffer);
const {
start
} = objectSaver(textEncoder, dataView, initialValue);
dataView.setUint32(8, start);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation || 0, initialValue);
dataView.setUint32(16, start);
return createObjectWrapper(dataView, start, textDecoder, textEncoder, true);

@@ -658,7 +991,60 @@ }

function createObjectBufferFromArrayBuffer(textDecoder, textEncoder, arrayBuffer, // set to true if the give array buffer is not one from `getUnderlyingArrayBuffer`
shouldInitializeArrayBuffer = false) {
shouldInitializeArrayBuffer = false, {
arrayAdditionalAllocation
} = {
arrayAdditionalAllocation: 0
}) {
const dataView = shouldInitializeArrayBuffer ? initializeArrayBuffer(arrayBuffer) : new DataView(arrayBuffer);
return createObjectWrapper(dataView, dataView.getUint32(8), textDecoder, textEncoder);
return createObjectWrapper(dataView, dataView.getUint32(16), textDecoder, textEncoder, true, arrayAdditionalAllocation);
}
export { createObjectBuffer, createObjectBufferFromArrayBuffer, getUnderlyingArrayBuffer };
/* global Atomics */
// I have no idea if its really works as i think it should
function getLock(playerId, sab) {
invariant(playerId > 0, "playerId must be more than 0");
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
return oldValue === 0;
}
function releaseLock(playerId, sab) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, playerId, 0); // we've released a lock. lets tell them about it
if (oldValue === playerId) {
Atomics.notify(int32, 0, +Infinity);
return true;
}
return false;
}
function waitForLock(playerId, sab, timeout) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
if (oldValue === 0) {
return "have-lock";
}
const r = Atomics.wait(int32, 0, oldValue, timeout);
if (r === "not-equal") {
if (Atomics.compareExchange(int32, 0, 0, playerId) === 0) {
return "have-lock";
} else {
return "miss-lock";
}
} else if (r === "timed-out") {
return "timed-out";
} else {
return "no-lock";
}
}
var locks = /*#__PURE__*/Object.freeze({
getLock: getLock,
releaseLock: releaseLock,
waitForLock: waitForLock
});
export { createObjectBuffer, createObjectBufferFromArrayBuffer, getUnderlyingArrayBuffer, locks };

@@ -72,8 +72,16 @@ (function (global, factory) {

}
function arrayBufferCopyTo(origin, startByte, length, target, toTargetByte) {
const copyFrom = new Uint8Array(origin);
const copyTo = new Uint8Array(target);
for (let i = 0; i < length; i += 1) {
copyTo[toTargetByte + i] = copyFrom[startByte + i];
}
}
let ENTRY_TYPE;
(function (ENTRY_TYPE) {
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 0] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 1] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["UNDEFINED"] = 0] = "UNDEFINED";
ENTRY_TYPE[ENTRY_TYPE["NULL"] = 1] = "NULL";
ENTRY_TYPE[ENTRY_TYPE["NUMBER"] = 2] = "NUMBER";

@@ -97,7 +105,9 @@ ENTRY_TYPE[ENTRY_TYPE["BIGINT"] = 3] = "BIGINT";

function initializeArrayBuffer(arrayBuffer) {
const dataView = new DataView(arrayBuffer); // End of data pointer
const dataView = new DataView(arrayBuffer); // global lock
dataView.setUint32(0, 16); // first entry pointer
dataView.setInt32(0, 0); // End of data pointer / first free byte
dataView.setUint32(8, 16);
dataView.setUint32(8, 24); // first entry pointer
dataView.setUint32(16, 24);
return dataView;

@@ -179,3 +189,14 @@ }

case ENTRY_TYPE.ARRAY:
dataView.setUint32(cursor, entry.value);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.length);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.allocatedLength);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -192,5 +213,5 @@ }

// End of data pointer
const firstFreeByte = dataView.getUint32(0);
const firstFreeByte = dataView.getUint32(8);
const written = writeEntry(dataView, firstFreeByte, entry, textEncoder);
dataView.setUint32(0, firstFreeByte + written);
dataView.setUint32(8, firstFreeByte + written);
return {

@@ -234,6 +255,9 @@ start: firstFreeByte,

const stringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT;
entry.value = textDecoder.decode( // this wrapping is needed until:
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + stringLength)));
// eslint-disable-next-line no-case-declarations
const tempAB = new ArrayBuffer(stringLength);
arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0);
entry.value = textDecoder.decode(tempAB);
cursor += stringLength;

@@ -260,8 +284,11 @@ break;

const keyStringLength = dataView.getUint16(cursor);
cursor += Uint16Array.BYTES_PER_ELEMENT; // eslint-disable-next-line no-case-declarations
cursor += Uint16Array.BYTES_PER_ELEMENT; // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB2 = new ArrayBuffer(keyStringLength);
arrayBufferCopyTo(dataView.buffer, cursor, keyStringLength, tempAB2, 0); // eslint-disable-next-line no-case-declarations
const objectPropsValue = {
key: textDecoder.decode( // this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + keyStringLength))),
key: textDecoder.decode(tempAB2),
value: dataView.getUint32(cursor + keyStringLength),

@@ -274,2 +301,11 @@ next: dataView.getUint32(cursor + keyStringLength + Uint32Array.BYTES_PER_ELEMENT)

case ENTRY_TYPE.ARRAY:
entry.value = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:

@@ -281,5 +317,36 @@ throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");

}
function reserveMemory(dataView, length) {
const firstFreeByte = dataView.getUint32(8);
dataView.setUint32(8, firstFreeByte + length);
return firstFreeByte;
}
function saveValue(textEncoder, dataView, value) {
function arraySaver(textEncoder, dataView, arrayAdditionalAllocation, arrayToSave) {
let totalWrittenBytes = 0;
let memoryForPointersCursor = reserveMemory(dataView, (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT);
totalWrittenBytes += (arrayToSave.length + arrayAdditionalAllocation) * Uint32Array.BYTES_PER_ELEMENT;
const arrayStartEntry = {
type: ENTRY_TYPE.ARRAY,
value: memoryForPointersCursor,
allocatedLength: arrayToSave.length + arrayAdditionalAllocation,
length: arrayToSave.length
};
for (const item of arrayToSave) {
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, item);
dataView.setUint32(memoryForPointersCursor, rOfValue.start);
memoryForPointersCursor += Uint32Array.BYTES_PER_ELEMENT;
totalWrittenBytes += rOfValue.length;
}
const arrayEntryAppendResult = appendEntry(dataView, arrayStartEntry, textEncoder);
totalWrittenBytes += arrayEntryAppendResult.length;
return {
start: arrayEntryAppendResult.start,
length: totalWrittenBytes
};
}
function saveValue(textEncoder, dataView, arrayAdditionalAllocation, value) {
let totalWrittenBytes = 0;
let valuePointer = 0;

@@ -295,2 +362,9 @@

totalWrittenBytes += length;
} else if (Array.isArray(value)) {
const {
start,
length
} = arraySaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;
totalWrittenBytes += length;
} else if (typeof value === "object") {

@@ -300,3 +374,3 @@ const {

length
} = objectSaver(textEncoder, dataView, value);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation, value);
valuePointer = start;

@@ -316,3 +390,3 @@ totalWrittenBytes += length;

function objectSaver(textEncoder, dataView, objectToSave) {
function objectSaver(textEncoder, dataView, arrayAdditionalAllocation, objectToSave) {
let totalWrittenBytes = 0; // const writtenLength = 0;

@@ -324,3 +398,3 @@

for (const [key, value] of objectEntries) {
const rOfValue = saveValue(textEncoder, dataView, value);
const rOfValue = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
const objectPropEntry = {

@@ -468,5 +542,274 @@ type: ENTRY_TYPE.OBJECT_PROP,

// isolated due to parser changes ts 3.7
// https://github.com/microsoft/TypeScript/pull/32695
// eslint-disable-next-line prettier/prettier
// export function assertNonNull<T>(v: T): asserts v is NonNullable<T> {
// if (v === undefined || v === null) {
// throw new Error("assertNonNull");
// }
// }
/**
* @template T
* @param {T} v
* @return {asserts v is NonNullable<T>}
*/
function assertNonNull(v) {
if (v === undefined || v === null) {
throw new Error("assertNonNull");
}
}
function arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry) {
const [arrayEntry] = readEntry(dataView, pointerToArrayEntry, textDecoder);
return arrayEntry;
}
function arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry); // out of bound
if (indexToGet >= metadata.length) {
return undefined;
}
const pointerToThePointer = metadata.value + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
const pointer = dataView.getUint32(pointerToThePointer);
return {
pointer,
pointerToThePointer
};
}
function getFinalValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToGet) {
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToGet);
if (pointers === undefined) {
return undefined;
}
const entry = readEntry(dataView, pointers.pointer, textDecoder);
return entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, entry[0], pointers.pointer);
}
function setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, pointerToEntry) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
if (indexToSet >= metadata.length) {
// we need to re-allocate the array in a new and bigger place
if (indexToSet >= metadata.allocatedLength) {
reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, indexToSet + 1 + arrayAdditionalAllocation, indexToSet + 1);
} else {
// no need to re-allocated, just push the length forward
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: indexToSet + 1
}, textEncoder);
}
}
const pointers = arrayGetPointersToValue(dataView, textDecoder, pointerToArrayEntry, indexToSet);
assertNonNull(pointers);
dataView.setUint32(pointers.pointerToThePointer, pointerToEntry);
}
function setValueAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, value) {
const saveValueResult = saveValue(textEncoder, dataView, arrayAdditionalAllocation, value);
setValuePointerAtArrayIndex(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, pointerToArrayEntry, indexToSet, saveValueResult.start);
}
function reallocateArray(dataView, textDecoder, textEncoder, pointerToArrayEntry, newAllocatedLength, newLength) {
const metadata = arrayGetMetadata(dataView, textDecoder, pointerToArrayEntry);
const newArrayValueLocation = reserveMemory(dataView, newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT);
for (let memoryToCopyIndex = 0; memoryToCopyIndex < metadata.length; memoryToCopyIndex += 1) {
dataView.setUint32(newArrayValueLocation + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT, dataView.getUint32(metadata.value + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT));
}
writeEntry(dataView, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
value: newArrayValueLocation,
allocatedLength: newAllocatedLength,
length: newLength
}, textEncoder);
}
class ArrayWrapper {
constructor(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
this.dataView = dataView;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
this.entryPointer = entryPointer;
this.textDecoder = textDecoder;
this.textEncoder = textEncoder;
}
get(target, p) {
if (p in this && p !== "constructor") {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return this[p];
}
if (p === "length") {
return arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
}
if (typeof p === "string" || typeof p === "number") {
const asInt = typeof p === "string" ? Number.parseInt(p, 10) : p;
if (Number.isSafeInteger(asInt)) {
return getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, asInt);
}
} // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
return target[p];
}
deleteProperty(target, p) {
throw new Error("unsupported");
}
enumerate() {
throw new Error("unsupported");
}
ownKeys() {
const length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
return [...new Array(length).keys()];
}
getOwnPropertyDescriptor() {
return {
configurable: true,
enumerable: true
};
}
has(target, p) {
throw new Error("unsupported");
}
set(target, p, value) {
setValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, Number.parseInt(p, 10), value);
return true;
}
isExtensible() {
return true;
}
preventExtensions() {
throw new Error("unsupported");
}
setPrototypeOf() {
throw new Error("unsupported");
}
*entries() {
let index = 0;
let length = 0;
do {
yield [index, getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index)];
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*keys() {
let index = 0;
let length = 0;
do {
yield index;
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
*values() {
let index = 0;
let length = 0;
do {
yield getFinalValueAtArrayIndex(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, this.entryPointer, index);
index += 1;
length = arrayGetMetadata(this.dataView, this.textDecoder, this.entryPointer).length;
} while (index < length);
}
get [Symbol.iterator]() {
return this.values;
} // in-place methods
shift() {
throw new Error("unsupported");
}
unshift() {
throw new Error("unsupported");
}
pop() {
throw new Error("unsupported");
}
push() {
throw new Error("unsupported");
}
sort() {
throw new Error("unsupported");
}
splice() {
throw new Error("unsupported");
} // // copy methods
// private concat() {
// throw new Error("unsupported");
// }
// private slice() {
// throw new Error("unsupported");
// }
// private map() {
// throw new Error("unsupported");
// }
// private reduce() {
// throw new Error("unsupported");
// }
}
function createArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder) {
return new Proxy([], new ArrayWrapper(dataView, arrayAdditionalAllocation, entryPointer, textDecoder, textEncoder));
}
function entryToFinalJavaScriptValue(dataView, textDecoder, textEncoder, arrayAdditionalAllocation, valueEntry, pointerToEntry) {
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(dataView, pointerToEntry, textDecoder, textEncoder, false, arrayAdditionalAllocation);
}
if (valueEntry.type === ENTRY_TYPE.ARRAY) {
return createArrayWrapper(dataView, arrayAdditionalAllocation, pointerToEntry, textDecoder, textEncoder);
}
throw new Error("unsupported yet");
}
const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL = Symbol("GET_UNDERLYING_ARRAY_BUFFER_SYMBOL");
class ObjectWrapper {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel) {
constructor(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation) {
this.dataView = dataView;

@@ -477,2 +820,3 @@ this.entryPointer = entryPointer;

this.isTopLevel = isTopLevel;
this.arrayAdditionalAllocation = arrayAdditionalAllocation;
}

@@ -508,20 +852,3 @@

const [valueEntry] = readEntry(this.dataView, foundEntry[1].value.value, this.textDecoder);
if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(this.dataView, foundEntry[1].value.value, this.textDecoder, this.textEncoder);
}
throw new Error("unsupported yet");
return entryToFinalJavaScriptValue(this.dataView, this.textDecoder, this.textEncoder, this.arrayAdditionalAllocation, valueEntry, foundEntry[1].value.value);
}

@@ -566,3 +893,3 @@

start: newValueEntryPointer
} = saveValue(this.textEncoder, this.dataView, value);
} = saveValue(this.textEncoder, this.dataView, this.arrayAdditionalAllocation, value);
const foundPropEntry = findObjectPropertyEntry(this.dataView, this.entryPointer, p, this.textDecoder); // new prop

@@ -644,15 +971,21 @@

}
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false) {
function createObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel = false, arrayAdditionalAllocation = 50) {
return new Proxy({
bla: 1
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel));
objectBufferWrapper: "objectBufferWrapper"
}, new ObjectWrapper(dataView, entryPointer, textDecoder, textEncoder, isTopLevel, arrayAdditionalAllocation));
}
function createObjectBuffer(textDecoder, textEncoder, size, initialValue) {
const arrayBuffer = new ArrayBuffer(size);
function createObjectBuffer(textDecoder, textEncoder, size, initialValue, {
arrayAdditionalAllocation,
useSharedArrayBuffer
} = {
arrayAdditionalAllocation: 0,
useSharedArrayBuffer: false
}) {
const arrayBuffer = new (useSharedArrayBuffer ? SharedArrayBuffer : ArrayBuffer)(size);
const dataView = initializeArrayBuffer(arrayBuffer);
const {
start
} = objectSaver(textEncoder, dataView, initialValue);
dataView.setUint32(8, start);
} = objectSaver(textEncoder, dataView, arrayAdditionalAllocation || 0, initialValue);
dataView.setUint32(16, start);
return createObjectWrapper(dataView, start, textDecoder, textEncoder, true);

@@ -664,10 +997,64 @@ }

function createObjectBufferFromArrayBuffer(textDecoder, textEncoder, arrayBuffer, // set to true if the give array buffer is not one from `getUnderlyingArrayBuffer`
shouldInitializeArrayBuffer = false) {
shouldInitializeArrayBuffer = false, {
arrayAdditionalAllocation
} = {
arrayAdditionalAllocation: 0
}) {
const dataView = shouldInitializeArrayBuffer ? initializeArrayBuffer(arrayBuffer) : new DataView(arrayBuffer);
return createObjectWrapper(dataView, dataView.getUint32(8), textDecoder, textEncoder);
return createObjectWrapper(dataView, dataView.getUint32(16), textDecoder, textEncoder, true, arrayAdditionalAllocation);
}
/* global Atomics */
// I have no idea if its really works as i think it should
function getLock(playerId, sab) {
invariant(playerId > 0, "playerId must be more than 0");
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
return oldValue === 0;
}
function releaseLock(playerId, sab) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, playerId, 0); // we've released a lock. lets tell them about it
if (oldValue === playerId) {
Atomics.notify(int32, 0, +Infinity);
return true;
}
return false;
}
function waitForLock(playerId, sab, timeout) {
const int32 = new Int32Array(sab);
const oldValue = Atomics.compareExchange(int32, 0, 0, playerId);
if (oldValue === 0) {
return "have-lock";
}
const r = Atomics.wait(int32, 0, oldValue, timeout);
if (r === "not-equal") {
if (Atomics.compareExchange(int32, 0, 0, playerId) === 0) {
return "have-lock";
} else {
return "miss-lock";
}
} else if (r === "timed-out") {
return "timed-out";
} else {
return "no-lock";
}
}
var locks = /*#__PURE__*/Object.freeze({
getLock: getLock,
releaseLock: releaseLock,
waitForLock: waitForLock
});
exports.createObjectBuffer = createObjectBuffer;
exports.createObjectBufferFromArrayBuffer = createObjectBufferFromArrayBuffer;
exports.getUnderlyingArrayBuffer = getUnderlyingArrayBuffer;
exports.locks = locks;

@@ -674,0 +1061,0 @@ Object.defineProperty(exports, '__esModule', { value: true });

{
"name": "@bnaya/objectbuffer",
"description": "Object like api, backed by an array buffer",
"version": "0.1.4",
"version": "0.2.0",
"main": "dist/objectbuffer.cjs.js",

@@ -17,3 +17,4 @@ "module": "dist/index.js",

"build": "yarn cleanup; yarn babel-build; yarn build-declarations; rollup -c; cp dist/index.d.ts dist/objectbuffer.cjs.d.ts ;echo `git rev-parse HEAD` > COMMIT",
"prepack": "yarn build"
"prepack": "yarn build",
"browser-playground": "webpack-dev-server --mode=development --config playground/webpack.config.js playground/main.js --open"
},

@@ -29,5 +30,7 @@ "devDependencies": {

"@typescript-eslint/parser": "^2.0.0",
"babel-loader": "^8.0.6",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.1.0",
"eslint-plugin-prettier": "^3.1.0",
"html-webpack-plugin": "^3.2.0",
"husky": "^3.0.4",

@@ -41,3 +44,7 @@ "jest": "^24.9.0",

"rollup-plugin-node-resolve": "^5.2.0",
"typescript": "^3.6.2",
"typescript": "^3.7.0-dev.20190927",
"webpack": "^4.39.3",
"webpack-cli": "^3.3.8",
"webpack-dev-server": "^3.8.0",
"worker-loader": "^2.0.0",
"yarn-deduplicate": "^1.1.1"

@@ -44,0 +51,0 @@ },

@@ -1,17 +0,40 @@

# WIP - object like api backed by a single array buffer.
# WIP: object-like api, backed by a [shared]arraybuffer.
For Modern browsers and node. Zero direct dependencies.
"design" doc:
https://docs.google.com/document/d/1-UlUyH3HgOrN58avyScZlfjQtfJxgVwK_yE35mQHpYw/edit?usp=sharing
The library offers you an api that have the look & feel of a regular javascript object, but the data is saved to an `ArrayBuffer` that can be shared or transferred to a `WebWorker`.
The library is still not complete, and will never offer full compatibility with plain js objects due, to the nature of the language and the problems space.
## Play with it:
[![Edit objectbuffer demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/objectbuffer-demo-uyov5?fontsize=14&module=%2Fsrc%2Findex.test.ts)
See [main.js](playground/main.js) for shared memory example.
to run it: clone the repo, `yarn install` and `yarn browser-playground`
## Why?
Personal interest, Maybe will be useful as shared memory primitive, and communicating with wasm.
Exchanging data with `WebWorkers` (other than ArrayBuffer) is done by serializing and copying the data to the other side.
for some use-cases, it's slow and memory expensive.
`ArrayBuffer` can be `transferred` without copy, and `SharedArrayBuffer` can be directly shared, but out of the box, it's hard to use `ArrayBuffer` as more than a [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays).
At the current state, it's working! but very optimized (based only on linked lists), only append data (no logic to reuse unreachable memory)
`SharedArrayBuffer` and `ArrayBuffer`
## Motivation
Personal interest, Maybe will be useful as shared memory primitive, and communicating with WASM. Maybe state management with shared memory across workers?
## What do we have in hand?
It's working! but very unoptimized (eg objects are simple linked lists), only append data (no logic to reuse unreachable memory)
and its not extending the backing `arraybuffer` size by itself.
if you pass the limit, an exception will be thrown.
We still don't have [ArrayBuffer.prototype.transfer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer) So we can't do that efficiently.
if you exceed the sb size, an exception will be thrown.
[ArrayBuffer.prototype.transfer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer) is still not supported anywhere, so we can't do that efficiently anyhow
### What's working:
* Kinda what ever that can go into `JSON.stringify`
* objects
* arrays (without methods yet)
* global lock using [Atomics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics) (i hope its really working)
### Missing parts
* `array` (Not sure yet if to make just make them as objects, or something smarter)
* `array` methods
* `Date`

@@ -21,7 +44,2 @@ * `Map` On primitive key/value

### What's working:
* Kinda what ever that can do into `JSON.stringify`
* objects!
* other
### What's not working yet, but can be:

@@ -35,5 +53,9 @@ * `bigint` bigger than 64 bit

### "design" doc:
https://docs.google.com/document/d/1-UlUyH3HgOrN58avyScZlfjQtfJxgVwK_yE35mQHpYw/edit?usp=sharing
## Contribution / Collaboration
There's a huge place for optimizations, code hygiene, and features!
Feel free to open issues and maybe implementing missing parts

@@ -1,45 +0,3 @@

import { initializeArrayBuffer } from "./internal/store";
import { objectSaver } from "./internal/objectSaver";
import {
createObjectWrapper,
GET_UNDERLYING_ARRAY_BUFFER_SYMBOL
} from "./internal/objectWrapper";
export function createObjectBuffer<T = any>(
textDecoder: any,
textEncoder: any,
size: number,
initialValue: T
): T {
const arrayBuffer = new ArrayBuffer(size);
const dataView = initializeArrayBuffer(arrayBuffer);
const { start } = objectSaver(textEncoder, dataView, initialValue);
dataView.setUint32(8, start);
return createObjectWrapper(dataView, start, textDecoder, textEncoder, true);
}
export function getUnderlyingArrayBuffer(objectBuffer: any): ArrayBuffer {
return objectBuffer[GET_UNDERLYING_ARRAY_BUFFER_SYMBOL];
}
export function createObjectBufferFromArrayBuffer<T = any>(
textDecoder: any,
textEncoder: any,
arrayBuffer: ArrayBuffer,
// set to true if the give array buffer is not one from `getUnderlyingArrayBuffer`
shouldInitializeArrayBuffer = false
): T {
const dataView = shouldInitializeArrayBuffer
? initializeArrayBuffer(arrayBuffer)
: new DataView(arrayBuffer);
return createObjectWrapper(
dataView,
dataView.getUint32(8),
textDecoder,
textEncoder
);
}
export * from "./internal/api";
import * as locks from "./internal/locks";
export { locks };

@@ -9,4 +9,4 @@ /* eslint-env jest */

Object {
"0": "NULL",
"1": "UNDEFINED",
"0": "UNDEFINED",
"1": "NULL",
"10": "ARRAY_ITEM",

@@ -30,3 +30,3 @@ "11": "MAP",

"MAP": 11,
"NULL": 0,
"NULL": 1,
"NUMBER": 2,

@@ -38,3 +38,3 @@ "OBJECT": 7,

"UBIGINT": 4,
"UNDEFINED": 1,
"UNDEFINED": 0,
}

@@ -41,0 +41,0 @@ `);

import { createKnownTypeGuard } from "./utils";
export enum ENTRY_TYPE {
UNDEFINED,
NULL,
UNDEFINED,
NUMBER,

@@ -7,0 +7,0 @@ BIGINT,

@@ -15,4 +15,3 @@ import { ENTRY_TYPE } from "./entry-types";

| ObjectPropEntry
| ArrayEntry
| ArrayItemEntry;
| ArrayEntry;

@@ -82,12 +81,4 @@ export interface NullEntry {

value: number;
length: number;
allocatedLength: number;
}
export interface ArrayItemEntry {
type: ENTRY_TYPE.ARRAY_ITEM;
value: {
// pointer to value entry
value: number;
// pointer to next prop
next: number;
};
}

@@ -28,3 +28,3 @@ /* eslint-env jest */

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -34,3 +34,3 @@ expect(saverOutput).toMatchInlineSnapshot(`

"length": 159,
"start": 170,
"start": 178,
}

@@ -37,0 +37,0 @@ `);

@@ -11,2 +11,3 @@ // import { isPrimitive, primitiveValueToEntry } from "./utils";

dataView: DataView,
arrayAdditionalAllocation: number,
objectToSave: any

@@ -22,3 +23,8 @@ ) {

for (const [key, value] of objectEntries) {
const rOfValue = saveValue(textEncoder, dataView, value);
const rOfValue = saveValue(
textEncoder,
dataView,
arrayAdditionalAllocation,
value
);

@@ -25,0 +31,0 @@ const objectPropEntry: ObjectPropEntry = {

@@ -27,3 +27,3 @@ /* eslint-env jest */

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -71,3 +71,3 @@ const objectWrapper: any = createObjectWrapper(

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -102,3 +102,3 @@ const objectWrapper: any = createObjectWrapper(

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -144,3 +144,3 @@ const objectWrapper = createObjectWrapper(

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -187,3 +187,3 @@ const objectWrapper = createObjectWrapper(

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -190,0 +190,0 @@ const objectWrapper = createObjectWrapper(

import { ObjectEntry } from "./interfaces";
import { readEntry, writeEntry, appendEntry } from "./store";
import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { ENTRY_TYPE } from "./entry-types";
import {

@@ -12,2 +12,4 @@ findObjectPropertyEntry,

import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
export const GET_UNDERLYING_ARRAY_BUFFER_SYMBOL = Symbol(

@@ -23,3 +25,4 @@ "GET_UNDERLYING_ARRAY_BUFFER_SYMBOL"

private textEncoder: any,
private isTopLevel: boolean
private isTopLevel: boolean,
private arrayAdditionalAllocation: number
) {}

@@ -65,24 +68,10 @@

if (valueEntry.type === ENTRY_TYPE.NULL) {
return null;
}
if (valueEntry.type === ENTRY_TYPE.UNDEFINED) {
return undefined;
}
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
if (valueEntry.type === ENTRY_TYPE.OBJECT) {
return createObjectWrapper(
this.dataView,
foundEntry[1].value.value,
this.textDecoder,
this.textEncoder
);
}
throw new Error("unsupported yet");
return entryToFinalJavaScriptValue(
this.dataView,
this.textDecoder,
this.textEncoder,
this.arrayAdditionalAllocation,
valueEntry,
foundEntry[1].value.value
);
}

@@ -147,2 +136,3 @@

this.dataView,
this.arrayAdditionalAllocation,
value

@@ -265,6 +255,7 @@ );

textEncoder: any,
isTopLevel = false
isTopLevel = false,
arrayAdditionalAllocation = 50
): T {
return new Proxy(
{ bla: 1 },
{ objectBufferWrapper: "objectBufferWrapper" },
new ObjectWrapper(

@@ -275,5 +266,6 @@ dataView,

textEncoder,
isTopLevel
isTopLevel,
arrayAdditionalAllocation
)
) as any;
}

@@ -29,3 +29,3 @@ /* eslint-env jest */

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -41,3 +41,3 @@ let foundEntry = findObjectPropertyEntry(

Array [
71,
79,
Object {

@@ -47,4 +47,4 @@ "type": 8,

"key": "a",
"next": 42,
"value": 62,
"next": 50,
"value": 70,
},

@@ -82,3 +82,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -97,4 +97,4 @@ const gotEntries = getObjectPropertiesEntries(

"key": "5",
"next": 129,
"value": 141,
"next": 137,
"value": 149,
},

@@ -106,4 +106,4 @@ },

"key": "a",
"next": 100,
"value": 120,
"next": 108,
"value": 128,
},

@@ -115,4 +115,4 @@ },

"key": "kawabanga",
"next": 87,
"value": 99,
"next": 95,
"value": 107,
},

@@ -124,4 +124,4 @@ },

"key": "b",
"next": 51,
"value": 74,
"next": 59,
"value": 82,
},

@@ -134,3 +134,3 @@ },

"next": 0,
"value": 46,
"value": 54,
},

@@ -155,3 +155,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -178,4 +178,4 @@ deleteObjectPropertyEntryByKey(

"key": "b",
"next": 30,
"value": 42,
"next": 38,
"value": 50,
},

@@ -187,4 +187,4 @@ },

"key": "c",
"next": 17,
"value": 29,
"next": 25,
"value": 37,
},

@@ -197,3 +197,3 @@ },

"next": 0,
"value": 16,
"value": 24,
},

@@ -219,3 +219,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -238,4 +238,4 @@ deleteObjectPropertyEntryByKey(

"key": "a",
"next": 55,
"value": 67,
"next": 63,
"value": 75,
},

@@ -247,4 +247,4 @@ },

"key": "b",
"next": 30,
"value": 42,
"next": 38,
"value": 50,
},

@@ -257,3 +257,3 @@ },

"next": 0,
"value": 29,
"value": 37,
},

@@ -280,3 +280,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -299,4 +299,4 @@ deleteObjectPropertyEntryByKey(

"key": "a",
"next": 76,
"value": 88,
"next": 84,
"value": 96,
},

@@ -308,4 +308,4 @@ },

"key": "b",
"next": 38,
"value": 63,
"next": 46,
"value": 71,
},

@@ -317,4 +317,4 @@ },

"key": "d",
"next": 25,
"value": 37,
"next": 33,
"value": 45,
},

@@ -327,3 +327,3 @@ },

"next": 0,
"value": 16,
"value": 24,
},

@@ -348,3 +348,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -359,3 +359,3 @@ const found = findLastObjectPropertyEntry(

Array [
17,
25,
Object {

@@ -366,3 +366,3 @@ "type": 8,

"next": 0,
"value": 16,
"value": 24,
},

@@ -382,4 +382,4 @@ },

"key": "a",
"next": 42,
"value": 54,
"next": 50,
"value": 62,
},

@@ -391,4 +391,4 @@ },

"key": "b",
"next": 17,
"value": 29,
"next": 25,
"value": 37,
},

@@ -401,3 +401,3 @@ },

"next": 0,
"value": 16,
"value": 24,
},

@@ -418,3 +418,3 @@ },

const saverOutput = objectSaver(textEncoder, dataView, objectToSave);
const saverOutput = objectSaver(textEncoder, dataView, 0, objectToSave);

@@ -429,3 +429,3 @@ const found = findLastObjectPropertyEntry(

Array [
16,
24,
Object {

@@ -432,0 +432,0 @@ "type": 7,

import { primitiveValueToEntry, isPrimitive } from "./utils";
import { appendEntry } from "./store";
import { objectSaver } from "./objectSaver";
import { arraySaver } from "./arraySaver";
export function saveValue(textEncoder: any, dataView: DataView, value: any) {
export function saveValue(
textEncoder: any,
dataView: DataView,
arrayAdditionalAllocation: number,
value: any
) {
let totalWrittenBytes = 0;

@@ -15,4 +21,18 @@ let valuePointer = 0;

totalWrittenBytes += length;
} else if (Array.isArray(value)) {
const { start, length } = arraySaver(
textEncoder,
dataView,
arrayAdditionalAllocation,
value
);
valuePointer = start;
totalWrittenBytes += length;
} else if (typeof value === "object") {
const { start, length } = objectSaver(textEncoder, dataView, value);
const { start, length } = objectSaver(
textEncoder,
dataView,
arrayAdditionalAllocation,
value
);
valuePointer = start;

@@ -19,0 +39,0 @@ totalWrittenBytes += length;

@@ -16,3 +16,3 @@ /* eslint-env jest */

test("initializeArrayBuffer", () => {
const arrayBuffer = new ArrayBuffer(16);
const arrayBuffer = new ArrayBuffer(20);

@@ -25,3 +25,3 @@ initializeArrayBuffer(arrayBuffer);

"2:0x00",
"3:0x10",
"3:0x00",
"4:0x00",

@@ -34,3 +34,3 @@ "5:0x00",

"10:0x00",
"11:0x10",
"11:0x18",
"12:0x00",

@@ -40,2 +40,6 @@ "13:0x00",

"15:0x00",
"16:0x00",
"17:0x00",
"18:0x00",
"19:0x18",
]

@@ -368,3 +372,3 @@ `);

test("appendEntry", () => {
const arrayBuffer = new ArrayBuffer(32);
const arrayBuffer = new ArrayBuffer(40);
const textEncoder = new utils.TextEncoder();

@@ -386,3 +390,3 @@ const dataView = new DataView(arrayBuffer);

"length": 14,
"start": 16,
"start": 24,
}

@@ -396,3 +400,3 @@ `);

"2:0x00",
"3:0x1e",
"3:0x00",
"4:0x00",

@@ -405,3 +409,3 @@ "5:0x00",

"10:0x00",
"11:0x10",
"11:0x26",
"12:0x00",

@@ -411,18 +415,26 @@ "13:0x00",

"15:0x00",
"16:0x05",
"16:0x00",
"17:0x00",
"18:0x0b",
"19:0x69",
"20:0x6d",
"21:0x20",
"22:0x61",
"23:0x20",
"24:0x73",
"25:0x74",
"26:0x72",
"18:0x00",
"19:0x18",
"20:0x00",
"21:0x00",
"22:0x00",
"23:0x00",
"24:0x05",
"25:0x00",
"26:0x0b",
"27:0x69",
"28:0x6e",
"29:0x67",
"30:0x00",
"31:0x00",
"28:0x6d",
"29:0x20",
"30:0x61",
"31:0x20",
"32:0x73",
"33:0x74",
"34:0x72",
"35:0x69",
"36:0x6e",
"37:0x67",
"38:0x00",
"39:0x00",
]

@@ -443,3 +455,3 @@ `);

"length": 2,
"start": 30,
"start": 38,
}

@@ -452,3 +464,3 @@ `);

"2:0x00",
"3:0x20",
"3:0x00",
"4:0x00",

@@ -461,3 +473,3 @@ "5:0x00",

"10:0x00",
"11:0x10",
"11:0x28",
"12:0x00",

@@ -467,18 +479,26 @@ "13:0x00",

"15:0x00",
"16:0x05",
"16:0x00",
"17:0x00",
"18:0x0b",
"19:0x69",
"20:0x6d",
"21:0x20",
"22:0x61",
"23:0x20",
"24:0x73",
"25:0x74",
"26:0x72",
"18:0x00",
"19:0x18",
"20:0x00",
"21:0x00",
"22:0x00",
"23:0x00",
"24:0x05",
"25:0x00",
"26:0x0b",
"27:0x69",
"28:0x6e",
"29:0x67",
"30:0x06",
"31:0x01",
"28:0x6d",
"29:0x20",
"30:0x61",
"31:0x20",
"32:0x73",
"33:0x74",
"34:0x72",
"35:0x69",
"36:0x6e",
"37:0x67",
"38:0x06",
"39:0x01",
]

@@ -485,0 +505,0 @@ `);

import { ENTRY_TYPE } from "./entry-types";
import { Entry, ObjectPropEntry } from "./interfaces";
import { arrayBufferCopyTo } from "./utils";
const DEFAULT_ARRAY_BUFFER_SIZE = 10 ^ 6;

@@ -21,7 +22,10 @@

// End of data pointer
dataView.setUint32(0, 16);
// global lock
dataView.setInt32(0, 0);
// End of data pointer / first free byte
dataView.setUint32(8, 24);
// first entry pointer
dataView.setUint32(8, 16);
dataView.setUint32(16, 24);

@@ -111,3 +115,14 @@ return dataView;

case ENTRY_TYPE.ARRAY:
dataView.setUint32(cursor, entry.value);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.length);
cursor += Uint32Array.BYTES_PER_ELEMENT;
dataView.setUint32(cursor, entry.allocatedLength);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -128,6 +143,6 @@ }

// End of data pointer
const firstFreeByte = dataView.getUint32(0);
const firstFreeByte = dataView.getUint32(8);
const written = writeEntry(dataView, firstFreeByte, entry, textEncoder);
dataView.setUint32(0, firstFreeByte + written);
dataView.setUint32(8, firstFreeByte + written);

@@ -182,8 +197,10 @@ return {

entry.value = textDecoder.decode(
// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(dataView.buffer.slice(cursor, cursor + stringLength))
);
// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB = new ArrayBuffer(stringLength);
arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0);
entry.value = textDecoder.decode(tempAB);
cursor += stringLength;

@@ -213,11 +230,11 @@

// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
const tempAB2 = new ArrayBuffer(keyStringLength);
arrayBufferCopyTo(dataView.buffer, cursor, keyStringLength, tempAB2, 0);
// eslint-disable-next-line no-case-declarations
const objectPropsValue: ObjectPropEntry["value"] = {
key: textDecoder.decode(
// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
new Uint8Array(
dataView.buffer.slice(cursor, cursor + keyStringLength)
)
),
key: textDecoder.decode(tempAB2),
value: dataView.getUint32(cursor + keyStringLength),

@@ -237,2 +254,11 @@ next: dataView.getUint32(

case ENTRY_TYPE.ARRAY:
entry.value = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = dataView.getUint32(cursor);
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:

@@ -244,1 +270,9 @@ throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");

}
export function reserveMemory(dataView: DataView, length: number) {
const firstFreeByte = dataView.getUint32(8);
dataView.setUint32(8, firstFreeByte + length);
return firstFreeByte;
}

@@ -79,1 +79,16 @@ import { primitive, Entry } from "./interfaces";

}
export function arrayBufferCopyTo(
origin: ArrayBuffer,
startByte: number,
length: number,
target: ArrayBuffer,
toTargetByte: number
) {
const copyFrom = new Uint8Array(origin);
const copyTo = new Uint8Array(target);
for (let i = 0; i < length; i += 1) {
copyTo[toTargetByte + i] = copyFrom[startByte + i];
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc