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.0.0-f1ba10a to 0.0.0-f463ae1

dist/internal/arraySaverIterative.d.ts

3

dist/index.js

@@ -11,4 +11,3 @@ /**

/** */
export { createObjectBuffer, resizeObjectBuffer, getUnderlyingArrayBuffer, loadObjectBuffer, replaceUnderlyingArrayBuffer // eslint-disable-next-line @typescript-eslint/camelcase
, sizeOf as unreliable_sizeOf, memoryStats, disposeWrapperObject, updateExternalArgs } from "./internal/api";
export { createObjectBuffer, resizeObjectBuffer, getUnderlyingArrayBuffer, loadObjectBuffer, replaceUnderlyingArrayBuffer, sizeOf as unreliable_sizeOf, memoryStats, disposeWrapperObject, updateExternalArgs } from "./internal/api";
export { acquireLock, acquireLockWait, releaseLock } from "./internal/locks";
import { IMemPool } from "@thi.ng/malloc";
export declare function allocationsTransaction(operation: () => void, pool: IMemPool): void;
export declare function allocationsTransaction<T>(operation: () => T, pool: IMemPool): T;
//# sourceMappingURL=allocationsTransaction.d.ts.map

@@ -58,6 +58,9 @@ import { OutOfMemoryError } from "./exceptions"; // extend pool and not monkey patch? need to think about it

operation();
pool.malloc = originalMalloc;
pool.calloc = originalCalloc;
pool.realloc = originalRealloc;
try {
return operation();
} finally {
pool.malloc = originalMalloc;
pool.calloc = originalCalloc;
pool.realloc = originalRealloc;
}
}
import { initializeArrayBuffer } from "./store";
import { objectSaver } from "./objectSaver";
import { createObjectWrapper } from "./objectWrapper";

@@ -9,2 +8,5 @@ import { arrayBufferCopyTo, externalArgsApiToExternalArgsApi, getInternalAPI, isPrimitive } from "./utils";

import { UnsupportedOperationError } from "./exceptions";
import { createHeap } from "../structsGenerator/consts";
import { saveValueIterative } from "./saveValue";
import { allocationsTransaction } from "./allocationsTransaction";

@@ -17,3 +19,3 @@ /**

export function createObjectBuffer(externalArgs, size, initialValue, options = {}) {
if (Array.isArray(initialValue) || initialValue instanceof Date || initialValue instanceof Map || initialValue instanceof Set || isPrimitive(initialValue)) {
if (Array.isArray(initialValue) || initialValue instanceof Date || initialValue instanceof Map || initialValue instanceof Set || isPrimitive(initialValue) || typeof initialValue === "symbol") {
throw new UnsupportedOperationError();

@@ -36,7 +38,9 @@ }

float64: new Float64Array(arrayBuffer),
bigUint64: new BigUint64Array(arrayBuffer)
bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer)
};
const start = objectSaver(externalArgsApiToExternalArgsApi(externalArgs), carrier, [], new Map(), initialValue);
carrier.uint32[INITIAL_ENTRY_POINTER_TO_POINTER / Uint32Array.BYTES_PER_ELEMENT] = start;
return createObjectWrapper(externalArgsApiToExternalArgsApi(externalArgs), carrier, start);
allocationsTransaction(() => {
saveValueIterative(externalArgsApiToExternalArgsApi(externalArgs), carrier, [], INITIAL_ENTRY_POINTER_TO_POINTER, initialValue);
}, allocator);
return createObjectWrapper(externalArgsApiToExternalArgsApi(externalArgs), carrier, carrier.heap.Uint32Array[INITIAL_ENTRY_POINTER_TO_POINTER / Uint32Array.BYTES_PER_ELEMENT]);
}

@@ -85,3 +89,4 @@ /**

float64: new Float64Array(arrayBuffer),
bigUint64: new BigUint64Array(arrayBuffer)
bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer)
};

@@ -124,5 +129,6 @@ return createObjectWrapper(externalArgsApiToExternalArgsApi(externalArgs), carrier, carrier.uint32[INITIAL_ENTRY_POINTER_TO_POINTER / Uint32Array.BYTES_PER_ELEMENT]);

float64: new Float64Array(newArrayBuffer),
bigUint64: new BigUint64Array(newArrayBuffer)
}; // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
bigUint64: new BigUint64Array(newArrayBuffer),
heap: createHeap(newArrayBuffer)
}; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error

@@ -129,0 +135,0 @@ allocator.end = newArrayBuffer.byteLength;

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

import { ArrayEntry, ExternalArgs, GlobalCarrier } from "./interfaces";
export declare function arrayGetMetadata(carrier: GlobalCarrier, pointerToArrayEntry: number): ArrayEntry;
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { Heap } from "../structsGenerator/consts";
export declare function arrayGetPointersToValueInIndex(carrier: GlobalCarrier, pointerToArrayEntry: number, indexToGet: number): {

@@ -17,5 +17,5 @@ pointer: number;

*/
export declare function shrinkArray(externalArgs: ExternalArgs, carrier: GlobalCarrier, pointerToArrayEntry: number, wishedLength: number): void;
export declare function arraySort(externalArgs: ExternalArgs, globalCarrier: GlobalCarrier, pointerToArrayEntry: number, sortComparator?: (a: any, b: any) => 1 | -1 | 0): void;
export declare function arrayReverse(externalArgs: ExternalArgs, carrier: GlobalCarrier, pointerToArrayEntry: number): void;
export declare function shrinkArray(heap: Heap, pointerToArrayEntry: number, wishedLength: number): void;
export declare function arraySort(externalArgs: ExternalArgs, carrier: GlobalCarrier, pointerToArrayEntry: number, sortComparator?: (a: any, b: any) => 1 | -1 | 0): void;
export declare function arrayReverse(carrier: GlobalCarrier, pointerToArrayEntry: number): void;
//# sourceMappingURL=arrayHelpers.d.ts.map

@@ -1,17 +0,13 @@

import { readEntry, writeEntry, writeValueInPtrToPtrAndHandleMemory } from "./store";
import { writeValueInPtrToPtrAndHandleMemory } from "./store";
import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { ENTRY_TYPE } from "./entry-types";
import { assertNonNull } from "./assertNonNull";
export function arrayGetMetadata(carrier, pointerToArrayEntry) {
const arrayEntry = readEntry(carrier, pointerToArrayEntry);
return arrayEntry;
}
import { array_length_get, array_dataspacePointer_get, array_allocatedLength_get, array_length_set, array_set_all, array_refsCount_get } from "./generatedStructs";
export function arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, indexToGet) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry); // out of bound
if (indexToGet >= metadata.length) {
// out of bound
if (indexToGet >= array_length_get(carrier.heap, pointerToArrayEntry)) {
return undefined;
}
const pointerToThePointer = metadata.value + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
const pointerToThePointer = array_dataspacePointer_get(carrier.heap, pointerToArrayEntry) + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
const pointer = carrier.uint32[pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT];

@@ -47,16 +43,8 @@ return {

export function extendArrayIfNeeded(externalArgs, carrier, pointerToArrayEntry, wishedLength) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
if (wishedLength > metadata.length) {
if (wishedLength > metadata.allocatedLength) {
reallocateArray(externalArgs, carrier, pointerToArrayEntry, wishedLength + externalArgs.arrayAdditionalAllocation, wishedLength);
if (wishedLength > array_length_get(carrier.heap, pointerToArrayEntry)) {
if (wishedLength > array_allocatedLength_get(carrier.heap, pointerToArrayEntry)) {
reallocateArray(carrier, pointerToArrayEntry, wishedLength + externalArgs.arrayAdditionalAllocation, wishedLength);
} else {
// no need to re-allocated, just push the length forward
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: wishedLength
});
array_length_set(carrier.heap, pointerToArrayEntry, wishedLength);
}

@@ -69,42 +57,18 @@ }

export function shrinkArray(externalArgs, carrier, pointerToArrayEntry, wishedLength) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: wishedLength
});
export function shrinkArray(heap, pointerToArrayEntry, wishedLength) {
array_length_set(heap, pointerToArrayEntry, wishedLength);
}
function reallocateArray(externalArgs, carrier, pointerToArrayEntry, newAllocatedLength, newLength) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
const newArrayValueLocation = carrier.allocator.realloc(metadata.value, newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT); // for (
// let memoryToCopyIndex = 0;
// memoryToCopyIndex < metadata.length;
// memoryToCopyIndex += 1
// ) {
// carrier.dataView.setUint32(
// newArrayValueLocation + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT,
// carrier.dataView.getUint32(
// metadata.value + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT
// )
// );
// }
function reallocateArray(carrier, pointerToArrayEntry, newAllocatedLength, newLength) {
const dataspacePointer = array_dataspacePointer_get(carrier.heap, pointerToArrayEntry); // if array was zero length, dataspacePointer was zero
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: newArrayValueLocation,
allocatedLength: newAllocatedLength,
length: newLength
});
const newArrayValueLocation = dataspacePointer !== 0 ? carrier.allocator.realloc(dataspacePointer, newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT) : carrier.allocator.calloc(newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT);
array_set_all(carrier.heap, pointerToArrayEntry, ENTRY_TYPE.ARRAY, array_refsCount_get(carrier.heap, pointerToArrayEntry), newArrayValueLocation, newLength, newAllocatedLength);
}
export function arraySort(externalArgs, globalCarrier, pointerToArrayEntry, sortComparator = defaultCompareFunction) {
const metadata = arrayGetMetadata(globalCarrier, pointerToArrayEntry);
const pointersToValues = [...new Array(metadata.length).keys()].map(index => metadata.value + index * Uint32Array.BYTES_PER_ELEMENT).map(pointerToPointer => globalCarrier.uint32[pointerToPointer / Uint32Array.BYTES_PER_ELEMENT]);
export function arraySort(externalArgs, carrier, pointerToArrayEntry, sortComparator = defaultCompareFunction) {
const arrayDataSpace = array_dataspacePointer_get(carrier.heap, pointerToArrayEntry);
const pointersToValues = [...new Array(array_length_get(carrier.heap, pointerToArrayEntry)).keys()].map(index => arrayDataSpace + index * Uint32Array.BYTES_PER_ELEMENT).map(pointerToPointer => carrier.heap.Uint32Array[pointerToPointer / Uint32Array.BYTES_PER_ELEMENT]);
const sortMe = pointersToValues.map(pointer => {
return [pointer, entryToFinalJavaScriptValue(externalArgs, globalCarrier, pointer)];
return [pointer, entryToFinalJavaScriptValue(externalArgs, carrier, pointer)];
});

@@ -116,3 +80,3 @@ sortMe.sort((a, b) => {

for (let i = 0; i < sortMe.length; i += 1) {
globalCarrier.uint32[(metadata.value + i * Uint32Array.BYTES_PER_ELEMENT) / Uint32Array.BYTES_PER_ELEMENT] = sortMe[i][0];
carrier.heap.Uint32Array[(arrayDataSpace + i * Uint32Array.BYTES_PER_ELEMENT) / Uint32Array.BYTES_PER_ELEMENT] = sortMe[i][0];
}

@@ -144,8 +108,6 @@ } // https://stackoverflow.com/a/47349064/711152

export function arrayReverse(externalArgs, carrier, pointerToArrayEntry) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
export function arrayReverse(carrier, pointerToArrayEntry) {
for (let i = 0; i < Math.floor(array_length_get(carrier.heap, pointerToArrayEntry) / 2); i += 1) {
const theOtherIndex = array_length_get(carrier.heap, pointerToArrayEntry) - i - 1; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
for (let i = 0; i < Math.floor(metadata.length / 2); i += 1) {
const theOtherIndex = metadata.length - i - 1; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const a = arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, i); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion

@@ -152,0 +114,0 @@

import { ExternalArgs, GlobalCarrier } from "./interfaces";
export declare function arraySplice(externalArgs: ExternalArgs, globalCarrier: GlobalCarrier, pointerToArrayEntry: number, startArg: number, deleteCountArg?: number, ...itemsToAddArg: Array<any>): any[];
/**
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#Syntax
this function is not OOM same yet unfortunately,
There's allocations after destructive mutations
*/
export declare function arraySplice(externalArgs: ExternalArgs, carrier: GlobalCarrier, pointerToArrayEntry: number, startArg: number, deleteCountArg?: number, ...itemsToAddArg: Array<any>): any[];
//# sourceMappingURL=arraySplice.d.ts.map

@@ -1,17 +0,25 @@

import { arrayGetMetadata, getFinalValueAtArrayIndex, shrinkArray, extendArrayIfNeeded, arrayGetPointersToValueInIndex, setValuePointerAtArrayIndex } from "./arrayHelpers";
import { getFinalValueAtArrayIndex, shrinkArray, extendArrayIfNeeded, arrayGetPointersToValueInIndex, setValuePointerAtArrayIndex } from "./arrayHelpers";
import { assertNonNull } from "./assertNonNull";
import { writeValueInPtrToPtr } from "./store"; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#Syntax
import { writeValueInPtrToPtr, handleArcForDeletedValuePointer } from "./store";
import { array_length_get } from "./generatedStructs";
/**
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#Syntax
this function is not OOM same yet unfortunately,
There's allocations after destructive mutations
*/
export function arraySplice(externalArgs, globalCarrier, pointerToArrayEntry, startArg, deleteCountArg, ...itemsToAddArg) {
const metadata = arrayGetMetadata(globalCarrier, pointerToArrayEntry);
const calcedStart = calculateSpliceStart(metadata.length, startArg);
const calcedDeleteCount = calculateDeleteCount(metadata.length, calcedStart, deleteCountArg);
const newLength = metadata.length + itemsToAddArg.length - calcedDeleteCount;
extendArrayIfNeeded(externalArgs, globalCarrier, pointerToArrayEntry, newLength);
export function arraySplice(externalArgs, carrier, pointerToArrayEntry, startArg, deleteCountArg, ...itemsToAddArg) {
const arrayLength = array_length_get(carrier.heap, pointerToArrayEntry);
const calcedStart = calculateSpliceStart(arrayLength, startArg);
const calcedDeleteCount = calculateDeleteCount(arrayLength, calcedStart, deleteCountArg);
const newLength = arrayLength + itemsToAddArg.length - calcedDeleteCount;
extendArrayIfNeeded(externalArgs, carrier, pointerToArrayEntry, newLength);
const deletedItemsToReturn = []; // can be negative
const itemCountChange = newLength - metadata.length;
const itemCountChange = newLength - arrayLength;
for (let deletedItemIndexToSave = calcedStart; deletedItemIndexToSave < calcedStart + calcedDeleteCount; deletedItemIndexToSave += 1) {
deletedItemsToReturn.push(getFinalValueAtArrayIndex(externalArgs, globalCarrier, pointerToArrayEntry, deletedItemIndexToSave));
deletedItemsToReturn.push(getFinalValueAtArrayIndex(externalArgs, carrier, pointerToArrayEntry, deletedItemIndexToSave));
handleArcForDeletedValuePointer(carrier, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, deletedItemIndexToSave).pointer);
} // copy-up items

@@ -28,6 +36,6 @@

for (let writeValueToIndex = newLength - 1; writeValueToIndex >= calcedStart + itemCountChange; writeValueToIndex -= 1) {
const valueToCopyPointers = arrayGetPointersToValueInIndex(globalCarrier, pointerToArrayEntry, writeValueToIndex - itemCountChange);
const valueToCopyPointers = arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, writeValueToIndex - itemCountChange);
assertNonNull(valueToCopyPointers);
setValuePointerAtArrayIndex(globalCarrier, pointerToArrayEntry, writeValueToIndex, valueToCopyPointers.pointer);
globalCarrier.uint32[valueToCopyPointers.pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT] = 0;
setValuePointerAtArrayIndex(carrier, pointerToArrayEntry, writeValueToIndex, valueToCopyPointers.pointer);
carrier.heap.Uint32Array[valueToCopyPointers.pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT] = 0;
}

@@ -42,17 +50,6 @@ } // copy-down items

else if (itemCountChange < 0) {
for (let writeValueToIndex = calcedStart + itemsToAddArg.length; writeValueToIndex < metadata.length + itemCountChange; writeValueToIndex += 1) {
const valueToCopyPointers = arrayGetPointersToValueInIndex(globalCarrier, pointerToArrayEntry, writeValueToIndex - itemCountChange);
assertNonNull(valueToCopyPointers);
setValuePointerAtArrayIndex(globalCarrier, pointerToArrayEntry, writeValueToIndex, valueToCopyPointers.pointer); // empty old array index, its still allocated!
globalCarrier.uint32[valueToCopyPointers.pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT] = 0; // using that is wastefull
// setValueAtArrayIndex(
// dataView,
// textDecoder,
// textEncoder,
// arrayAdditionalAllocation,
// pointerToArrayEntry,
// writeValueToIndex + calcedDeleteCount,
// undefined
// );
for (let writeValueToIndex = calcedStart + itemsToAddArg.length; writeValueToIndex < arrayLength + itemCountChange; writeValueToIndex += 1) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const valueToCopyPointers = arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, writeValueToIndex - itemCountChange);
setValuePointerAtArrayIndex(carrier, pointerToArrayEntry, writeValueToIndex, valueToCopyPointers.pointer);
}

@@ -62,9 +59,9 @@ }

for (let i = 0; i < itemsToAddArg.length; i += 1) {
const valueToSetPointers = arrayGetPointersToValueInIndex(globalCarrier, pointerToArrayEntry, calcedStart + i);
const valueToSetPointers = arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, calcedStart + i);
assertNonNull(valueToSetPointers);
writeValueInPtrToPtr(externalArgs, globalCarrier, valueToSetPointers.pointerToThePointer, itemsToAddArg[i]);
writeValueInPtrToPtr(externalArgs, carrier, valueToSetPointers.pointerToThePointer, itemsToAddArg[i]);
}
if (newLength < metadata.length) {
shrinkArray(externalArgs, globalCarrier, pointerToArrayEntry, newLength);
if (newLength < arrayLength) {
shrinkArray(carrier.heap, pointerToArrayEntry, newLength);
}

@@ -81,3 +78,3 @@

if (deleteCountArg === undefined || deleteCountArg >= arrayLength - start) {
return arrayLength - start;
return Math.min(arrayLength, arrayLength - start);
}

@@ -89,3 +86,3 @@

return deleteCountArg;
return Math.min(arrayLength, deleteCountArg);
}

@@ -1,9 +0,9 @@

import { ExternalArgs, GlobalCarrier, ArrayEntry } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { BaseProxyTrap } from "./BaseProxyTrap";
export declare class ArrayWrapper extends BaseProxyTrap<ArrayEntry> implements ProxyHandler<{}> {
get(target: {}, p: PropertyKey): any;
deleteProperty(target: {}, p: PropertyKey): boolean;
export declare class ArrayWrapper extends BaseProxyTrap implements ProxyHandler<Record<string, unknown>> {
get(target: Record<string, unknown>, p: PropertyKey): any;
deleteProperty(target: Record<string, unknown>, p: PropertyKey): boolean;
enumerate(): PropertyKey[];
ownKeys(): PropertyKey[];
getOwnPropertyDescriptor(target: {}, prop: any): {
getOwnPropertyDescriptor(target: Record<string, unknown>, prop: any): {
configurable: boolean;

@@ -17,4 +17,4 @@ enumerable: boolean;

} | undefined;
has(target: {}, p: PropertyKey): boolean;
set(target: {}, accessedProp: PropertyKey, value: any): boolean;
has(target: Record<string, unknown>, p: PropertyKey): boolean;
set(target: Record<string, unknown>, accessedProp: PropertyKey, value: any): boolean;
entries(): Iterable<[number, any]>;

@@ -21,0 +21,0 @@ keys(): Iterable<number>;

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

import { getFinalValueAtArrayIndex, arrayGetMetadata, setValueAtArrayIndex, arraySort, extendArrayIfNeeded, arrayReverse } from "./arrayHelpers";
import { getFinalValueAtArrayIndex, setValueAtArrayIndex, arraySort, extendArrayIfNeeded, arrayReverse } from "./arrayHelpers";
import { INTERNAL_API_SYMBOL } from "./symbols";

@@ -7,2 +7,3 @@ import { arraySplice } from "./arraySplice";

import { BaseProxyTrap } from "./BaseProxyTrap";
import { array_length_get } from "./generatedStructs";
export class ArrayWrapper extends BaseProxyTrap {

@@ -15,4 +16,4 @@ get(target, p) {

if (p in this && p !== "constructor") {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return this[p];

@@ -22,3 +23,3 @@ }

if (p === "length") {
return arrayGetMetadata(this.carrier, this.entryPointer).length;
return array_length_get(this.carrier.heap, this.entryPointer);
}

@@ -32,4 +33,4 @@

}
} // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
} // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error

@@ -50,3 +51,3 @@

ownKeys() {
const length = arrayGetMetadata(this.carrier, this.entryPointer).length;
const length = array_length_get(this.carrier.heap, this.entryPointer);
return [...new Array(length).keys(), "length"];

@@ -79,3 +80,3 @@ }

const length = arrayGetMetadata(this.carrier, this.entryPointer).length;
const length = array_length_get(this.carrier.heap, this.entryPointer);

@@ -101,3 +102,3 @@ if (typeof p === "number") {

const currentLength = arrayGetMetadata(this.carrier, this.entryPointer).length;
const currentLength = array_length_get(this.carrier.heap, this.entryPointer);

@@ -139,3 +140,3 @@ if (currentLength === value) {

index += 1;
length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -151,3 +152,3 @@ }

index += 1;
length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -163,3 +164,3 @@ }

index += 1;
length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -177,7 +178,9 @@ }

splice(start, deleteCount, ...items) {
return arraySplice(this.externalArgs, this.carrier, this.entryPointer, start, deleteCount, ...items);
return allocationsTransaction(() => {
return arraySplice(this.externalArgs, this.carrier, this.entryPointer, start, deleteCount, ...items);
}, this.carrier.allocator);
}
reverse() {
arrayReverse(this.externalArgs, this.carrier, this.entryPointer);
arrayReverse(this.carrier, this.entryPointer);
return this;

@@ -196,3 +199,3 @@ } // no copy inside array is needed, so we can live with the built-in impl

this.splice(0, 0, ...elements);
return arrayGetMetadata(this.carrier, this.entryPointer).length;
return array_length_get(this.carrier.heap, this.entryPointer);
} // public getDataView() {

@@ -233,3 +236,5 @@ // return this.carrier.dataView;

export function createArrayWrapper(externalArgs, globalCarrier, entryPointer) {
return new Proxy([], new ArrayWrapper(externalArgs, globalCarrier, entryPointer));
return new Proxy( // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
[], new ArrayWrapper(externalArgs, globalCarrier, entryPointer));
}

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

import { ExternalArgs, GlobalCarrier, InternalAPI, DateEntry, ArrayEntry, ObjectEntry, MapEntry, SetEntry } from "./interfaces";
export declare class BaseProxyTrap<T extends ObjectEntry | DateEntry | ArrayEntry | MapEntry | SetEntry> implements InternalAPI {
import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
export declare abstract class BaseProxyTrap implements InternalAPI {
protected externalArgs: ExternalArgs;

@@ -17,4 +17,3 @@ protected carrier: GlobalCarrier;

protected get entryPointer(): number;
protected get entry(): T;
}
//# sourceMappingURL=BaseProxyTrap.d.ts.map

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

import { incrementRefCount, decrementRefCount, readEntry } from "./store";
import { incrementRefCount, decrementRefCount } from "./store";
import { WrapperDestroyed } from "./exceptions";

@@ -8,7 +8,7 @@ export class BaseProxyTrap {

this._entryPointer = _entryPointer;
incrementRefCount(this.externalArgs, this.carrier, this.entryPointer);
incrementRefCount(this.carrier.heap, this.entryPointer);
}
destroy() {
const newRefCount = decrementRefCount(this.externalArgs, this.carrier, this.entryPointer);
const newRefCount = decrementRefCount(this.carrier.heap, this.entryPointer);
this._entryPointer = 0;

@@ -42,6 +42,2 @@ return newRefCount;

get entry() {
return readEntry(this.carrier, this.entryPointer);
}
}

@@ -9,2 +9,3 @@ export declare const LOCK_OFFSET = 0;

export declare const FALSE_KNOWN_ADDRESS = 3;
export declare const MAX_64_BIG_INT: bigint;
//# sourceMappingURL=consts.d.ts.map

@@ -8,2 +8,3 @@ export const LOCK_OFFSET = 0;

export const TRUE_KNOWN_ADDRESS = 2;
export const FALSE_KNOWN_ADDRESS = 3;
export const FALSE_KNOWN_ADDRESS = 3;
export const MAX_64_BIG_INT = BigInt("0xFFFFFFFFFFFFFFFF");

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

import { ExternalArgs, GlobalCarrier, DateEntry } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { BaseProxyTrap } from "./BaseProxyTrap";
export declare class DateWrapper extends BaseProxyTrap<DateEntry> implements ProxyHandler<Date> {
export declare class DateWrapper extends BaseProxyTrap implements ProxyHandler<Date> {
private dateObjectForReuse;

@@ -5,0 +5,0 @@ private useMeToGiveNamesToFunctionsAndCacheThem;

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

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

@@ -6,2 +5,3 @@ import { INTERNAL_API_SYMBOL } from "./symbols";

import { BaseProxyTrap } from "./BaseProxyTrap";
import { date_set_all, date_refsCount_get, date_timestamp_get } from "./generatedStructs";
const getFunctions = ["toString", "toDateString", "toTimeString", "toISOString", "toUTCString", // "toGMTString",

@@ -50,12 +50,8 @@ "getDate", "getDay", "getFullYear", "getHours", "getMilliseconds", "getMinutes", "getMonth", "getSeconds", "getTime", "getTimezoneOffset", "getUTCDate", "getUTCDay", "getUTCFullYear", "getUTCHours", "getUTCMilliseconds", "getUTCMinutes", "getUTCMonth", "getUTCSeconds", // "getYear",

updateDateObjectForReuse() {
const entry = readEntry(this.carrier, this.entryPointer);
this.dateObjectForReuse.setTime(entry.value);
this.dateObjectForReuse.setTime(date_timestamp_get(this.carrier.heap, this.entryPointer));
}
persistDateObject() {
writeEntry(this.carrier, this.entryPointer, {
type: ENTRY_TYPE.DATE,
refsCount: this.entry.refsCount,
value: this.dateObjectForReuse.getTime()
});
date_set_all(this.carrier.heap, this.entryPointer, ENTRY_TYPE.DATE, date_refsCount_get(this.carrier.heap, this.entryPointer), // padding
0, this.dateObjectForReuse.getTime());
}

@@ -62,0 +58,0 @@

@@ -18,9 +18,13 @@ import { getInternalAPI } from "./utils";

const addressesToFree = getAllLinkedAddresses(internalApi.getCarrier(), false, entryPointer);
const {
allocator,
heap
} = internalApi.getCarrier();
for (const address of addressesToFree.leafAddresses) {
internalApi.getCarrier().allocator.free(address);
allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(internalApi.getExternalArgs(), internalApi.getCarrier(), address);
decrementRefCount(heap, address);
}

@@ -27,0 +31,0 @@

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

import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { ENTRY_TYPE } from "./entry-types";
import { createObjectWrapper } from "./objectWrapper";

@@ -6,9 +6,9 @@ import { createArrayWrapper } from "./arrayWrapper";

import { getCacheFor } from "./externalObjectsCache";
import { decrementRefCount, readEntry } from "./store";
import { decrementRefCount } from "./store";
import { getAllLinkedAddresses } from "./getAllLinkedAddresses";
import { createMapWrapper } from "./mapWrapper";
import { createSetWrapper } from "./setWrapper";
import { UNDEFINED_KNOWN_ADDRESS, NULL_KNOWN_ADDRESS, TRUE_KNOWN_ADDRESS, FALSE_KNOWN_ADDRESS } from "./consts"; // declare const FinalizationGroup: any;
// declare const WeakRef: any;
import { UNDEFINED_KNOWN_ADDRESS, NULL_KNOWN_ADDRESS, TRUE_KNOWN_ADDRESS, FALSE_KNOWN_ADDRESS } from "./consts";
import { typeOnly_type_get, number_value_get, bigint_value_get } from "./generatedStructs";
import { readString } from "./readString";
const TYPE_TO_FACTORY = {

@@ -38,29 +38,44 @@ [ENTRY_TYPE.OBJECT]: createObjectWrapper,

const valueEntry = readEntry(carrier, pointerToEntry);
const entryType = typeOnly_type_get(carrier.heap, pointerToEntry);
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
}
switch (entryType) {
case ENTRY_TYPE.NUMBER:
return number_value_get(carrier.heap, pointerToEntry);
break;
if (valueEntry.type === ENTRY_TYPE.OBJECT || valueEntry.type === ENTRY_TYPE.DATE || valueEntry.type === ENTRY_TYPE.ARRAY || valueEntry.type === ENTRY_TYPE.MAP || valueEntry.type === ENTRY_TYPE.SET) {
const cache = getCacheFor(carrier, key => {
finalizer(key, carrier, externalArgs);
});
let ret = cache.get(pointerToEntry);
case ENTRY_TYPE.STRING:
return readString(carrier.heap, pointerToEntry);
break;
if (!ret) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
ret = TYPE_TO_FACTORY[valueEntry.type](externalArgs, carrier, pointerToEntry);
cache.set(pointerToEntry, ret);
}
case ENTRY_TYPE.BIGINT_POSITIVE:
return bigint_value_get(carrier.heap, pointerToEntry);
break;
return ret;
case ENTRY_TYPE.BIGINT_NEGATIVE:
return bigint_value_get(carrier.heap, pointerToEntry) * BigInt("-1");
break;
} // this is an invariant
if (!(entryType === ENTRY_TYPE.OBJECT || entryType === ENTRY_TYPE.DATE || entryType === ENTRY_TYPE.ARRAY || entryType === ENTRY_TYPE.MAP || entryType === ENTRY_TYPE.SET)) {
throw new Error("Nope Nope Nope");
}
throw new Error("unsupported yet");
const cache = getCacheFor(carrier, key => {
finalizer(key, carrier);
});
let ret = cache.get(pointerToEntry);
if (!ret) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ret = TYPE_TO_FACTORY[entryType](externalArgs, carrier, pointerToEntry);
cache.set(pointerToEntry, ret);
}
return ret;
}
function finalizer(memoryAddress, carrier, externalArgs) {
const newRefsCount = decrementRefCount(externalArgs, carrier, memoryAddress);
function finalizer(memoryAddress, carrier) {
const newRefsCount = decrementRefCount(carrier.heap, memoryAddress);

@@ -75,5 +90,5 @@ if (newRefsCount === 0) {

for (const address of freeUs.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
decrementRefCount(carrier.heap, address);
}
}
}

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

import { WeakValueMap } from "./WeakValueMap";
import { WeakValueMap } from "./WeakValueMap"; // eslint-disable-next-line @typescript-eslint/ban-types
const externalObjectsCache = new WeakMap();
export function getCacheFor(obj, externalFinalizer) {
export function getCacheFor( // eslint-disable-next-line @typescript-eslint/ban-types
obj, externalFinalizer) {
let map = externalObjectsCache.get(obj);

@@ -5,0 +7,0 @@

@@ -1,5 +0,5 @@

import { readEntry } from "./store";
import { ENTRY_TYPE } from "./entry-types";
import { hashMapGetPointersToFree } from "./hashmap/hashmap";
import { isKnownAddressValuePointer } from "./utils";
import { typeOnly_type_get, string_charsPointer_get, typeAndRc_refsCount_get, object_pointerToHashMap_get, array_dataspacePointer_get, array_length_get } from "./generatedStructs";
export function getAllLinkedAddresses(carrier, ignoreRefCount, entryPointer) {

@@ -28,2 +28,6 @@ const leafAddresses = new Set();

function getAllLinkedAddressesStep(carrier, ignoreRefCount, entryPointer, leafAddresses, arcAddresses, addressesToProcessQueue) {
const {
heap
} = carrier;
if (isKnownAddressValuePointer(entryPointer) || leafAddresses.has(entryPointer) || arcAddresses.has(entryPointer)) {

@@ -33,7 +37,8 @@ return;

const entry = readEntry(carrier, entryPointer);
const entryType = typeOnly_type_get(heap, entryPointer); // to be used ONLY if the type has ref counter
switch (entry.type) {
const refsCount = typeAndRc_refsCount_get(heap, entryPointer);
switch (entryType) {
case ENTRY_TYPE.NUMBER:
case ENTRY_TYPE.STRING:
case ENTRY_TYPE.BIGINT_NEGATIVE:

@@ -44,8 +49,13 @@ case ENTRY_TYPE.BIGINT_POSITIVE:

case ENTRY_TYPE.STRING:
leafAddresses.add(string_charsPointer_get(heap, entryPointer));
leafAddresses.add(entryPointer);
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.MAP:
case ENTRY_TYPE.SET:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);
getObjectOrMapOrSetAddresses(carrier, entry.value, leafAddresses, addressesToProcessQueue);
getObjectOrMapOrSetAddresses(carrier, object_pointerToHashMap_get(heap, entryPointer), leafAddresses, addressesToProcessQueue);
} else {

@@ -58,8 +68,9 @@ arcAddresses.add(entryPointer);

case ENTRY_TYPE.ARRAY:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);
leafAddresses.add(entry.value);
leafAddresses.add(array_dataspacePointer_get(heap, entryPointer));
const arrayLength = array_length_get(heap, entryPointer);
for (let i = 0; i < entry.allocatedLength; i += 1) {
const valuePointer = carrier.uint32[(entry.value + i * Uint32Array.BYTES_PER_ELEMENT) / Uint32Array.BYTES_PER_ELEMENT];
for (let i = 0; i < arrayLength; i += 1) {
const valuePointer = carrier.uint32[(array_dataspacePointer_get(heap, entryPointer) + i * Uint32Array.BYTES_PER_ELEMENT) / Uint32Array.BYTES_PER_ELEMENT];
addressesToProcessQueue.push(valuePointer);

@@ -74,3 +85,3 @@ }

case ENTRY_TYPE.DATE:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);

@@ -84,5 +95,3 @@ } else {

default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");
throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");
}

@@ -89,0 +98,0 @@ }

import { MAP_MACHINE, NODE_MACHINE } from "./memoryLayout";
import { hashCodeInPlace, hashCodeExternalValue, getKeyStartLength } from "./hashmapUtils";
import { primitiveValueToEntry } from "../utils";
import { sizeOfEntry, writeEntry, readEntry, compareStringOrNumberEntriesInPlace } from "../store";
import { strByteLength } from "../utils";
import { stringEncodeInto } from "../stringEncodeInto";
import { compareStringOrNumberEntriesInPlace, readNumberOrString } from "../store";
import { ENTRY_TYPE } from "../entry-types";
import { initLinkedList, linkedListItemInsert, linkedListItemRemove, linkedListLowLevelIterator, linkedListGetValue, linkedListGetPointersToFree } from "../linkedList/linkedList";
import { number_size, string_size, number_set_all, string_set_all, number_value_place, number_value_ctor, typeOnly_type_get, string_charsPointer_get } from "../generatedStructs";
export function createHashMap(carrier,

@@ -28,19 +30,31 @@ /**

export function hashMapInsertUpdate(externalArgs, carrier, mapPointer, externalKeyValue) {
const mapOperator = MAP_MACHINE.createOperator(carrier, mapPointer);
const keyEntry = primitiveValueToEntry(externalKeyValue); // allocate all possible needed memory upfront, so we won't oom in the middle of something
const mapOperator = MAP_MACHINE.createOperator(carrier, mapPointer); // const keyEntry = primitiveValueToEntry(externalKeyValue) as
// | NumberEntry
// | StringEntry;
// allocate all possible needed memory upfront, so we won't oom in the middle of something
// in case of overwrite, we will not need this memory
const memoryForNewNode = carrier.allocator.calloc(NODE_MACHINE.map.SIZE_OF);
const memorySizeOfKey = sizeOfEntry(keyEntry);
const keyEntryMemory = carrier.allocator.calloc(memorySizeOfKey);
writeEntry(carrier, keyEntryMemory, keyEntry);
const keyHeaderOverhead = keyEntry.type === ENTRY_TYPE.STRING ? // type + string length
8 + 4 : // type
8;
const keyHashCode = hashCodeInPlace(carrier.uint8, mapOperator.get("CAPACITY"), // + 1 for the type of key
keyEntryMemory + keyHeaderOverhead, memorySizeOfKey - keyHeaderOverhead);
let keyMemoryEntryPointer;
let keyDataMemoryStart;
let keyDataMemoryLength;
if (typeof externalKeyValue === "number") {
keyMemoryEntryPointer = carrier.allocator.calloc(number_size);
number_set_all(carrier.heap, keyMemoryEntryPointer, ENTRY_TYPE.NUMBER, externalKeyValue);
keyDataMemoryStart = keyMemoryEntryPointer + number_value_place;
keyDataMemoryLength = number_value_ctor.BYTES_PER_ELEMENT;
} else {
keyMemoryEntryPointer = carrier.allocator.calloc(string_size);
keyDataMemoryLength = strByteLength(externalKeyValue);
keyDataMemoryStart = carrier.allocator.calloc(keyDataMemoryLength);
stringEncodeInto(carrier.heap.Uint8Array, keyDataMemoryStart, externalKeyValue);
string_set_all(carrier.heap, keyMemoryEntryPointer, ENTRY_TYPE.STRING, keyDataMemoryLength, keyDataMemoryStart);
}
const keyHashCode = hashCodeInPlace(carrier.uint8, mapOperator.get("CAPACITY"), keyDataMemoryStart, keyDataMemoryLength);
let ptrToPtrToSaveTheNodeTo = mapOperator.get("ARRAY_POINTER") + keyHashCode * Uint32Array.BYTES_PER_ELEMENT;
const commonNodeOperator = NODE_MACHINE.createOperator(carrier, carrier.uint32[ptrToPtrToSaveTheNodeTo / Uint32Array.BYTES_PER_ELEMENT]); // todo: share code with hashMapNodeLookup?
while (commonNodeOperator.startAddress !== 0 && !compareStringOrNumberEntriesInPlace(carrier, commonNodeOperator.get("KEY_POINTER"), keyEntryMemory)) {
while (commonNodeOperator.startAddress !== 0 && !compareStringOrNumberEntriesInPlace(carrier.heap, commonNodeOperator.get("KEY_POINTER"), keyMemoryEntryPointer)) {
ptrToPtrToSaveTheNodeTo = commonNodeOperator.pointerTo("NEXT_NODE_POINTER");

@@ -58,3 +72,4 @@ commonNodeOperator.startAddress = commonNodeOperator.get("NEXT_NODE_POINTER");

// we don't need the new memory
carrier.allocator.free(keyEntryMemory);
// @todo Free here also the string data
carrier.allocator.free(keyMemoryEntryPointer);
carrier.allocator.free(memoryForNewNode);

@@ -64,3 +79,3 @@ return commonNodeOperator.pointerTo("VALUE_POINTER");

commonNodeOperator.startAddress = memoryForNewNode;
commonNodeOperator.set("KEY_POINTER", keyEntryMemory);
commonNodeOperator.set("KEY_POINTER", keyMemoryEntryPointer);
commonNodeOperator.set("LINKED_LIST_ITEM_POINTER", linkedListItemInsert(carrier, mapOperator.get("LINKED_LIST_POINTER"), memoryForNewNode));

@@ -70,3 +85,3 @@ carrier.uint32[ptrToPtrToSaveTheNodeTo / Uint32Array.BYTES_PER_ELEMENT] = memoryForNewNode;

if (shouldRehash(mapOperator.get("LINKED_LIST_SIZE"), mapOperator.get("CAPACITY"), mapOperator.get("USED_CAPACITY"), externalArgs.hashMapLoadFactor)) {
if (shouldRehash(mapOperator.get("CAPACITY"), mapOperator.get("USED_CAPACITY"), externalArgs.hashMapLoadFactor)) {
// console.log("rehash", {

@@ -92,5 +107,5 @@ // USED_CAPACITY: mapOperator.get("USED_CAPACITY")

while (node.startAddress !== 0) {
const keyEntry = readEntry(carrier, node.get("KEY_POINTER"));
const keyValue = readNumberOrString(carrier.heap, node.get("KEY_POINTER"));
if (keyEntry.value === externalKeyValue) {
if (keyValue === externalKeyValue) {
return ptrToPtr;

@@ -132,2 +147,7 @@ }

carrier.uint32[foundNodePtrToPtr / Uint32Array.BYTES_PER_ELEMENT] = nodeOperator.get("NEXT_NODE_POINTER");
if (typeOnly_type_get(carrier.heap, nodeOperator.get("KEY_POINTER")) === ENTRY_TYPE.STRING) {
carrier.allocator.free(string_charsPointer_get(carrier.heap, nodeOperator.get("KEY_POINTER")));
}
carrier.allocator.free(nodeOperator.get("KEY_POINTER"));

@@ -180,2 +200,7 @@ carrier.allocator.free(nodeOperator.startAddress);

pointersToValuePointers.push(nodeOperator.pointerTo("VALUE_POINTER"));
if (typeOnly_type_get(carrier.heap, nodeOperator.get("KEY_POINTER")) === ENTRY_TYPE.STRING) {
pointers.push(string_charsPointer_get(carrier.heap, nodeOperator.get("KEY_POINTER")));
}
pointers.push(nodePointer, nodeOperator.get("KEY_POINTER"));

@@ -237,3 +262,3 @@ }

function shouldRehash(nodesCount, buckets, fullBuckets, loadFactor) {
function shouldRehash(buckets, fullBuckets, loadFactor) {
// add proportion check?

@@ -240,0 +265,0 @@ // nodesCount

import { ENTRY_TYPE } from "./entry-types";
import { Heap } from "../structsGenerator/consts";
export declare type primitive = string | number | bigint | boolean | undefined | null;

@@ -67,2 +68,3 @@ export declare type Entry = StringEntry | NumberEntry | BigIntPositiveEntry | BigIntNegativeEntry | ObjectEntry | ArrayEntry | DateEntry | MapEntry | SetEntry;

allocator: import("@thi.ng/malloc").IMemPool;
heap: Heap;
}

@@ -69,0 +71,0 @@ export declare type ExternalArgs = Readonly<{

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

/* istanbul ignore file */
// I'm not sure how to test that yet
import { invariant } from "./utils";

@@ -2,0 +4,0 @@ import { getUnderlyingArrayBuffer } from "./api";

@@ -1,5 +0,5 @@

import { ExternalArgs, GlobalCarrier, MapEntry, InternalAPI } from "./interfaces";
import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
import { INTERNAL_API_SYMBOL } from "./symbols";
import { BaseProxyTrap } from "./BaseProxyTrap";
export declare class MapWrapper<K extends string | number, V> extends BaseProxyTrap<MapEntry> implements Map<K, V> {
export declare class MapWrapper<K extends string | number, V> extends BaseProxyTrap implements Map<K, V> {
clear(): void;

@@ -6,0 +6,0 @@ forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;

@@ -7,2 +7,3 @@ import { deleteObjectPropertyEntryByKey, objectGet, objectSet, mapOrSetClear } from "./objectWrapperHelpers";

import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class MapWrapper extends BaseProxyTrap {

@@ -20,3 +21,3 @@ clear() {

get size() {
return hashMapSize(this.carrier, this.entry.value);
return hashMapSize(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer));
}

@@ -29,3 +30,3 @@

*entries() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const {

@@ -40,3 +41,3 @@ valuePointer,

*keys() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

@@ -48,3 +49,3 @@ yield entryToFinalJavaScriptValue(this.externalArgs, this.carrier, t.keyPointer);

*values() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const {

@@ -74,3 +75,3 @@ valuePointer

return objectGet(this.externalArgs, this.carrier, this.entry.value, p);
return objectGet(this.externalArgs, this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p);
}

@@ -83,3 +84,3 @@

return deleteObjectPropertyEntryByKey(this.externalArgs, this.carrier, this.entry.value, p);
return deleteObjectPropertyEntryByKey(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p);
}

@@ -92,3 +93,3 @@

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return hashMapNodeLookup(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p) !== 0;
}

@@ -102,3 +103,3 @@

allocationsTransaction(() => {
objectSet(this.externalArgs, this.carrier, this.entry.value, p, value);
objectSet(this.externalArgs, this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p, value);
}, this.carrier.allocator);

@@ -105,0 +106,0 @@ return this;

@@ -12,5 +12,3 @@ const ALLOWS_TYPED_ARRAYS_CTORS = [Uint8Array, Uint32Array, // BigUint64Array,

const READ_WRITE_MAPS_V2 = [[Uint8Array, "uint8"], [Uint32Array, "uint32"], // [BigUint64Array, dataViewInstance.getBigUint64, dataViewInstance.setBigUint64],
[Uint16Array, "uint16"]]; // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// dataViewInstance = undefined;
[Uint16Array, "uint16"]]; // dataViewInstance = undefined;
// const READ_MAP = new Map(READ_WRITE_MAPS.map(e => [e[0], e[1]]));

@@ -89,6 +87,6 @@ // const WRITE_MAP = new Map(READ_WRITE_MAPS.map(e => [e[0], e[2]]));

newObjectEntries.push(["TOTAL_SIZE", newObjectEntries[newObjectEntries.length - 1][1] + oldEntries[newObjectEntries.length - 1][1]]); // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
newObjectEntries.push(["TOTAL_SIZE", newObjectEntries[newObjectEntries.length - 1][1] + oldEntries[newObjectEntries.length - 1][1]]); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return Object.fromEntries(newObjectEntries);
}

@@ -1,14 +0,14 @@

import { ObjectEntry, ExternalArgs, GlobalCarrier } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { BaseProxyTrap } from "./BaseProxyTrap";
export declare class ObjectWrapper extends BaseProxyTrap<ObjectEntry> implements ProxyHandler<{}> {
get(target: {}, p: PropertyKey): any;
deleteProperty(target: {}, p: PropertyKey): boolean;
export declare class ObjectWrapper extends BaseProxyTrap implements ProxyHandler<Record<string, unknown>> {
get(target: Record<string, unknown>, p: PropertyKey): any;
deleteProperty(target: Record<string, unknown>, p: PropertyKey): boolean;
enumerate(): PropertyKey[];
ownKeys(): PropertyKey[];
getOwnPropertyDescriptor(target: {}, p: PropertyKey): {
getOwnPropertyDescriptor(target: Record<string, unknown>, p: PropertyKey): {
configurable: boolean;
enumerable: boolean;
} | undefined;
has(target: {}, p: PropertyKey): boolean;
set(target: {}, p: PropertyKey, value: any): boolean;
has(target: Record<string, unknown>, p: PropertyKey): boolean;
set(target: Record<string, unknown>, p: PropertyKey, value: any): boolean;
isExtensible(): boolean;

@@ -15,0 +15,0 @@ preventExtensions(): boolean;

@@ -7,2 +7,3 @@ import { getObjectPropertiesEntries, deleteObjectPropertyEntryByKey, objectGet, objectSet } from "./objectWrapperHelpers";

import { hashMapNodeLookup } from "./hashmap/hashmap";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class ObjectWrapper extends BaseProxyTrap {

@@ -18,3 +19,3 @@ get(target, p) {

return objectGet(this.externalArgs, this.carrier, this.entry.value, p);
return objectGet(this.externalArgs, this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p);
}

@@ -27,7 +28,7 @@

return deleteObjectPropertyEntryByKey(this.externalArgs, this.carrier, this.entry.value, p);
return deleteObjectPropertyEntryByKey(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p);
}
enumerate() {
const gotEntries = getObjectPropertiesEntries(this.carrier, this.entry.value);
const gotEntries = getObjectPropertiesEntries(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer));
return gotEntries.map(e => e.key);

@@ -37,3 +38,3 @@ }

ownKeys() {
const gotEntries = getObjectPropertiesEntries(this.carrier, this.entry.value);
const gotEntries = getObjectPropertiesEntries(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer));
return gotEntries.map(e => e.key);

@@ -62,3 +63,3 @@ }

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return hashMapNodeLookup(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p) !== 0;
}

@@ -72,3 +73,3 @@

allocationsTransaction(() => {
objectSet(this.externalArgs, this.carrier, this.entry.value, p, value);
objectSet(this.externalArgs, this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p, value);
}, this.carrier.allocator);

@@ -75,0 +76,0 @@ return true;

import { ExternalArgs, GlobalCarrier } from "./interfaces";
export declare function deleteObjectPropertyEntryByKey(externalArgs: ExternalArgs, carrier: GlobalCarrier, hashmapPointer: number, keyToDeleteBy: string | number): boolean;
export declare function deleteObjectPropertyEntryByKey(carrier: GlobalCarrier, hashmapPointer: number, keyToDeleteBy: string | number): boolean;
export declare function getObjectPropertiesEntries(carrier: GlobalCarrier, hashmapPointer: number): Array<{

@@ -7,5 +7,5 @@ key: string | number;

}>;
export declare function objectSet(externalArgs: ExternalArgs, carrier: GlobalCarrier, hashMapPointer: number, p: string | number, value: any): void;
export declare function objectSet(externalArgs: ExternalArgs, carrier: GlobalCarrier, hashMapPointer: number, p: string | number, value: unknown): void;
export declare function objectGet(externalArgs: ExternalArgs, carrier: GlobalCarrier, entryPointer: number, key: string | number): any;
export declare function mapOrSetClear(externalArgs: ExternalArgs, carrier: GlobalCarrier, mapOrSetPtr: number): void;
//# sourceMappingURL=objectWrapperHelpers.d.ts.map

@@ -1,6 +0,9 @@

import { readEntry, writeValueInPtrToPtrAndHandleMemory, handleArcForDeletedValuePointer, decrementRefCount, writeEntry, setRefCount } from "./store";
import { writeValueInPtrToPtrAndHandleMemory, handleArcForDeletedValuePointer, decrementRefCount } from "./store";
import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { hashMapDelete, hashMapLowLevelIterator, hashMapNodePointerToKeyValue, hashMapInsertUpdate, hashMapValueLookup, createHashMap } from "./hashmap/hashmap";
import { getAllLinkedAddresses } from "./getAllLinkedAddresses";
export function deleteObjectPropertyEntryByKey(externalArgs, carrier, hashmapPointer, keyToDeleteBy) {
import { typeOnly_type_get, number_value_get, typeAndRc_refsCount_get, typeAndRc_refsCount_set, object_pointerToHashMap_set } from "./generatedStructs";
import { ENTRY_TYPE } from "./entry-types";
import { readString } from "./readString";
export function deleteObjectPropertyEntryByKey(carrier, hashmapPointer, keyToDeleteBy) {
const deletedValuePointerToPointer = hashMapDelete(carrier, hashmapPointer, keyToDeleteBy); // no such key

@@ -12,4 +15,4 @@

const deletedValuePointer = carrier.uint32[deletedValuePointerToPointer / Uint32Array.BYTES_PER_ELEMENT];
handleArcForDeletedValuePointer(externalArgs, carrier, deletedValuePointer);
const deletedValuePointer = carrier.heap.Uint32Array[deletedValuePointerToPointer / Uint32Array.BYTES_PER_ELEMENT];
handleArcForDeletedValuePointer(carrier, deletedValuePointer);
return true;

@@ -26,6 +29,7 @@ }

} = hashMapNodePointerToKeyValue(carrier, iterator);
const keyEntry = readEntry(carrier, keyPointer);
const typeOfKeyEntry = typeOnly_type_get(carrier.heap, keyPointer);
const key = typeOfKeyEntry === ENTRY_TYPE.NUMBER ? number_value_get(carrier.heap, keyPointer) : readString(carrier.heap, keyPointer);
foundValues.push({
valuePointer: carrier.uint32[valuePointer / Uint32Array.BYTES_PER_ELEMENT],
key: keyEntry.value
key
});

@@ -42,7 +46,2 @@ }

const valuePointer = hashMapValueLookup(carrier, entryPointer, key);
if (valuePointer === 0) {
return undefined;
}
return entryToFinalJavaScriptValue(externalArgs, carrier, carrier.uint32[valuePointer / Uint32Array.BYTES_PER_ELEMENT]);

@@ -71,5 +70,5 @@ } // export function hashmapClearFree(

export function mapOrSetClear(externalArgs, carrier, mapOrSetPtr) {
const entry = readEntry(carrier, mapOrSetPtr); // we fake the entry refCount as zero so getAllLinkedAddresses will visit what's needed
const prevCount = setRefCount(carrier, mapOrSetPtr, 0);
// we fake the entry refCount as zero so getAllLinkedAddresses will visit what's needed
const prevCount = typeAndRc_refsCount_get(carrier.heap, mapOrSetPtr);
typeAndRc_refsCount_set(carrier.heap, mapOrSetPtr, 0);
const {

@@ -95,10 +94,8 @@ leafAddresses,

decrementRefCount(externalArgs, carrier, address);
} // hashmapClearFree(externalArgs, carrier, entry.value);
// Restore real ref count
decrementRefCount(carrier.heap, address);
} // Restore real ref count
setRefCount(carrier, mapOrSetPtr, prevCount);
entry.value = createHashMap(carrier, externalArgs.hashMapMinInitialCapacity);
writeEntry(carrier, mapOrSetPtr, entry);
typeAndRc_refsCount_set(carrier.heap, mapOrSetPtr, prevCount);
object_pointerToHashMap_set(carrier.heap, mapOrSetPtr, createHashMap(carrier, externalArgs.hashMapMinInitialCapacity));
}
import { ExternalArgs, GlobalCarrier } from "./interfaces";
/**
* Returns pointer for the value
*/
export declare function saveValue(externalArgs: ExternalArgs, carrier: GlobalCarrier, referencedPointers: number[], visitedValuesOnCurrentSaveOperation: Map<object, number>, value: any): number;
export declare function saveValueIterative(externalArgs: ExternalArgs, carrier: GlobalCarrier, referencedExistingPointers: number[], initialValuePtrToPtr: number, initialValue: unknown): void;
//# sourceMappingURL=saveValue.d.ts.map

@@ -1,63 +0,130 @@

import { primitiveValueToEntry, isPrimitive, getOurPointerIfApplicable } from "./utils";
import { appendEntry } from "./store";
import { objectSaver, mapSaver, setSaver } from "./objectSaver";
import { arraySaver } from "./arraySaver";
import { getOurPointerIfApplicable, strByteLength } from "./utils";
import { ENTRY_TYPE } from "./entry-types";
import { UNDEFINED_KNOWN_ADDRESS, NULL_KNOWN_ADDRESS, TRUE_KNOWN_ADDRESS, FALSE_KNOWN_ADDRESS } from "./consts";
/**
* Returns pointer for the value
*/
import { number_size, number_set_all, bigint_size, bigint_set_all, string_size, string_set_all, date_size, date_set_all } from "./generatedStructs";
import { UNDEFINED_KNOWN_ADDRESS, NULL_KNOWN_ADDRESS, TRUE_KNOWN_ADDRESS, FALSE_KNOWN_ADDRESS, MAX_64_BIG_INT } from "./consts";
import { arraySaverIterative } from "./arraySaverIterative";
import { objectSaverIterative, mapSaverIterative, setSaverIterative } from "./objectSaverIterative";
import { stringEncodeInto } from "./stringEncodeInto";
export function saveValueIterative(externalArgs, carrier, referencedExistingPointers, initialValuePtrToPtr, initialValue) {
const valuesToSave = [initialValue];
const pointersToSaveTo = [initialValuePtrToPtr];
const {
heap: {
Uint32Array: uint32
},
allocator,
heap
} = carrier;
export function saveValue(externalArgs, carrier, referencedPointers, // Not really working yet. we need iterative saving for it
visitedValuesOnCurrentSaveOperation, value) {
let valuePointer = 0;
let maybeOurPointer;
while (valuesToSave.length !== 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const valueToSave = valuesToSave.pop(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (value === undefined) {
return UNDEFINED_KNOWN_ADDRESS;
}
const ptrToPtrToSaveTo = pointersToSaveTo.pop(); // Handler well-known values
if (value === null) {
return NULL_KNOWN_ADDRESS;
}
if (valueToSave === undefined) {
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = UNDEFINED_KNOWN_ADDRESS;
continue;
}
if (value === true) {
return TRUE_KNOWN_ADDRESS;
}
if (valueToSave === null) {
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = NULL_KNOWN_ADDRESS;
continue;
}
if (value === false) {
return FALSE_KNOWN_ADDRESS;
}
if (valueToSave === true) {
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = TRUE_KNOWN_ADDRESS;
continue;
}
if (isPrimitive(value)) {
const entry = primitiveValueToEntry(value);
valuePointer = appendEntry(externalArgs, carrier, entry);
} else if (maybeOurPointer = getOurPointerIfApplicable(value, carrier.allocator)) {
valuePointer = maybeOurPointer;
referencedPointers.push(valuePointer);
} else if (maybeOurPointer = visitedValuesOnCurrentSaveOperation.get(value)) {
valuePointer = maybeOurPointer;
referencedPointers.push(valuePointer);
} else if (Array.isArray(value)) {
valuePointer = arraySaver(externalArgs, carrier, referencedPointers, value);
} else if (value instanceof Date) {
valuePointer = appendEntry(externalArgs, carrier, {
type: ENTRY_TYPE.DATE,
refsCount: 1,
value: value.getTime()
});
} else if (value instanceof Map) {
valuePointer = mapSaver(externalArgs, carrier, referencedPointers, visitedValuesOnCurrentSaveOperation, value);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else if (value instanceof Set) {
valuePointer = setSaver(externalArgs, carrier, value);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else if (typeof value === "object") {
valuePointer = objectSaver(externalArgs, carrier, referencedPointers, visitedValuesOnCurrentSaveOperation, value);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else {
throw new Error("unsupported yet");
if (valueToSave === false) {
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = FALSE_KNOWN_ADDRESS;
continue;
}
switch (typeof valueToSave) {
case "number":
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = allocator.calloc(number_size);
number_set_all(heap, uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT], ENTRY_TYPE.NUMBER, valueToSave);
continue;
break;
case "string":
// eslint-disable-next-line no-case-declarations
const stringBytesLength = strByteLength(valueToSave); // eslint-disable-next-line no-case-declarations
const stringDataPointer = allocator.calloc(stringBytesLength);
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = allocator.calloc(string_size);
stringEncodeInto(heap.Uint8Array, stringDataPointer, valueToSave);
string_set_all(heap, uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT], ENTRY_TYPE.STRING, stringBytesLength, stringDataPointer);
continue;
break;
case "bigint":
if (valueToSave > MAX_64_BIG_INT || valueToSave < -MAX_64_BIG_INT) {
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = UNDEFINED_KNOWN_ADDRESS;
continue; // Maybe don't make undefined but throw, or clamp
// throw new Error("MAX_64_BIG_INT");
}
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = allocator.calloc(bigint_size);
bigint_set_all(heap, uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT], valueToSave > 0 ? ENTRY_TYPE.BIGINT_POSITIVE : ENTRY_TYPE.BIGINT_NEGATIVE, valueToSave * (valueToSave > 0 ? BigInt("1") : BigInt("-1")));
continue;
break;
case "function":
// Nope Nope Nope
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = UNDEFINED_KNOWN_ADDRESS;
continue;
break;
case "symbol":
// not supported, write undefined
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = UNDEFINED_KNOWN_ADDRESS;
continue;
break;
// we will never get here
case "undefined":
continue;
break;
// we will never get here
case "boolean":
continue;
break;
}
const maybeOurPointerFromSymbol = getOurPointerIfApplicable(valueToSave, carrier.allocator);
if (maybeOurPointerFromSymbol) {
referencedExistingPointers.push(maybeOurPointerFromSymbol);
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = maybeOurPointerFromSymbol;
continue;
}
if (Array.isArray(valueToSave)) {
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = arraySaverIterative(externalArgs.arrayAdditionalAllocation, carrier, valuesToSave, pointersToSaveTo, valueToSave);
continue;
}
if (valueToSave instanceof Date) {
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = allocator.calloc(date_size);
date_set_all(heap, heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT], ENTRY_TYPE.DATE, 1, 0, valueToSave.getTime());
continue;
}
if (valueToSave instanceof Map) {
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = mapSaverIterative(externalArgs, carrier, valuesToSave, pointersToSaveTo, valueToSave);
continue;
}
if (valueToSave instanceof Set) {
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = setSaverIterative(externalArgs, carrier, valueToSave);
continue;
} // Plain object? I hope so
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT] = objectSaverIterative(externalArgs, carrier, valuesToSave, pointersToSaveTo, valueToSave);
}
return valuePointer;
}

@@ -1,5 +0,5 @@

import { ExternalArgs, GlobalCarrier, MapEntry, InternalAPI } from "./interfaces";
import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
import { INTERNAL_API_SYMBOL } from "./symbols";
import { BaseProxyTrap } from "./BaseProxyTrap";
export declare class SetWrapper<K extends string | number> extends BaseProxyTrap<MapEntry> implements Set<K> {
export declare class SetWrapper<K extends string | number> extends BaseProxyTrap implements Set<K> {
clear(): void;

@@ -6,0 +6,0 @@ forEach(callbackfn: (key: K, key2: K, map: Set<K>) => void, thisArg?: any): void;

@@ -7,2 +7,3 @@ import { deleteObjectPropertyEntryByKey, objectSet, mapOrSetClear } from "./objectWrapperHelpers";

import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class SetWrapper extends BaseProxyTrap {

@@ -20,3 +21,3 @@ clear() {

get size() {
return hashMapSize(this.carrier, this.entry.value);
return hashMapSize(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer));
}

@@ -29,3 +30,3 @@

*entries() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

@@ -38,3 +39,3 @@ const key = entryToFinalJavaScriptValue(this.externalArgs, this.carrier, t.keyPointer);

*keys() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

@@ -46,3 +47,3 @@ yield entryToFinalJavaScriptValue(this.externalArgs, this.carrier, t.keyPointer);

*values() {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, this.entry.value)) {
for (const nodePointer of hashmapNodesPointerIterator(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer))) {
const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

@@ -70,3 +71,3 @@ yield entryToFinalJavaScriptValue(this.externalArgs, this.carrier, t.keyPointer);

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return hashMapNodeLookup(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p) !== 0;
}

@@ -80,3 +81,3 @@

allocationsTransaction(() => {
objectSet(this.externalArgs, this.carrier, this.entry.value, p, undefined);
objectSet(this.externalArgs, this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p, undefined);
}, this.carrier.allocator);

@@ -91,3 +92,3 @@ return this;

return deleteObjectPropertyEntryByKey(this.externalArgs, this.carrier, this.entry.value, p);
return deleteObjectPropertyEntryByKey(this.carrier, object_pointerToHashMap_get(this.carrier.heap, this.entryPointer), p);
}

@@ -94,0 +95,0 @@

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

/* istanbul ignore file */
import { externalArgsApiToExternalArgsApi, isPrimitive, primitiveValueToEntry, align } from "./utils";

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

@@ -1,23 +0,16 @@

import { Entry, primitive, GlobalCarrier } from "./interfaces";
import { Entry, GlobalCarrier } from "./interfaces";
import { ExternalArgs } from "./interfaces";
import { Heap } from "../structsGenerator/consts";
export declare function initializeArrayBuffer(arrayBuffer: ArrayBuffer): void;
export declare function sizeOfEntry(entry: Entry): number;
export declare function writeEntry(carrier: GlobalCarrier, startingCursor: number, entry: Entry): void;
export declare function appendEntry(externalArgs: ExternalArgs, carrier: GlobalCarrier, entry: Entry): number;
export declare function readEntry(carrier: GlobalCarrier, startingCursor: number): Entry;
export declare function canReuseMemoryOfEntry(entryA: Entry, value: primitive): boolean;
export declare function writeValueInPtrToPtr(externalArgs: ExternalArgs, carrier: GlobalCarrier, ptrToPtr: number, value: any): {
referencedPointers: number[];
existingEntryPointer: number;
existingValueEntry: import("./interfaces").StringEntry | import("./interfaces").NumberEntry | import("./interfaces").BigIntPositiveEntry | import("./interfaces").BigIntNegativeEntry | import("./interfaces").ObjectEntry | import("./interfaces").ArrayEntry | import("./interfaces").DateEntry | import("./interfaces").MapEntry | import("./interfaces").SetEntry | undefined;
} | undefined;
export declare function writeValueInPtrToPtrAndHandleMemory(externalArgs: ExternalArgs, carrier: GlobalCarrier, ptrToPtr: number, value: any): void;
export declare function handleArcForDeletedValuePointer(externalArgs: ExternalArgs, carrier: GlobalCarrier, deletedValuePointer: number): void;
export declare function incrementRefCount(externalArgs: ExternalArgs, carrier: GlobalCarrier, entryPointer: number): number;
export declare function decrementRefCount(externalArgs: ExternalArgs, carrier: GlobalCarrier, entryPointer: number): number;
export declare function getRefCount(carrier: GlobalCarrier, entryPointer: number): number;
export declare function setRefCount(carrier: GlobalCarrier, entryPointer: number, newRefCount: number): number;
export declare function writeValueInPtrToPtr(externalArgs: ExternalArgs, carrier: GlobalCarrier, ptrToPtr: number, value: unknown): number[];
export declare function writeValueInPtrToPtrAndHandleMemory(externalArgs: ExternalArgs, carrier: GlobalCarrier, ptrToPtr: number, value: unknown): void;
export declare function handleArcForDeletedValuePointer(carrier: GlobalCarrier, deletedValuePointer: number): void;
export declare function incrementRefCount(heap: Heap, entryPointer: number): number;
export declare function decrementRefCount(heap: Heap, entryPointer: number): number;
export declare function getObjectValuePtrToPtr(pointerToEntry: number): number;
export declare function memComp(uint8: Uint8Array, aStart: number, bStart: number, length: number): boolean;
export declare function compareStringOrNumberEntriesInPlace(carrier: GlobalCarrier, entryAPointer: number, entryBPointer: number): boolean;
export declare function compareStringOrNumberEntriesInPlace(heap: Heap, entryAPointer: number, entryBPointer: number): boolean;
export declare function compareStringOrNumberEntriesInPlaceOld(carrier: GlobalCarrier, entryAPointer: number, entryBPointer: number): boolean;
export declare function readNumberOrString(heap: Heap, pointer: number): string | number;
//# sourceMappingURL=store.d.ts.map

@@ -1,9 +0,9 @@

import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { isPrimitive, primitiveValueToEntry, isKnownAddressValuePointer } from "./utils";
import { ENTRY_TYPE } from "./entry-types";
import { isKnownAddressValuePointer, isTypeWithRC } from "./utils";
import { BigInt64OverflowError } from "./exceptions";
import { INITIAL_ENTRY_POINTER_TO_POINTER, INITIAL_ENTRY_POINTER_VALUE } from "./consts";
import { saveValue } from "./saveValue";
import { getAllLinkedAddresses } from "./getAllLinkedAddresses";
import { stringEncodeInto } from "./stringEncodeInto";
import { stringDecode } from "./stringDecode";
import { typeAndRc_refsCount_get, typeAndRc_refsCount_set, typeOnly_type_get, number_value_get, string_bytesLength_get, string_charsPointer_get } from "./generatedStructs";
import { readString } from "./readString";
import { saveValueIterative } from "./saveValue";
const MAX_64_BIG_INT = BigInt("0xFFFFFFFFFFFFFFFF");

@@ -71,4 +71,4 @@ export function initializeArrayBuffer(arrayBuffer) {

default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -79,246 +79,28 @@ }

}
export function writeEntry(carrier, startingCursor, entry) {
let cursor = startingCursor; // let writtenDataSizeInBytes = 0;
// write type
// undo on throw ?
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.type;
cursor += Float64Array.BYTES_PER_ELEMENT;
switch (entry.type) {
case ENTRY_TYPE.NUMBER:
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Float64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.STRING:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.allocatedBytes;
cursor += Uint32Array.BYTES_PER_ELEMENT; // eslint-disable-next-line no-case-declarations
const writtenBytes = stringEncodeInto(carrier.uint8, cursor, entry.value);
if (writtenBytes !== entry.allocatedBytes) {
// eslint-disable-next-line no-undef
console.warn({
value: entry.value,
writtenBytes,
allocatedBytes: entry.allocatedBytes
}, true);
throw new Error("WTF???");
}
cursor += entry.allocatedBytes;
break;
case ENTRY_TYPE.BIGINT_NEGATIVE:
case ENTRY_TYPE.BIGINT_POSITIVE:
if (entry.value > MAX_64_BIG_INT || entry.value < -MAX_64_BIG_INT) {
throw new BigInt64OverflowError();
}
carrier.bigUint64[cursor / BigUint64Array.BYTES_PER_ELEMENT] = entry.type === ENTRY_TYPE.BIGINT_NEGATIVE ? -entry.value : entry.value;
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.SET:
case ENTRY_TYPE.MAP:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.ARRAY:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.length;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.allocatedLength;
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.DATE:
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Float64Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
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");
}
}
export function appendEntry(externalArgs, carrier, entry) {
const size = sizeOfEntry(entry);
const memoryAddress = carrier.allocator.calloc(size);
writeEntry(carrier, memoryAddress, entry);
return memoryAddress;
}
export function readEntry(carrier, startingCursor) {
let cursor = startingCursor;
const entryType = carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
const entry = {
type: entryType,
value: undefined
}; // let writtenDataSizeInBytes = 0;
switch (entryType) {
// handled by well-known addresses
// case ENTRY_TYPE.UNDEFINED:
// break;
// case ENTRY_TYPE.NULL:
// break;
// case ENTRY_TYPE.BOOLEAN:
// entry.value = carrier.dataView.getUint8(cursor) !== 0;
// cursor += Uint8Array.BYTES_PER_ELEMENT;
// break;
case ENTRY_TYPE.NUMBER:
entry.value = carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.STRING:
// eslint-disable-next-line no-case-declarations
const stringLength = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
entry.allocatedBytes = stringLength;
cursor += Uint32Array.BYTES_PER_ELEMENT; // decode fails with zero length array
if (stringLength > 0) {
// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
// const tempAB = new ArrayBuffer(stringLength, true);
// arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0, true);
entry.value = stringDecode(carrier.uint8, cursor, stringLength);
} else {
entry.value = "";
}
cursor += stringLength;
break;
case ENTRY_TYPE.BIGINT_POSITIVE:
entry.value = carrier.bigUint64[cursor / BigUint64Array.BYTES_PER_ELEMENT];
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.BIGINT_NEGATIVE:
entry.value = -carrier.bigUint64[cursor / BigUint64Array.BYTES_PER_ELEMENT];
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.MAP:
case ENTRY_TYPE.SET:
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.value = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.ARRAY:
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.value = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.DATE:
entry.value = carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");
}
return entry;
}
export function canReuseMemoryOfEntry(entryA, value) {
const typeofTheValue = typeof value; // number & bigint 64 are the same size
if ((entryA.type === ENTRY_TYPE.BIGINT_NEGATIVE || entryA.type === ENTRY_TYPE.BIGINT_POSITIVE || entryA.type === ENTRY_TYPE.NUMBER) && (typeofTheValue === "bigint" || typeofTheValue === "number")) {
return true;
} // kill for strings for now
// if (
// entryA.type === ENTRY_TYPE.STRING &&
// typeofTheValue === "string" &&
// entryA.allocatedBytes >= strByteLength(value as string)
// ) {
// return true;
// }
return false;
}
export function writeValueInPtrToPtr(externalArgs, carrier, ptrToPtr, value) {
const existingEntryPointer = carrier.uint32[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT];
let reuse = false;
let existingValueEntry;
const referencedPointers = []; // Might oom here
if (!isKnownAddressValuePointer(existingEntryPointer)) {
existingValueEntry = readEntry(carrier, existingEntryPointer);
reuse = isPrimitive(value) && isPrimitiveEntryType(existingValueEntry.type) && canReuseMemoryOfEntry(existingValueEntry, value);
} // try to re use memory
if (reuse) {
const newEntry = primitiveValueToEntry(value);
writeEntry(carrier, existingEntryPointer, newEntry);
} else {
const referencedPointers = [];
const newEntryPointer = saveValue(externalArgs, carrier, referencedPointers, new Map(), value);
carrier.uint32[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT] = newEntryPointer;
return {
referencedPointers,
existingEntryPointer,
existingValueEntry
};
}
saveValueIterative(externalArgs, carrier, referencedPointers, ptrToPtr, value);
return referencedPointers;
}
export function writeValueInPtrToPtrAndHandleMemory(externalArgs, carrier, ptrToPtr, value) {
const {
existingValueEntry = false,
existingEntryPointer = 0,
referencedPointers = []
} = writeValueInPtrToPtr(externalArgs, carrier, ptrToPtr, value) || {};
const existingEntryPointer = carrier.heap.Uint32Array[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT]; // Might oom here
const referencedPointers = writeValueInPtrToPtr(externalArgs, carrier, ptrToPtr, value); // -- end of might oom
// commit ref count changes of existing objects
if (referencedPointers.length > 0) {
for (const ptr of referencedPointers) {
incrementRefCount(externalArgs, carrier, ptr);
incrementRefCount(carrier.heap, ptr);
}
}
if (existingValueEntry && "refsCount" in existingValueEntry) {
const newRefCount = decrementRefCount(externalArgs, carrier, existingEntryPointer);
handleArcForDeletedValuePointer(carrier, existingEntryPointer);
}
export function handleArcForDeletedValuePointer(carrier, deletedValuePointer) {
const {
heap,
allocator
} = carrier; // No memory to free/ARC
if (newRefCount === 0) {
const addressesToFree = getAllLinkedAddresses(carrier, false, existingEntryPointer);
for (const address of addressesToFree.leafAddresses) {
carrier.allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
}
}
} else {
carrier.allocator.free(existingEntryPointer);
}
}
export function handleArcForDeletedValuePointer(externalArgs, carrier, deletedValuePointer) {
// No memory to free/ARC
if (isKnownAddressValuePointer(deletedValuePointer)) {

@@ -328,78 +110,39 @@ return;

const existingValueEntry = readEntry(carrier, deletedValuePointer);
const entryType = typeOnly_type_get(heap, deletedValuePointer);
if (existingValueEntry && "refsCount" in existingValueEntry) {
const newRefCount = decrementRefCount(externalArgs, carrier, deletedValuePointer);
if (!isTypeWithRC(entryType)) {
if (entryType === ENTRY_TYPE.STRING) {
allocator.free(string_charsPointer_get(carrier.heap, deletedValuePointer));
}
if (newRefCount === 0) {
const addressesToFree = getAllLinkedAddresses(carrier, false, deletedValuePointer);
for (const address of addressesToFree.leafAddresses) {
carrier.allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
}
}
} else {
carrier.allocator.free(deletedValuePointer);
allocator.free(deletedValuePointer);
return;
}
}
export function incrementRefCount(externalArgs, carrier, entryPointer) {
const entry = readEntry(carrier, entryPointer);
if ("refsCount" in entry) {
entry.refsCount += 1;
writeEntry(carrier, entryPointer, entry);
return entry.refsCount;
if (decrementRefCount(heap, deletedValuePointer) > 0) {
allocator.free(deletedValuePointer);
return;
}
throw new Error("unexpected");
}
export function decrementRefCount(externalArgs, carrier, entryPointer) {
const entry = readEntry(carrier, entryPointer);
const {
leafAddresses,
arcAddresses
} = getAllLinkedAddresses(carrier, false, deletedValuePointer);
if ("refsCount" in entry) {
entry.refsCount -= 1;
writeEntry(carrier, entryPointer, entry);
return entry.refsCount;
for (const address of leafAddresses) {
allocator.free(address);
}
throw new Error("unexpected");
}
export function getRefCount(carrier, entryPointer) {
const entry = readEntry(carrier, entryPointer);
if ("refsCount" in entry) {
return entry.refsCount;
for (const address of arcAddresses) {
decrementRefCount(heap, address);
}
throw new Error("unexpected");
}
export function setRefCount(carrier, entryPointer, newRefCount) {
const entry = readEntry(carrier, entryPointer);
if ("refsCount" in entry) {
const prevCount = entry.refsCount;
entry.refsCount = newRefCount;
writeEntry(carrier, entryPointer, entry);
return prevCount;
}
throw new Error("unexpected");
} // export function getObjectPropPtrToPtr(
// { dataView }: GlobalCarrier,
// pointerToEntry: number
// ) {
// const keyStringLength = dataView.getUint16(pointerToEntry + 1);
// const valuePtrToPtr =
// Uint16Array.BYTES_PER_ELEMENT + pointerToEntry + 1 + keyStringLength;
// const nextPtrToPtr = valuePtrToPtr + Uint32Array.BYTES_PER_ELEMENT;
// return {
// valuePtrToPtr,
// nextPtrToPtr
// };
// }
export function incrementRefCount(heap, entryPointer) {
typeAndRc_refsCount_set(heap, entryPointer, typeAndRc_refsCount_get(heap, entryPointer) + 1);
return typeAndRc_refsCount_get(heap, entryPointer);
}
export function decrementRefCount(heap, entryPointer) {
typeAndRc_refsCount_set(heap, entryPointer, typeAndRc_refsCount_get(heap, entryPointer) - 1);
return typeAndRc_refsCount_get(heap, entryPointer);
}
export function getObjectValuePtrToPtr(pointerToEntry) {

@@ -422,3 +165,26 @@ return pointerToEntry + 1 + 1;

}
export function compareStringOrNumberEntriesInPlace(carrier, entryAPointer, entryBPointer) {
export function compareStringOrNumberEntriesInPlace(heap, entryAPointer, entryBPointer) {
typeOnly_type_get(heap, entryAPointer);
const entryAType = typeOnly_type_get(heap, entryAPointer);
const entryBType = typeOnly_type_get(heap, entryBPointer);
if (entryAType !== entryBType) {
return false;
}
if (entryAType === ENTRY_TYPE.STRING) {
const aLength = string_bytesLength_get(heap, entryAPointer);
const bLength = string_bytesLength_get(heap, entryBPointer);
if (aLength !== bLength) {
return false;
}
return memComp(heap.Uint8Array, string_charsPointer_get(heap, entryAPointer), string_charsPointer_get(heap, entryBPointer), aLength);
} // numbers
return number_value_get(heap, entryAPointer) === number_value_get(heap, entryBPointer);
}
export function compareStringOrNumberEntriesInPlaceOld(carrier, entryAPointer, entryBPointer) {
let cursor = 0;

@@ -447,2 +213,11 @@ const entryAType = carrier.float64[(entryAPointer + cursor) / Float64Array.BYTES_PER_ELEMENT];

return carrier.float64[(entryAPointer + cursor) / Float64Array.BYTES_PER_ELEMENT] === carrier.float64[(entryBPointer + cursor) / Float64Array.BYTES_PER_ELEMENT];
}
export function readNumberOrString(heap, pointer) {
const type = typeOnly_type_get(heap, pointer);
if (type === ENTRY_TYPE.NUMBER) {
return number_value_get(heap, pointer);
} else {
return readString(heap, pointer);
}
}

@@ -16,3 +16,4 @@ export function arrayBuffer2HexArray(buffer, withByteNumber = false) {

import { OutOfMemoryError } from "./exceptions";
import { MEM_POOL_START } from "./consts"; // extend pool and not monkey patch? need to think about it
import { MEM_POOL_START } from "./consts";
import { createHeap } from "../structsGenerator/consts"; // extend pool and not monkey patch? need to think about it

@@ -65,4 +66,4 @@ export function recordAllocations(operation, pool) {

return allocation;
}; // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
}; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error

@@ -98,5 +99,6 @@

float64: new Float64Array(arrayBuffer),
bigUint64: new BigUint64Array(arrayBuffer)
bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer)
};
return carrier;
}
import { primitive, Entry, ExternalArgs, InternalAPI, ExternalArgsApi } from "./interfaces";
import { ENTRY_TYPE } from "./entry-types";
import { IMemPool } from "@thi.ng/malloc";

@@ -11,5 +12,10 @@ export declare function isPrimitive(value: unknown): value is primitive;

export declare function getInternalAPI(value: any): InternalAPI;
/**
* Incorrect length (too big) for emojis
* @param str
*/
export declare function strByteLength(str: string): number;
export declare function align(value: number, alignTo?: number): number;
export declare function isKnownAddressValuePointer(entryPointer: number): boolean;
export declare function isTypeWithRC(type: ENTRY_TYPE): boolean;
//# sourceMappingURL=utils.d.ts.map

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

}
/**
* Incorrect length (too big) for emojis
* @param str
*/
export function strByteLength(str) {

@@ -95,2 +100,5 @@ let s = str.length;

return entryPointer === UNDEFINED_KNOWN_ADDRESS || entryPointer === NULL_KNOWN_ADDRESS || entryPointer === TRUE_KNOWN_ADDRESS || entryPointer === FALSE_KNOWN_ADDRESS;
}
export function isTypeWithRC(type) {
return type === ENTRY_TYPE.OBJECT || type === ENTRY_TYPE.ARRAY || type === ENTRY_TYPE.DATE || type === ENTRY_TYPE.MAP || type === ENTRY_TYPE.SET;
}

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

/* istanbul ignore file */
// We can't run test with weakrefs yet
const KEYS = 1;

@@ -2,0 +4,0 @@ const VALUES = 2;

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

@@ -36,38 +36,41 @@ "module": "dist/index.js",

"webpack-playground": "webpack-dev-server --mode=development --config playground/webpack.config.js --open",
"generate-docs": "rimraf -f docs/generated/ && typedoc --mode library --readme none --out docs/generated/ --excludeNotExported --ignoreCompilerErrors src/index.ts"
"generate-docs": "rimraf -f docs/generated/ && typedoc --mode library --readme none --out docs/generated/ --excludeNotExported --ignoreCompilerErrors src/index.ts",
"generate-structs": "npx ts-node src/structsGenerator/run.ts"
},
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"@babel/core": "^7.9.6",
"@babel/node": "^7.8.7",
"@babel/preset-env": "^7.9.6",
"@babel/preset-typescript": "^7.9.0",
"@types/benchmark": "^1.0.31",
"@types/jest": "^25.2.1",
"@types/benchmark": "^1.0.32",
"@types/jest": "^25.2.3",
"@types/node": "^12.12.21",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"@typescript-eslint/eslint-plugin": "^3.0.0",
"@typescript-eslint/parser": "^3.0.0",
"babel-loader": "^8.1.0",
"benchmark": "^2.1.4",
"concurrently": "^5.1.0",
"concurrently": "^5.2.0",
"core-js": "^3.6.5",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.1",
"eslint-plugin-prettier": "^3.1.2",
"eslint": "^7.1.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.3",
"gh-pages": "^2.2.0",
"html-webpack-plugin": "^4.2.0",
"html-webpack-plugin": "^4.3.0",
"husky": "^4.2.5",
"jest": "^25.3.0",
"jest": "^26.0.1",
"kind-of": "^6.0.3",
"prettier": "^2.0.4",
"prettier-eslint": "^9.0.1",
"prettier": "^2.0.5",
"prettier-eslint": "^10.1.0",
"rimraf": "^3.0.2",
"rollup": "^2.4.0",
"rollup": "^2.10.8",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-node-resolve": "^5.2.0",
"typedoc": "^0.17.0-3",
"rollup-plugin-terser": "^6.0.1",
"typedoc": "^0.17.7",
"typedoc-plugin-markdown": "^2.2.17",
"typescript": "^3.8.3",
"webpack": "^4.42.1",
"typescript": "^3.9.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"webpack-dev-server": "^3.11.0",
"worker-loader": "^2.0.0",

@@ -89,4 +92,4 @@ "yarn-deduplicate": "^2.0.0"

"dependencies": {
"@thi.ng/malloc": "^4.1.10"
"@thi.ng/malloc": "^4.1.14"
}
}

@@ -90,2 +90,3 @@ # ObjectBuffer: object-like API, backed by a [shared]arraybuffer 👀

* Need to specify size for the `ArrayBuffer`. When exceed that size, exception will be thrown. (Can be extended later with a utility function, but not automatically)
* Size must be multiplication of 8
* Set, Map, Object keys can be only string or numbers. no symbols or other things

@@ -92,0 +93,0 @@ * You can't save objects with circularities (But you can create them on objectbuffer)

/* eslint-env jest */
import { createObjectBuffer } from "../";
import { memoryStats } from "../internal/api";
import { memoryStats, disposeWrapperObject } from "../internal/api";
import { externalArgsApiToExternalArgsApi } from "../internal/utils";

@@ -35,4 +35,160 @@

expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`592`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`560`);
});
test("splice 1", () => {
const ob = createObjectBuffer<{ arr: (number | null)[] }>(
{ arrayAdditionalAllocation: 10 },
1024,
{ arr: [] },
{ useSharedArrayBuffer: false }
);
const usedAfterCreate = memoryStats(ob).used;
expect(usedAfterCreate).toMatchInlineSnapshot(`320`);
ob.arr.push(null, null, null, null, null, null, null, null, null, null);
const usedAfterNullPush = memoryStats(ob).used;
expect(usedAfterNullPush - usedAfterCreate).toMatchInlineSnapshot(`0`);
const removedNulls = ob.arr.splice(0, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
expect(removedNulls).toMatchInlineSnapshot(`
Array [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
]
`);
const usedAfterReplaceNullsWithNumbers = memoryStats(ob).used;
expect(
usedAfterReplaceNullsWithNumbers - usedAfterCreate
).toMatchInlineSnapshot(`240`);
const removedNumbers = ob.arr.splice(0, 10);
expect(removedNumbers).toMatchInlineSnapshot(`
Array [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
]
`);
const usedAfterRemoveNumbers = memoryStats(ob).used;
expect(usedAfterRemoveNumbers - usedAfterCreate).toMatchInlineSnapshot(`0`);
});
test("splice 2", () => {
const ob = createObjectBuffer<{ arr: any }>(
{ arrayAdditionalAllocation: 0 },
1024 * 2,
{ arr: [] },
{ useSharedArrayBuffer: false }
);
const usedAfterCreate = memoryStats(ob).used;
expect(usedAfterCreate).toMatchInlineSnapshot(`272`);
ob.arr.push(null, null, null, null, null, null, null, null, null, null);
const usedAfterNullPush = memoryStats(ob).used;
expect(usedAfterNullPush - usedAfterCreate).toMatchInlineSnapshot(`48`);
const removedNulls = ob.arr.splice(
0,
10,
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9],
[10]
);
expect(removedNulls).toMatchInlineSnapshot(`
Array [
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
]
`);
const usedAfterReplaceNullsWithNumbers = memoryStats(ob).used;
expect(
usedAfterReplaceNullsWithNumbers - usedAfterCreate
).toMatchInlineSnapshot(`768`);
const removedArrays = ob.arr.splice(0, 10);
expect(removedArrays).toMatchInlineSnapshot(`
Array [
Array [
1,
],
Array [
2,
],
Array [
3,
],
Array [
4,
],
Array [
5,
],
Array [
6,
],
Array [
7,
],
Array [
8,
],
Array [
9,
],
Array [
10,
],
]
`);
const usedAfterRemovedArrays = memoryStats(ob).used;
expect(usedAfterRemovedArrays - usedAfterCreate).toMatchInlineSnapshot(
`448`
);
disposeWrapperObject(ob.arr);
removedArrays.forEach((a: any) => disposeWrapperObject(a));
const usedDisposeArrays = memoryStats(ob).used;
expect(usedDisposeArrays - usedAfterCreate).toMatchInlineSnapshot(`48`);
});
});

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

expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`264`);
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`272`);
});
});

@@ -23,2 +23,25 @@ /* eslint-env jest */

expect(objectBuffer).toMatchInlineSnapshot(`
Object {
"arr": Array [
1,
2,
3,
4,
],
"arr2": Array [
1,
2,
3,
4,
],
"obj": Object {
"a": 1,
},
"obj2": Object {
"a": 1,
},
}
`);
expect(objectBuffer.arr2).toBe(objectBuffer.arr2);

@@ -30,27 +53,4 @@ expect(objectBuffer.arr2).toBe(objectBuffer.arr);

expect(objectBuffer).toMatchInlineSnapshot(`
Object {
"arr": Array [
1,
2,
3,
4,
],
"arr2": Array [
1,
2,
3,
4,
],
"obj": Object {
"a": 1,
},
"obj2": Object {
"a": 1,
},
}
`);
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`776`);
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`856`);
});
});

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

objectBuffer.foo = new Map([[1, "a"]]);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`592`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`560`);
expect(objectBuffer.foo).toMatchInlineSnapshot(`

@@ -30,3 +30,3 @@ Map {

objectBuffer.foo.set("2", "b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`440`);
expect(objectBuffer.foo).toMatchInlineSnapshot(`

@@ -54,7 +54,7 @@ Map {

objectBuffer.foo.set("2", "b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`440`);
objectBuffer.foo.delete(1);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`592`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`544`);

@@ -73,11 +73,12 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`

objectBuffer.foo = new Map();
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`680`);
const availSizeAfterCreation = memoryStats(objectBuffer).available;
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`664`);
objectBuffer.foo.set(1, "a");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`592`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`560`);
objectBuffer.foo.set("2", "b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`440`);
objectBuffer.foo.clear();
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`680`);
expect(memoryStats(objectBuffer).available).toBe(availSizeAfterCreation);

@@ -94,3 +95,3 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`Map {}`);

expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`440`);

@@ -97,0 +98,0 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`

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

Object {
"available": 376,
"used": 648,
"available": 328,
"used": 696,
}

@@ -35,4 +35,4 @@ `);

Object {
"available": 1400,
"used": 648,
"available": 1352,
"used": 696,
}

@@ -44,4 +44,4 @@ `);

Object {
"available": 376,
"used": 648,
"available": 328,
"used": 696,
}

@@ -53,4 +53,4 @@ `);

Object {
"available": 120,
"used": 648,
"available": 72,
"used": 696,
}

@@ -61,8 +61,8 @@ `);

expect(memoryStats(objectBuffer)).toMatchInlineSnapshot(`
Object {
"available": 1400,
"used": 648,
}
`);
Object {
"available": 1352,
"used": 696,
}
`);
});
});

@@ -12,10 +12,11 @@ /* eslint-env jest */

const objectBuffer = createObjectBuffer<any>(externalArgs, 1024, {});
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`864`);
const sizeBeforeSet = memoryStats(objectBuffer).available;
expect(sizeBeforeSet).toMatchInlineSnapshot(`864`);
objectBuffer.foo = "a";
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`776`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`744`);
delete objectBuffer.foo;
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`864`);
expect(memoryStats(objectBuffer).available).toBe(sizeBeforeSet);
expect(objectBuffer).toMatchInlineSnapshot(`Object {}`);

@@ -35,3 +36,3 @@ });

const objectBuffer = createObjectBuffer<any>(externalArgs, 2048, input);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`1016`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`840`);
expect(input).toEqual(objectBuffer);

@@ -38,0 +39,0 @@ expect(objectBuffer).toMatchInlineSnapshot(`

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

expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`776`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`760`);
expect(objectBuffer).toMatchInlineSnapshot(`

@@ -38,0 +38,0 @@ Object {

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

expect(memoryStats(objectBuffer).available).toEqual(freeSpaceLeft);
expect(freeSpaceLeft).toMatchInlineSnapshot(`40`);
expect(freeSpaceLeft).toMatchInlineSnapshot(`24`);

@@ -33,0 +33,0 @@ expect(objectBuffer).toMatchInlineSnapshot(`

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

objectBuffer.foo = new Set(["a"]);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`616`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`584`);
expect(objectBuffer.foo).toMatchInlineSnapshot(`

@@ -30,3 +30,3 @@ Set {

objectBuffer.foo.add("b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`552`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
expect(objectBuffer.foo).toMatchInlineSnapshot(`

@@ -54,7 +54,7 @@ Set {

objectBuffer.foo.add("b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`552`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
objectBuffer.foo.delete(1);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`552`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);

@@ -75,7 +75,7 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`

objectBuffer.foo.add("b");
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`552`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);
objectBuffer.foo.clear();
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`680`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`664`);

@@ -92,3 +92,3 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`Set {}`);

expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`552`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`504`);

@@ -95,0 +95,0 @@ expect(objectBuffer.foo).toMatchInlineSnapshot(`

@@ -21,2 +21,15 @@ /* eslint-env jest */

// expect(objectBuffer).toMatchInlineSnapshot(`
// Object {
// "arr": Array [
// Object {
// "a": 1,
// },
// ],
// }
// `);
// disposeWrapperObject(objectBuffer.arr[0]);
// disposeWrapperObject(objectBuffer.arr);
objectBuffer.arr = [{ bar: 666 }];

@@ -34,3 +47,9 @@

expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`480`);
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`528`);
disposeWrapperObject(objectBuffer.arr[0]);
disposeWrapperObject(objectBuffer.arr);
delete objectBuffer.arr;
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`176`);
});

@@ -84,4 +103,4 @@

expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`664`);
expect(memoryStats(objectBuffer).used).toMatchInlineSnapshot(`744`);
});
});

@@ -19,3 +19,3 @@ import { createObjectBuffer } from "..";

expect(initialFreeSpace).toMatchInlineSnapshot(`32`);
expect(initialFreeSpace).toMatchInlineSnapshot(`16`);

@@ -30,3 +30,3 @@ expect(() => {

expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`32`);
expect(memoryStats(objectBuffer).available).toMatchInlineSnapshot(`16`);

@@ -33,0 +33,0 @@ expect(objectBuffer).toMatchInlineSnapshot(`

@@ -16,3 +16,2 @@ /**

replaceUnderlyingArrayBuffer,
// eslint-disable-next-line @typescript-eslint/camelcase
sizeOf as unreliable_sizeOf,

@@ -19,0 +18,0 @@ memoryStats,

@@ -5,3 +5,6 @@ import { IMemPool } from "@thi.ng/malloc";

// extend pool and not monkey patch? need to think about it
export function allocationsTransaction(operation: () => void, pool: IMemPool) {
export function allocationsTransaction<T>(
operation: () => T,
pool: IMemPool
): T {
const allocations: number[] = [];

@@ -62,7 +65,9 @@ const originalMalloc = pool.malloc;

operation();
pool.malloc = originalMalloc;
pool.calloc = originalCalloc;
pool.realloc = originalRealloc;
try {
return operation();
} finally {
pool.malloc = originalMalloc;
pool.calloc = originalCalloc;
pool.realloc = originalRealloc;
}
}
import { initializeArrayBuffer } from "./store";
import { objectSaver } from "./objectSaver";
import { createObjectWrapper } from "./objectWrapper";

@@ -15,2 +14,5 @@ import { ExternalArgsApi, GlobalCarrier } from "./interfaces";

import { UnsupportedOperationError } from "./exceptions";
import { createHeap } from "../structsGenerator/consts";
import { saveValueIterative } from "./saveValue";
import { allocationsTransaction } from "./allocationsTransaction";

@@ -43,3 +45,4 @@ export interface CreateObjectBufferOptions {

initialValue instanceof Set ||
isPrimitive(initialValue)
isPrimitive(initialValue) ||
typeof initialValue === "symbol"
) {

@@ -68,20 +71,21 @@ throw new UnsupportedOperationError();

bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer),
};
const start = objectSaver(
externalArgsApiToExternalArgsApi(externalArgs),
carrier,
[],
new Map(),
initialValue
);
allocationsTransaction(() => {
saveValueIterative(
externalArgsApiToExternalArgsApi(externalArgs),
carrier,
[],
INITIAL_ENTRY_POINTER_TO_POINTER,
initialValue
);
}, allocator);
carrier.uint32[
INITIAL_ENTRY_POINTER_TO_POINTER / Uint32Array.BYTES_PER_ELEMENT
] = start;
return createObjectWrapper(
externalArgsApiToExternalArgsApi(externalArgs),
carrier,
start
carrier.heap.Uint32Array[
INITIAL_ENTRY_POINTER_TO_POINTER / Uint32Array.BYTES_PER_ELEMENT
]
);

@@ -148,2 +152,3 @@ }

bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer),
};

@@ -199,6 +204,7 @@

bigUint64: new BigUint64Array(newArrayBuffer),
heap: createHeap(newArrayBuffer),
};
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
allocator.end = newArrayBuffer.byteLength;

@@ -205,0 +211,0 @@

@@ -1,20 +0,16 @@

import {
readEntry,
writeEntry,
writeValueInPtrToPtrAndHandleMemory,
} from "./store";
import { ArrayEntry, ExternalArgs, GlobalCarrier } from "./interfaces";
import { writeValueInPtrToPtrAndHandleMemory } from "./store";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { ENTRY_TYPE } from "./entry-types";
import { assertNonNull } from "./assertNonNull";
import {
array_length_get,
array_dataspacePointer_get,
array_allocatedLength_get,
array_length_set,
array_set_all,
array_refsCount_get,
} from "./generatedStructs";
import { Heap } from "../structsGenerator/consts";
export function arrayGetMetadata(
carrier: GlobalCarrier,
pointerToArrayEntry: number
) {
const arrayEntry = readEntry(carrier, pointerToArrayEntry) as ArrayEntry;
return arrayEntry;
}
export function arrayGetPointersToValueInIndex(

@@ -25,6 +21,4 @@ carrier: GlobalCarrier,

) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
// out of bound
if (indexToGet >= metadata.length) {
if (indexToGet >= array_length_get(carrier.heap, pointerToArrayEntry)) {
return undefined;

@@ -34,3 +28,4 @@ }

const pointerToThePointer =
metadata.value + indexToGet * Uint32Array.BYTES_PER_ELEMENT;
array_dataspacePointer_get(carrier.heap, pointerToArrayEntry) +
indexToGet * Uint32Array.BYTES_PER_ELEMENT;

@@ -118,8 +113,8 @@ const pointer =

) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
if (wishedLength > metadata.length) {
if (wishedLength > metadata.allocatedLength) {
if (wishedLength > array_length_get(carrier.heap, pointerToArrayEntry)) {
if (
wishedLength >
array_allocatedLength_get(carrier.heap, pointerToArrayEntry)
) {
reallocateArray(
externalArgs,
carrier,

@@ -132,9 +127,3 @@ pointerToArrayEntry,

// no need to re-allocated, just push the length forward
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: wishedLength,
});
array_length_set(carrier.heap, pointerToArrayEntry, wishedLength);
}

@@ -148,20 +137,10 @@ }

export function shrinkArray(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
heap: Heap,
pointerToArrayEntry: number,
wishedLength: number
) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: metadata.value,
allocatedLength: metadata.allocatedLength,
length: wishedLength,
});
array_length_set(heap, pointerToArrayEntry, wishedLength);
}
function reallocateArray(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,

@@ -171,30 +150,28 @@ pointerToArrayEntry: number,

newLength: number
) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
const newArrayValueLocation = carrier.allocator.realloc(
metadata.value,
newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT
): void {
const dataspacePointer = array_dataspacePointer_get(
carrier.heap,
pointerToArrayEntry
);
// for (
// let memoryToCopyIndex = 0;
// memoryToCopyIndex < metadata.length;
// memoryToCopyIndex += 1
// ) {
// carrier.dataView.setUint32(
// newArrayValueLocation + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT,
// carrier.dataView.getUint32(
// metadata.value + memoryToCopyIndex * Uint32Array.BYTES_PER_ELEMENT
// )
// );
// }
// if array was zero length, dataspacePointer was zero
const newArrayValueLocation =
dataspacePointer !== 0
? carrier.allocator.realloc(
dataspacePointer,
newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT
)
: carrier.allocator.calloc(
newAllocatedLength * Uint32Array.BYTES_PER_ELEMENT
);
writeEntry(carrier, pointerToArrayEntry, {
type: ENTRY_TYPE.ARRAY,
refsCount: metadata.refsCount,
value: newArrayValueLocation,
allocatedLength: newAllocatedLength,
length: newLength,
});
array_set_all(
carrier.heap,
pointerToArrayEntry,
ENTRY_TYPE.ARRAY,
array_refsCount_get(carrier.heap, pointerToArrayEntry),
newArrayValueLocation,
newLength,
newAllocatedLength
);
}

@@ -204,12 +181,19 @@

externalArgs: ExternalArgs,
globalCarrier: GlobalCarrier,
carrier: GlobalCarrier,
pointerToArrayEntry: number,
sortComparator: (a: any, b: any) => 1 | -1 | 0 = defaultCompareFunction
) {
const metadata = arrayGetMetadata(globalCarrier, pointerToArrayEntry);
const pointersToValues = [...new Array(metadata.length).keys()]
.map((index) => metadata.value + index * Uint32Array.BYTES_PER_ELEMENT)
const arrayDataSpace = array_dataspacePointer_get(
carrier.heap,
pointerToArrayEntry
);
const pointersToValues = [
...new Array(array_length_get(carrier.heap, pointerToArrayEntry)).keys(),
]
.map((index) => arrayDataSpace + index * Uint32Array.BYTES_PER_ELEMENT)
.map(
(pointerToPointer) =>
globalCarrier.uint32[pointerToPointer / Uint32Array.BYTES_PER_ELEMENT]
carrier.heap.Uint32Array[
pointerToPointer / Uint32Array.BYTES_PER_ELEMENT
]
);

@@ -220,3 +204,3 @@

pointer,
entryToFinalJavaScriptValue(externalArgs, globalCarrier, pointer),
entryToFinalJavaScriptValue(externalArgs, carrier, pointer),
] as const;

@@ -230,4 +214,4 @@ });

for (let i = 0; i < sortMe.length; i += 1) {
globalCarrier.uint32[
(metadata.value + i * Uint32Array.BYTES_PER_ELEMENT) /
carrier.heap.Uint32Array[
(arrayDataSpace + i * Uint32Array.BYTES_PER_ELEMENT) /
Uint32Array.BYTES_PER_ELEMENT

@@ -276,11 +260,13 @@ ] = sortMe[i][0];

export function arrayReverse(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
pointerToArrayEntry: number
) {
const metadata = arrayGetMetadata(carrier, pointerToArrayEntry);
for (
let i = 0;
i < Math.floor(array_length_get(carrier.heap, pointerToArrayEntry) / 2);
i += 1
) {
const theOtherIndex =
array_length_get(carrier.heap, pointerToArrayEntry) - i - 1;
for (let i = 0; i < Math.floor(metadata.length / 2); i += 1) {
const theOtherIndex = metadata.length - i - 1;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion

@@ -287,0 +273,0 @@ const a = arrayGetPointersToValueInIndex(carrier, pointerToArrayEntry, i)!;

/* eslint-env jest */
import { initializeArrayBuffer } from "./store";
import { createObjectBuffer } from "..";
import { memoryStats } from "./api";
import { createArrayWrapper } from "./arrayWrapper";
import { arraySaver } from "./arraySaver";
import { MemPool } from "@thi.ng/malloc";
import { MEM_POOL_START } from "./consts";
import { externalArgsApiToExternalArgsApi } from "./utils";
import { makeCarrier } from "./testUtils";
describe("arraySplice tests", () => {
const externalArgs = externalArgsApiToExternalArgsApi({
arrayAdditionalAllocation: 20,
});
test("arrayWrapper splice - add + delete - array stay in same length", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const removed = arrayWrapper.splice(2, 3, "a", "b", "c");

@@ -86,25 +65,12 @@ const removedFromPlain = plainJSArray.splice(2, 3, "a", "b", "c");

expect(removedFromPlain).toEqual([...removed]);
expect(allocator.stats().available).toMatchInlineSnapshot(`0`);
});
test("arrayWrapper splice - Just delete items from the middle", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.splice(2, 3);

@@ -137,25 +103,12 @@ plainJSArray.splice(2, 3);

expect(plainJSArray).toEqual([...arrayWrapper]);
expect(allocator.stats().available).toMatchInlineSnapshot(`72`);
});
test("arrayWrapper splice - Just add items in the middle", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.splice(4, 0, "a", "b");

@@ -198,26 +151,12 @@ plainJSArray.splice(4, 0, "a", "b");

expect(plainJSArray).toEqual([...arrayWrapper]);
expect(allocator.stats().available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper splice - add + delete - array will get longer", () => {
const arrayBuffer = new ArrayBuffer(1024);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 3 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const availableCheckpoint = allocator.stats().available;
const removed = arrayWrapper.splice(2, 2, "a", "b", "c", "d");

@@ -277,29 +216,14 @@ const removedFromPlain = plainJSArray.splice(2, 2, "a", "b", "c", "d");

expect(removedFromPlain).toEqual([...removed]);
expect(
availableCheckpoint - allocator.stats().available
).toMatchInlineSnapshot(`96`);
});
test("arrayWrapper splice - add + delete - array will get shorter", () => {
const arrayBuffer = new ArrayBuffer(1024);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const availableCheckpoint = memoryStats(ob).available;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = ob.arr;
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const availableCheckpoint = allocator.stats().available;
const removed = arrayWrapper.splice(2, 6, "a", "b", "c", "d");

@@ -362,25 +286,14 @@ const removedFromPlain = plainJSArray.splice(2, 6, "a", "b", "c", "d");

expect(
availableCheckpoint - allocator.stats().available
).toMatchInlineSnapshot(`96`);
availableCheckpoint - memoryStats(ob).available
).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper splice - start bigger than array", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const removed = arrayWrapper.splice(12, 3, "a", "b");

@@ -431,25 +344,12 @@ const removedFromPlain = plainJSArray.splice(12, 3, "a", "b");

expect(removedFromPlain).toEqual([...removed]);
expect(allocator.stats().available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper splice - delete bigger than array", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const removed = arrayWrapper.splice(2, 20, "a", "b");

@@ -506,25 +406,12 @@ const removedFromPlain = plainJSArray.splice(2, 20, "a", "b");

expect(removedFromPlain).toEqual([...removed]);
expect(allocator.stats().available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper splice - negative start", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 20 }, 1024, {
arr: plainJSArray,
});
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const removed = arrayWrapper.splice(-4, 1, "a", "b");

@@ -581,25 +468,12 @@ const removedFromPlain = plainJSArray.splice(-4, 1, "a", "b");

expect(removedFromPlain).toEqual([...removed]);
expect(allocator.stats().available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper splice - negative delete", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
const plainJSArray: any[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const ob = createObjectBuffer({ arrayAdditionalAllocation: 3 }, 1024, {
arr: plainJSArray,
});
const plainJSArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arrayWrapper = ob.arr;
const saverOutput = arraySaver(externalArgs, carrier, [], plainJSArray);
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
const removed = arrayWrapper.splice(4, -1, 50, 51);

@@ -650,5 +524,3 @@ const removedFromPlain = plainJSArray.splice(4, -1, 50, 51);

expect(removedFromPlain).toEqual([...removed]);
expect(allocator.stats().available).toMatchInlineSnapshot(`24`);
});
});
import {
arrayGetMetadata,
getFinalValueAtArrayIndex,

@@ -11,8 +10,13 @@ shrinkArray,

import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { writeValueInPtrToPtr } from "./store";
import { writeValueInPtrToPtr, handleArcForDeletedValuePointer } from "./store";
import { array_length_get } from "./generatedStructs";
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#Syntax
/**
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#Syntax
this function is not OOM same yet unfortunately,
There's allocations after destructive mutations
*/
export function arraySplice(
externalArgs: ExternalArgs,
globalCarrier: GlobalCarrier,
carrier: GlobalCarrier,
pointerToArrayEntry: number,

@@ -23,8 +27,8 @@ startArg: number,

) {
const metadata = arrayGetMetadata(globalCarrier, pointerToArrayEntry);
const arrayLength = array_length_get(carrier.heap, pointerToArrayEntry);
const calcedStart = calculateSpliceStart(metadata.length, startArg);
const calcedStart = calculateSpliceStart(arrayLength, startArg);
const calcedDeleteCount = calculateDeleteCount(
metadata.length,
arrayLength,
calcedStart,

@@ -34,14 +38,9 @@ deleteCountArg

const newLength = metadata.length + itemsToAddArg.length - calcedDeleteCount;
const newLength = arrayLength + itemsToAddArg.length - calcedDeleteCount;
extendArrayIfNeeded(
externalArgs,
globalCarrier,
pointerToArrayEntry,
newLength
);
extendArrayIfNeeded(externalArgs, carrier, pointerToArrayEntry, newLength);
const deletedItemsToReturn = [];
// can be negative
const itemCountChange = newLength - metadata.length;
const itemCountChange = newLength - arrayLength;

@@ -56,3 +55,3 @@ for (

externalArgs,
globalCarrier,
carrier,
pointerToArrayEntry,

@@ -62,2 +61,11 @@ deletedItemIndexToSave

);
handleArcForDeletedValuePointer(
carrier,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
arrayGetPointersToValueInIndex(
carrier,
pointerToArrayEntry,
deletedItemIndexToSave
)!.pointer
);
}

@@ -78,3 +86,3 @@

const valueToCopyPointers = arrayGetPointersToValueInIndex(
globalCarrier,
carrier,
pointerToArrayEntry,

@@ -87,3 +95,3 @@ writeValueToIndex - itemCountChange

setValuePointerAtArrayIndex(
globalCarrier,
carrier,
pointerToArrayEntry,

@@ -94,3 +102,3 @@ writeValueToIndex,

globalCarrier.uint32[
carrier.heap.Uint32Array[
valueToCopyPointers.pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT

@@ -109,15 +117,14 @@ ] = 0;

let writeValueToIndex = calcedStart + itemsToAddArg.length;
writeValueToIndex < metadata.length + itemCountChange;
writeValueToIndex < arrayLength + itemCountChange;
writeValueToIndex += 1
) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const valueToCopyPointers = arrayGetPointersToValueInIndex(
globalCarrier,
carrier,
pointerToArrayEntry,
writeValueToIndex - itemCountChange
);
)!;
assertNonNull(valueToCopyPointers);
setValuePointerAtArrayIndex(
globalCarrier,
carrier,
pointerToArrayEntry,

@@ -127,19 +134,2 @@ writeValueToIndex,

);
// empty old array index, its still allocated!
globalCarrier.uint32[
valueToCopyPointers.pointerToThePointer / Uint32Array.BYTES_PER_ELEMENT
] = 0;
// using that is wastefull
// setValueAtArrayIndex(
// dataView,
// textDecoder,
// textEncoder,
// arrayAdditionalAllocation,
// pointerToArrayEntry,
// writeValueToIndex + calcedDeleteCount,
// undefined
// );
}

@@ -150,3 +140,3 @@ }

const valueToSetPointers = arrayGetPointersToValueInIndex(
globalCarrier,
carrier,
pointerToArrayEntry,

@@ -160,3 +150,3 @@ calcedStart + i

externalArgs,
globalCarrier,
carrier,
valueToSetPointers.pointerToThePointer,

@@ -167,4 +157,4 @@ itemsToAddArg[i]

if (newLength < metadata.length) {
shrinkArray(externalArgs, globalCarrier, pointerToArrayEntry, newLength);
if (newLength < arrayLength) {
shrinkArray(carrier.heap, pointerToArrayEntry, newLength);
}

@@ -189,3 +179,3 @@

if (deleteCountArg === undefined || deleteCountArg >= arrayLength - start) {
return arrayLength - start;
return Math.min(arrayLength, arrayLength - start);
}

@@ -197,3 +187,3 @@

return deleteCountArg;
return Math.min(arrayLength, deleteCountArg);
}
/* eslint-env jest */
import { initializeArrayBuffer } from "./store";
import { createObjectBuffer, memoryStats } from "./api";
import { createArrayWrapper } from "./arrayWrapper";
import { arraySaver } from "./arraySaver";
import { MemPool } from "@thi.ng/malloc";
import { MEM_POOL_START } from "./consts";
import { externalArgsApiToExternalArgsApi } from "./utils";
import { makeCarrier } from "./testUtils";
describe("arrayWrapper tests", () => {
const externalArgs = externalArgsApiToExternalArgsApi({
arrayAdditionalAllocation: 20,
});
describe("arrayWrapper - general", () => {
test("arrayWrapper class 1", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 20 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper: any = createArrayWrapper(
externalArgs,
carrier,
saverOutput
);
expect(arrayWrapper).toMatchInlineSnapshot(`

@@ -45,46 +24,28 @@ Array [

expect(allocator.stats().available).toMatchInlineSnapshot(`264`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper array.keys()", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 20 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
externalArgs,
carrier,
saverOutput
);
expect([...arrayWrapper.keys()]).toEqual([0, 1, 2]);
expect(allocator.stats().available).toMatchInlineSnapshot(`264`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper array.entries()", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 20 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
externalArgs,
carrier,
saverOutput
);
expect([...arrayWrapper.entries()]).toMatchInlineSnapshot(`

@@ -107,23 +68,14 @@ Array [

expect(allocator.stats().available).toMatchInlineSnapshot(`264`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper array.values() & iterator", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 20 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
externalArgs,
carrier,
saverOutput
);
expect([...arrayWrapper.values()]).toMatchInlineSnapshot(`

@@ -144,19 +96,14 @@ Array [

expect(allocator.stats().available).toMatchInlineSnapshot(`264`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`24`);
});
test("arrayWrapper set value in bound", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 20 },
1024,
{ arrayToSave }
).arrayToSave;
const arrayWrapper: any = createArrayWrapper(
externalArgs,
carrier,
saverOutput
);
arrayWrapper[1] = "new value";

@@ -174,20 +121,10 @@

test("arrayWrapper set value out of bound, but inside allocated space", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(
{ ...externalArgs, arrayAdditionalAllocation: 15 },
carrier,
[],
arrayToSave
);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 15 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper: any = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 15 },
carrier,
saverOutput
);
arrayWrapper[10] = "new value";

@@ -213,19 +150,10 @@

test("arrayWrapper set value out of bound, but outside allocated space", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = ["a", "b", 1];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 3 },
1024,
{ arrayToSave }
).arrayToSave;
const arrayWrapper: any = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper[10] = "new value";

@@ -248,3 +176,3 @@

`);
expect(allocator.stats().available).toMatchInlineSnapshot(`232`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`496`);
});

@@ -254,20 +182,10 @@ });

test("arrayWrapper sort - no comparator", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = [2, 1, null, 3, 10, undefined, 6, 77];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 3 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.sort();

@@ -288,14 +206,6 @@

expect(allocator.stats().available).toMatchInlineSnapshot(`176`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`32`);
});
test("arrayWrapper sort - with comparator", () => {
const arrayBuffer = new ArrayBuffer(2048);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = [2, 1, 3, 10, 6, 77].map((value) => ({

@@ -305,10 +215,8 @@ value,

const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 3 },
1024 * 2,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.sort((a, b) => {

@@ -347,24 +255,14 @@ if (a.value > b.value) {

expect(allocator.stats().available).toMatchInlineSnapshot(`568`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`376`);
});
test("arrayWrapper - reverse", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = [1, 2, 3, 4, 5, 6, 7];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 3 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.reverse();

@@ -388,24 +286,14 @@ arrayWrapper.reverse();

expect(allocator.stats().available).toMatchInlineSnapshot(`152`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`16`);
});
test("arrayWrapper - set length", () => {
const arrayBuffer = new ArrayBuffer(512);
const carrier = makeCarrier(arrayBuffer);
initializeArrayBuffer(arrayBuffer);
const allocator = new MemPool({
buf: arrayBuffer,
start: MEM_POOL_START,
});
const arrayToSave = [1, 2, 3, 4, 5, 6, 7];
const saverOutput = arraySaver(externalArgs, carrier, [], arrayToSave);
const arrayWrapper = createObjectBuffer(
{ arrayAdditionalAllocation: 3 },
512,
{ arrayToSave }
).arrayToSave;
const arrayWrapper = createArrayWrapper(
{ ...externalArgs, arrayAdditionalAllocation: 3 },
carrier,
saverOutput
);
arrayWrapper.length = 10;

@@ -446,4 +334,4 @@ expect(arrayWrapper).toMatchInlineSnapshot(`

expect(allocator.stats().available).toMatchInlineSnapshot(`152`);
expect(memoryStats(arrayWrapper).available).toMatchInlineSnapshot(`160`);
});
});
import {
getFinalValueAtArrayIndex,
arrayGetMetadata,
setValueAtArrayIndex,

@@ -11,3 +10,3 @@ arraySort,

import { arraySplice } from "./arraySplice";
import { ExternalArgs, GlobalCarrier, ArrayEntry } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import {

@@ -19,6 +18,7 @@ IllegalArrayIndexError,

import { BaseProxyTrap } from "./BaseProxyTrap";
import { array_length_get } from "./generatedStructs";
export class ArrayWrapper extends BaseProxyTrap<ArrayEntry>
implements ProxyHandler<{}> {
public get(target: {}, p: PropertyKey): any {
export class ArrayWrapper extends BaseProxyTrap
implements ProxyHandler<Record<string, unknown>> {
public get(target: Record<string, unknown>, p: PropertyKey): any {
if (p === INTERNAL_API_SYMBOL) {

@@ -29,4 +29,4 @@ return this;

if (p in this && p !== "constructor") {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return this[p];

@@ -36,3 +36,3 @@ }

if (p === "length") {
return arrayGetMetadata(this.carrier, this.entryPointer).length;
return array_length_get(this.carrier.heap, this.entryPointer);
}

@@ -53,8 +53,11 @@

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return target[p];
}
public deleteProperty(target: {}, p: PropertyKey): boolean {
public deleteProperty(
target: Record<string, unknown>,
p: PropertyKey
): boolean {
const index = typeof p === "number" ? p : Number.parseInt(p as string, 10);

@@ -70,3 +73,3 @@

public ownKeys(): PropertyKey[] {
const length = arrayGetMetadata(this.carrier, this.entryPointer).length;
const length = array_length_get(this.carrier.heap, this.entryPointer);

@@ -76,3 +79,3 @@ return [...new Array(length).keys(), "length"];

public getOwnPropertyDescriptor(target: {}, prop: any) {
public getOwnPropertyDescriptor(target: Record<string, unknown>, prop: any) {
if (prop === "length") {

@@ -89,3 +92,3 @@ return { configurable: false, enumerable: false, writable: true };

public has(target: {}, p: PropertyKey): boolean {
public has(target: Record<string, unknown>, p: PropertyKey): boolean {
if (p === INTERNAL_API_SYMBOL) {

@@ -95,3 +98,3 @@ return true;

const length = arrayGetMetadata(this.carrier, this.entryPointer).length;
const length = array_length_get(this.carrier.heap, this.entryPointer);

@@ -107,3 +110,7 @@ if (typeof p === "number") {

public set(target: {}, accessedProp: PropertyKey, value: any): boolean {
public set(
target: Record<string, unknown>,
accessedProp: PropertyKey,
value: any
): boolean {
if (typeof accessedProp === "symbol") {

@@ -118,4 +125,6 @@ throw new IllegalArrayIndexError();

const currentLength = arrayGetMetadata(this.carrier, this.entryPointer)
.length;
const currentLength = array_length_get(
this.carrier.heap,
this.entryPointer
);

@@ -187,3 +196,3 @@ if (currentLength === value) {

length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -201,3 +210,3 @@ }

length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -220,3 +229,3 @@ }

length = arrayGetMetadata(this.carrier, this.entryPointer).length;
length = array_length_get(this.carrier.heap, this.entryPointer);
} while (index < length);

@@ -234,14 +243,16 @@ }

public splice(start: number, deleteCount?: number, ...items: any[]) {
return arraySplice(
this.externalArgs,
this.carrier,
this.entryPointer,
start,
deleteCount,
...items
);
return allocationsTransaction(() => {
return arraySplice(
this.externalArgs,
this.carrier,
this.entryPointer,
start,
deleteCount,
...items
);
}, this.carrier.allocator);
}
public reverse() {
arrayReverse(this.externalArgs, this.carrier, this.entryPointer);
arrayReverse(this.carrier, this.entryPointer);
return this;

@@ -263,3 +274,3 @@ }

return arrayGetMetadata(this.carrier, this.entryPointer).length;
return array_length_get(this.carrier.heap, this.entryPointer);
}

@@ -287,3 +298,3 @@

public defineProperty(): // target: {},
public defineProperty(): // target: Record<string, unknown>,
// p: PropertyKey,

@@ -312,2 +323,4 @@ // attributes: PropertyDescriptor

return new Proxy(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
[],

@@ -314,0 +327,0 @@ new ArrayWrapper(externalArgs, globalCarrier, entryPointer)

@@ -1,17 +0,6 @@

import {
ExternalArgs,
GlobalCarrier,
InternalAPI,
DateEntry,
ArrayEntry,
ObjectEntry,
MapEntry,
SetEntry,
} from "./interfaces";
import { incrementRefCount, decrementRefCount, readEntry } from "./store";
import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
import { incrementRefCount, decrementRefCount } from "./store";
import { WrapperDestroyed } from "./exceptions";
export class BaseProxyTrap<
T extends ObjectEntry | DateEntry | ArrayEntry | MapEntry | SetEntry
> implements InternalAPI {
export abstract class BaseProxyTrap implements InternalAPI {
constructor(

@@ -22,11 +11,7 @@ protected externalArgs: ExternalArgs,

) {
incrementRefCount(this.externalArgs, this.carrier, this.entryPointer);
incrementRefCount(this.carrier.heap, this.entryPointer);
}
public destroy() {
const newRefCount = decrementRefCount(
this.externalArgs,
this.carrier,
this.entryPointer
);
const newRefCount = decrementRefCount(this.carrier.heap, this.entryPointer);
this._entryPointer = 0;

@@ -60,6 +45,2 @@

}
protected get entry(): T {
return readEntry(this.carrier, this.entryPointer) as T;
}
}

@@ -15,1 +15,2 @@ export const LOCK_OFFSET = 0;

export const FALSE_KNOWN_ADDRESS = 3;
export const MAX_64_BIG_INT = BigInt("0xFFFFFFFFFFFFFFFF");

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

import { ExternalArgs, GlobalCarrier, DateEntry } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { readEntry, writeEntry } from "./store";
import { ENTRY_TYPE } from "./entry-types";

@@ -8,2 +7,7 @@ import { INTERNAL_API_SYMBOL } from "./symbols";

import { BaseProxyTrap } from "./BaseProxyTrap";
import {
date_set_all,
date_refsCount_get,
date_timestamp_get,
} from "./generatedStructs";

@@ -62,4 +66,3 @@ const getFunctions: Array<keyof Date> = [

export class DateWrapper extends BaseProxyTrap<DateEntry>
implements ProxyHandler<Date> {
export class DateWrapper extends BaseProxyTrap implements ProxyHandler<Date> {
private dateObjectForReuse: Date;

@@ -109,13 +112,17 @@ private useMeToGiveNamesToFunctionsAndCacheThem: any;

private updateDateObjectForReuse() {
const entry = readEntry(this.carrier, this.entryPointer) as DateEntry;
this.dateObjectForReuse.setTime(entry.value);
this.dateObjectForReuse.setTime(
date_timestamp_get(this.carrier.heap, this.entryPointer)
);
}
private persistDateObject() {
writeEntry(this.carrier, this.entryPointer, {
type: ENTRY_TYPE.DATE,
refsCount: this.entry.refsCount,
value: this.dateObjectForReuse.getTime(),
});
date_set_all(
this.carrier.heap,
this.entryPointer,
ENTRY_TYPE.DATE,
date_refsCount_get(this.carrier.heap, this.entryPointer),
// padding
0,
this.dateObjectForReuse.getTime()
);
}

@@ -122,0 +129,0 @@

@@ -25,12 +25,10 @@ import { getInternalAPI } from "./utils";

const { allocator, heap } = internalApi.getCarrier();
for (const address of addressesToFree.leafAddresses) {
internalApi.getCarrier().allocator.free(address);
allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(
internalApi.getExternalArgs(),
internalApi.getCarrier(),
address
);
decrementRefCount(heap, address);
}

@@ -37,0 +35,0 @@

import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { ENTRY_TYPE } from "./entry-types";
import { createObjectWrapper } from "./objectWrapper";

@@ -7,3 +7,3 @@ import { createArrayWrapper } from "./arrayWrapper";

import { getCacheFor } from "./externalObjectsCache";
import { decrementRefCount, readEntry } from "./store";
import { decrementRefCount } from "./store";
import { getAllLinkedAddresses } from "./getAllLinkedAddresses";

@@ -18,6 +18,9 @@ import { createMapWrapper } from "./mapWrapper";

} from "./consts";
import {
typeOnly_type_get,
number_value_get,
bigint_value_get,
} from "./generatedStructs";
import { readString } from "./readString";
// declare const FinalizationGroup: any;
// declare const WeakRef: any;
const TYPE_TO_FACTORY = {

@@ -52,44 +55,53 @@ [ENTRY_TYPE.OBJECT]: createObjectWrapper,

const valueEntry = readEntry(carrier, pointerToEntry);
const entryType: ENTRY_TYPE = typeOnly_type_get(carrier.heap, pointerToEntry);
if (isPrimitiveEntryType(valueEntry.type)) {
return valueEntry.value;
switch (entryType) {
case ENTRY_TYPE.NUMBER:
return number_value_get(carrier.heap, pointerToEntry);
break;
case ENTRY_TYPE.STRING:
return readString(carrier.heap, pointerToEntry);
break;
case ENTRY_TYPE.BIGINT_POSITIVE:
return bigint_value_get(carrier.heap, pointerToEntry);
break;
case ENTRY_TYPE.BIGINT_NEGATIVE:
return bigint_value_get(carrier.heap, pointerToEntry) * BigInt("-1");
break;
}
// this is an invariant
if (
valueEntry.type === ENTRY_TYPE.OBJECT ||
valueEntry.type === ENTRY_TYPE.DATE ||
valueEntry.type === ENTRY_TYPE.ARRAY ||
valueEntry.type === ENTRY_TYPE.MAP ||
valueEntry.type === ENTRY_TYPE.SET
!(
entryType === ENTRY_TYPE.OBJECT ||
entryType === ENTRY_TYPE.DATE ||
entryType === ENTRY_TYPE.ARRAY ||
entryType === ENTRY_TYPE.MAP ||
entryType === ENTRY_TYPE.SET
)
) {
const cache = getCacheFor(carrier, (key) => {
finalizer(key, carrier, externalArgs);
});
throw new Error("Nope Nope Nope");
}
let ret = cache.get(pointerToEntry);
const cache = getCacheFor(carrier, (key) => {
finalizer(key, carrier);
});
if (!ret) {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
ret = TYPE_TO_FACTORY[valueEntry.type](
externalArgs,
carrier,
pointerToEntry
);
cache.set(pointerToEntry, ret);
}
let ret = cache.get(pointerToEntry);
return ret;
if (!ret) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ret = TYPE_TO_FACTORY[entryType](externalArgs, carrier, pointerToEntry);
cache.set(pointerToEntry, ret);
}
throw new Error("unsupported yet");
return ret;
}
function finalizer(
memoryAddress: number,
carrier: GlobalCarrier,
externalArgs: ExternalArgs
) {
const newRefsCount = decrementRefCount(externalArgs, carrier, memoryAddress);
function finalizer(memoryAddress: number, carrier: GlobalCarrier) {
const newRefsCount = decrementRefCount(carrier.heap, memoryAddress);

@@ -104,5 +116,5 @@ if (newRefsCount === 0) {

for (const address of freeUs.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
decrementRefCount(carrier.heap, address);
}
}
}
import { WeakValueMap } from "./WeakValueMap";
// eslint-disable-next-line @typescript-eslint/ban-types
const externalObjectsCache = new WeakMap<object, Map<number, any>>();

@@ -9,2 +10,3 @@

export function getCacheFor(
// eslint-disable-next-line @typescript-eslint/ban-types
obj: object,

@@ -11,0 +13,0 @@ externalFinalizer?: (key: number) => void

@@ -28,5 +28,2 @@ /* eslint-env jest */

});
// const a = objectBuffer.nestedObject;
// getInternalAPI(a).destroy();
// // a.toString();

@@ -101,8 +98,5 @@ const carrier = getInternalAPI(objectBuffer).getCarrier();

// const a = objectBuffer.nestedObject;
// getInternalAPI(a).destroy();
// // a.toString();
const carrier = getInternalAPI(objectBuffer).getCarrier();
const entryPointer = getInternalAPI(objectBuffer).getEntryPointer();
getInternalAPI(objectBuffer).destroy();

@@ -113,3 +107,3 @@

false,
allocatedAddresses[allocatedAddresses.length - 1]
entryPointer
);

@@ -120,55 +114,2 @@

);
expect([...linkedAddresses.leafAddresses].slice().sort())
.toMatchInlineSnapshot(`
Array [
1008,
1032,
1056,
1072,
1096,
112,
1120,
1144,
1160,
1184,
1216,
128,
144,
168,
200,
216,
240,
280,
296,
312,
336,
360,
376,
400,
424,
448,
464,
48,
488,
512,
528,
560,
584,
616,
632,
656,
680,
704,
72,
728,
744,
848,
880,
912,
936,
976,
992,
]
`);
});

@@ -195,8 +136,9 @@

expect(memoryStats(objectBuffer)).toMatchInlineSnapshot(`
Object {
"available": 816,
"used": 1232,
}
`);
Object {
"available": 656,
"used": 1392,
}
`);
const entryPointer = getInternalAPI(objectBuffer).getEntryPointer();
const carrier = getInternalAPI(objectBuffer).getCarrier();

@@ -209,3 +151,3 @@

false,
allocatedAddresses[allocatedAddresses.length - 1]
entryPointer
);

@@ -212,0 +154,0 @@

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

import { readEntry } from "./store";
import { GlobalCarrier } from "./interfaces";

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

import { isKnownAddressValuePointer } from "./utils";
import {
typeOnly_type_get,
string_charsPointer_get,
typeAndRc_refsCount_get,
object_pointerToHashMap_get,
array_dataspacePointer_get,
array_length_get,
} from "./generatedStructs";

@@ -53,2 +60,3 @@ export function getAllLinkedAddresses(

) {
const { heap } = carrier;
if (

@@ -62,7 +70,8 @@ isKnownAddressValuePointer(entryPointer) ||

const entry = readEntry(carrier, entryPointer);
const entryType = typeOnly_type_get(heap, entryPointer);
// to be used ONLY if the type has ref counter
const refsCount = typeAndRc_refsCount_get(heap, entryPointer);
switch (entry.type) {
switch (entryType) {
case ENTRY_TYPE.NUMBER:
case ENTRY_TYPE.STRING:
case ENTRY_TYPE.BIGINT_NEGATIVE:

@@ -73,10 +82,15 @@ case ENTRY_TYPE.BIGINT_POSITIVE:

case ENTRY_TYPE.STRING:
leafAddresses.add(string_charsPointer_get(heap, entryPointer));
leafAddresses.add(entryPointer);
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.MAP:
case ENTRY_TYPE.SET:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);
getObjectOrMapOrSetAddresses(
carrier,
entry.value,
object_pointerToHashMap_get(heap, entryPointer),
leafAddresses,

@@ -88,14 +102,14 @@ addressesToProcessQueue

}
break;
case ENTRY_TYPE.ARRAY:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);
leafAddresses.add(entry.value);
for (let i = 0; i < entry.allocatedLength; i += 1) {
leafAddresses.add(array_dataspacePointer_get(heap, entryPointer));
const arrayLength = array_length_get(heap, entryPointer);
for (let i = 0; i < arrayLength; i += 1) {
const valuePointer =
carrier.uint32[
(entry.value + i * Uint32Array.BYTES_PER_ELEMENT) /
(array_dataspacePointer_get(heap, entryPointer) +
i * Uint32Array.BYTES_PER_ELEMENT) /
Uint32Array.BYTES_PER_ELEMENT

@@ -112,3 +126,3 @@ ];

case ENTRY_TYPE.DATE:
if (entry.refsCount <= 1 || ignoreRefCount) {
if (refsCount <= 1 || ignoreRefCount) {
leafAddresses.add(entryPointer);

@@ -121,5 +135,3 @@ } else {

default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");
throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");
}

@@ -126,0 +138,0 @@ }

@@ -18,5 +18,5 @@ /* eslint-env jest */

} from "./hashmap";
import { GlobalCarrier, StringEntry } from "../interfaces";
import { readEntry } from "../store";
import { GlobalCarrier } from "../interfaces";
import { externalArgsApiToExternalArgsApi } from "../utils";
import { readString } from "../readString";

@@ -182,5 +182,4 @@ describe("hashmap", () => {

}
expect(
values.map((v) => (readEntry(carrier, v.keyPointer) as StringEntry).value)
).toMatchInlineSnapshot(`
expect(values.map((v) => readString(carrier.heap, v.keyPointer)))
.toMatchInlineSnapshot(`
Array [

@@ -209,6 +208,2 @@ "a",

"v",
"w",
"x",
"y",
"z",
]

@@ -247,33 +242,33 @@ `);

expect(memAvailableAfterEachStep).toMatchInlineSnapshot(`
Array [
1904,
1840,
1776,
1712,
1648,
1584,
1520,
1456,
1352,
1288,
1224,
1160,
1096,
1032,
968,
904,
760,
696,
632,
568,
504,
440,
376,
312,
248,
184,
120,
120,
]
`);
Array [
1904,
1824,
1744,
1664,
1584,
1504,
1424,
1344,
1224,
1144,
1064,
984,
904,
824,
744,
664,
504,
416,
336,
256,
176,
96,
16,
0,
0,
0,
0,
0,
]
`);
});

@@ -309,53 +304,63 @@

expect(r).toMatchInlineSnapshot(`
Object {
"pointers": Array [
48,
664,
120,
136,
200,
264,
328,
392,
456,
520,
584,
648,
752,
816,
152,
176,
216,
240,
280,
304,
344,
368,
408,
432,
472,
496,
536,
560,
600,
624,
72,
96,
768,
792,
],
"pointersToValuePointers": Array [
152,
216,
280,
344,
408,
472,
536,
600,
72,
768,
],
}
`);
Object {
"pointers": Array [
48,
792,
120,
136,
216,
296,
376,
456,
536,
616,
696,
776,
896,
976,
200,
152,
176,
280,
232,
256,
360,
312,
336,
440,
392,
416,
520,
472,
496,
600,
552,
576,
680,
632,
656,
760,
712,
736,
880,
72,
96,
960,
912,
936,
],
"pointersToValuePointers": Array [
152,
232,
312,
392,
472,
552,
632,
712,
72,
912,
],
}
`);

@@ -362,0 +367,0 @@ expect(r.pointers.sort()).toEqual(allocations.sort());

import { MAP_MACHINE, NODE_MACHINE } from "./memoryLayout";
import { GlobalCarrier, ExternalArgs } from "../interfaces";
import {
GlobalCarrier,
ExternalArgs,
NumberEntry,
StringEntry,
} from "../interfaces";
import {
hashCodeInPlace,

@@ -13,8 +8,7 @@ hashCodeExternalValue,

} from "./hashmapUtils";
import { primitiveValueToEntry } from "../utils";
import { strByteLength } from "../utils";
import { stringEncodeInto } from "../stringEncodeInto";
import {
sizeOfEntry,
writeEntry,
readEntry,
compareStringOrNumberEntriesInPlace,
readNumberOrString,
} from "../store";

@@ -32,2 +26,12 @@ import { ENTRY_TYPE } from "../entry-types";

import { MemoryOperator } from "../memoryMachinery";
import {
number_size,
string_size,
number_set_all,
string_set_all,
number_value_place,
number_value_ctor,
typeOnly_type_get,
string_charsPointer_get,
} from "../generatedStructs";

@@ -69,5 +73,5 @@ export function createHashMap(

const mapOperator = MAP_MACHINE.createOperator(carrier, mapPointer);
const keyEntry = primitiveValueToEntry(externalKeyValue) as
| NumberEntry
| StringEntry;
// const keyEntry = primitiveValueToEntry(externalKeyValue) as
// | NumberEntry
// | StringEntry;

@@ -77,19 +81,41 @@ // allocate all possible needed memory upfront, so we won't oom in the middle of something

const memoryForNewNode = carrier.allocator.calloc(NODE_MACHINE.map.SIZE_OF);
const memorySizeOfKey = sizeOfEntry(keyEntry);
const keyEntryMemory = carrier.allocator.calloc(memorySizeOfKey);
let keyMemoryEntryPointer;
let keyDataMemoryStart: number;
let keyDataMemoryLength: number;
writeEntry(carrier, keyEntryMemory, keyEntry);
if (typeof externalKeyValue === "number") {
keyMemoryEntryPointer = carrier.allocator.calloc(number_size);
number_set_all(
carrier.heap,
keyMemoryEntryPointer,
ENTRY_TYPE.NUMBER,
externalKeyValue
);
const keyHeaderOverhead =
keyEntry.type === ENTRY_TYPE.STRING
? // type + string length
8 + 4
: // type
8;
keyDataMemoryStart = keyMemoryEntryPointer + number_value_place;
keyDataMemoryLength = number_value_ctor.BYTES_PER_ELEMENT;
} else {
keyMemoryEntryPointer = carrier.allocator.calloc(string_size);
keyDataMemoryLength = strByteLength(externalKeyValue);
keyDataMemoryStart = carrier.allocator.calloc(keyDataMemoryLength);
stringEncodeInto(
carrier.heap.Uint8Array,
keyDataMemoryStart,
externalKeyValue
);
string_set_all(
carrier.heap,
keyMemoryEntryPointer,
ENTRY_TYPE.STRING,
keyDataMemoryLength,
keyDataMemoryStart
);
}
const keyHashCode = hashCodeInPlace(
carrier.uint8,
mapOperator.get("CAPACITY"),
// + 1 for the type of key
keyEntryMemory + keyHeaderOverhead,
memorySizeOfKey - keyHeaderOverhead
keyDataMemoryStart,
keyDataMemoryLength
);

@@ -110,5 +136,5 @@

!compareStringOrNumberEntriesInPlace(
carrier,
carrier.heap,
commonNodeOperator.get("KEY_POINTER"),
keyEntryMemory
keyMemoryEntryPointer
)

@@ -134,3 +160,4 @@ ) {

// we don't need the new memory
carrier.allocator.free(keyEntryMemory);
// @todo Free here also the string data
carrier.allocator.free(keyMemoryEntryPointer);
carrier.allocator.free(memoryForNewNode);

@@ -141,3 +168,3 @@

commonNodeOperator.startAddress = memoryForNewNode;
commonNodeOperator.set("KEY_POINTER", keyEntryMemory);
commonNodeOperator.set("KEY_POINTER", keyMemoryEntryPointer);
commonNodeOperator.set(

@@ -163,3 +190,2 @@ "LINKED_LIST_ITEM_POINTER",

shouldRehash(
mapOperator.get("LINKED_LIST_SIZE"),
mapOperator.get("CAPACITY"),

@@ -205,7 +231,5 @@ mapOperator.get("USED_CAPACITY"),

while (node.startAddress !== 0) {
const keyEntry = readEntry(carrier, node.get("KEY_POINTER")) as
| NumberEntry
| StringEntry;
const keyValue = readNumberOrString(carrier.heap, node.get("KEY_POINTER"));
if (keyEntry.value === externalKeyValue) {
if (keyValue === externalKeyValue) {
return ptrToPtr;

@@ -275,2 +299,11 @@ }

if (
typeOnly_type_get(carrier.heap, nodeOperator.get("KEY_POINTER")) ===
ENTRY_TYPE.STRING
) {
carrier.allocator.free(
string_charsPointer_get(carrier.heap, nodeOperator.get("KEY_POINTER"))
);
}
carrier.allocator.free(nodeOperator.get("KEY_POINTER"));

@@ -357,2 +390,10 @@ carrier.allocator.free(nodeOperator.startAddress);

pointersToValuePointers.push(nodeOperator.pointerTo("VALUE_POINTER"));
if (
typeOnly_type_get(carrier.heap, nodeOperator.get("KEY_POINTER")) ===
ENTRY_TYPE.STRING
) {
pointers.push(
string_charsPointer_get(carrier.heap, nodeOperator.get("KEY_POINTER"))
);
}
pointers.push(nodePointer, nodeOperator.get("KEY_POINTER"));

@@ -460,3 +501,2 @@ }

function shouldRehash(
nodesCount: number,
buckets: number,

@@ -463,0 +503,0 @@ fullBuckets: number,

import { ENTRY_TYPE } from "./entry-types";
import { Heap } from "../structsGenerator/consts";

@@ -91,2 +92,3 @@ export type primitive = string | number | bigint | boolean | undefined | null;

allocator: import("@thi.ng/malloc").IMemPool;
heap: Heap;
}

@@ -93,0 +95,0 @@

@@ -9,6 +9,2 @@ /* eslint-env jest */

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// import jestDiff from "jest-diff";
import {

@@ -15,0 +11,0 @@ linkedListItemInsert,

@@ -0,1 +1,5 @@

/* istanbul ignore file */
// I'm not sure how to test that yet
import { invariant } from "./utils";

@@ -2,0 +6,0 @@ import { getUnderlyingArrayBuffer } from "./api";

@@ -0,8 +1,3 @@

import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
import {
ExternalArgs,
GlobalCarrier,
MapEntry,
InternalAPI,
} from "./interfaces";
import {
deleteObjectPropertyEntryByKey,

@@ -25,5 +20,5 @@ objectGet,

import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class MapWrapper<K extends string | number, V>
extends BaseProxyTrap<MapEntry>
export class MapWrapper<K extends string | number, V> extends BaseProxyTrap
implements Map<K, V> {

@@ -44,3 +39,6 @@ clear(): void {

get size(): number {
return hashMapSize(this.carrier, this.entry.value);
return hashMapSize(
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
);
}

@@ -55,3 +53,3 @@

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -81,3 +79,3 @@ const { valuePointer, keyPointer } = hashMapNodePointerToKeyValue(

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -97,3 +95,3 @@ const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -130,3 +128,8 @@ const { valuePointer } = hashMapNodePointerToKeyValue(

return objectGet(this.externalArgs, this.carrier, this.entry.value, p);
return objectGet(
this.externalArgs,
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p
);
}

@@ -140,5 +143,4 @@

return deleteObjectPropertyEntryByKey(
this.externalArgs,
this.carrier,
this.entry.value,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p

@@ -153,3 +155,9 @@ );

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return (
hashMapNodeLookup(
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p
) !== 0
);
}

@@ -163,3 +171,9 @@

allocationsTransaction(() => {
objectSet(this.externalArgs, this.carrier, this.entry.value, p, value);
objectSet(
this.externalArgs,
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p,
value
);
}, this.carrier.allocator);

@@ -166,0 +180,0 @@

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

entry[0],
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
entry[1].type,

@@ -45,0 +45,0 @@ ])

@@ -40,4 +40,2 @@ import { GlobalCarrier } from "./interfaces";

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// dataViewInstance = undefined;

@@ -167,5 +165,5 @@

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return Object.fromEntries(newObjectEntries);
}

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

import { ObjectEntry, ExternalArgs, GlobalCarrier } from "./interfaces";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import {

@@ -17,6 +17,7 @@ getObjectPropertiesEntries,

import { hashMapNodeLookup } from "./hashmap/hashmap";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class ObjectWrapper extends BaseProxyTrap<ObjectEntry>
implements ProxyHandler<{}> {
public get(target: {}, p: PropertyKey): any {
export class ObjectWrapper extends BaseProxyTrap
implements ProxyHandler<Record<string, unknown>> {
public get(target: Record<string, unknown>, p: PropertyKey): any {
if (p === INTERNAL_API_SYMBOL) {

@@ -30,6 +31,14 @@ return this;

return objectGet(this.externalArgs, this.carrier, this.entry.value, p);
return objectGet(
this.externalArgs,
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p
);
}
public deleteProperty(target: {}, p: PropertyKey): boolean {
public deleteProperty(
target: Record<string, unknown>,
p: PropertyKey
): boolean {
if (typeof p === "symbol") {

@@ -40,5 +49,4 @@ return false;

return deleteObjectPropertyEntryByKey(
this.externalArgs,
this.carrier,
this.entry.value,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p

@@ -51,3 +59,3 @@ );

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
);

@@ -61,3 +69,3 @@

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
);

@@ -68,3 +76,6 @@

public getOwnPropertyDescriptor(target: {}, p: PropertyKey) {
public getOwnPropertyDescriptor(
target: Record<string, unknown>,
p: PropertyKey
) {
if (this.has(target, p)) {

@@ -77,3 +88,3 @@ return { configurable: true, enumerable: true };

public has(target: {}, p: PropertyKey) {
public has(target: Record<string, unknown>, p: PropertyKey) {
if (p === INTERNAL_API_SYMBOL) {

@@ -87,6 +98,16 @@ return true;

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return (
hashMapNodeLookup(
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p
) !== 0
);
}
public set(target: {}, p: PropertyKey, value: any): boolean {
public set(
target: Record<string, unknown>,
p: PropertyKey,
value: any
): boolean {
if (typeof p === "symbol") {

@@ -97,3 +118,9 @@ throw new IllegalObjectPropConfigError();

allocationsTransaction(() => {
objectSet(this.externalArgs, this.carrier, this.entry.value, p, value);
objectSet(
this.externalArgs,
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p,
value
);
}, this.carrier.allocator);

@@ -116,3 +143,3 @@

public defineProperty(): // target: {},
public defineProperty(): // target: Record<string, unknown>,
// p: PropertyKey,

@@ -119,0 +146,0 @@ // attributes: PropertyDescriptor

@@ -0,16 +1,6 @@

import { ExternalArgs, GlobalCarrier } from "./interfaces";
import {
ExternalArgs,
GlobalCarrier,
StringEntry,
NumberEntry,
MapEntry,
SetEntry,
} from "./interfaces";
import {
readEntry,
writeValueInPtrToPtrAndHandleMemory,
handleArcForDeletedValuePointer,
decrementRefCount,
writeEntry,
setRefCount,
} from "./store";

@@ -27,5 +17,13 @@ import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";

import { getAllLinkedAddresses } from "./getAllLinkedAddresses";
import {
typeOnly_type_get,
number_value_get,
typeAndRc_refsCount_get,
typeAndRc_refsCount_set,
object_pointerToHashMap_set,
} from "./generatedStructs";
import { ENTRY_TYPE } from "./entry-types";
import { readString } from "./readString";
export function deleteObjectPropertyEntryByKey(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,

@@ -47,7 +45,7 @@ hashmapPointer: number,

const deletedValuePointer =
carrier.uint32[
carrier.heap.Uint32Array[
deletedValuePointerToPointer / Uint32Array.BYTES_PER_ELEMENT
];
handleArcForDeletedValuePointer(externalArgs, carrier, deletedValuePointer);
handleArcForDeletedValuePointer(carrier, deletedValuePointer);

@@ -72,10 +70,15 @@ return true;

const keyEntry = readEntry(carrier, keyPointer) as
| StringEntry
| NumberEntry;
const typeOfKeyEntry:
| ENTRY_TYPE.NUMBER
| ENTRY_TYPE.STRING = typeOnly_type_get(carrier.heap, keyPointer);
const key =
typeOfKeyEntry === ENTRY_TYPE.NUMBER
? number_value_get(carrier.heap, keyPointer)
: readString(carrier.heap, keyPointer);
foundValues.push({
valuePointer:
carrier.uint32[valuePointer / Uint32Array.BYTES_PER_ELEMENT],
key: keyEntry.value,
key,
});

@@ -92,3 +95,3 @@ }

p: string | number,
value: any
value: unknown
) {

@@ -113,6 +116,2 @@ const ptrToPtr = hashMapInsertUpdate(

if (valuePointer === 0) {
return undefined;
}
return entryToFinalJavaScriptValue(

@@ -155,6 +154,5 @@ externalArgs,

) {
const entry = readEntry(carrier, mapOrSetPtr) as MapEntry | SetEntry;
// we fake the entry refCount as zero so getAllLinkedAddresses will visit what's needed
const prevCount = setRefCount(carrier, mapOrSetPtr, 0);
const prevCount = typeAndRc_refsCount_get(carrier.heap, mapOrSetPtr);
typeAndRc_refsCount_set(carrier.heap, mapOrSetPtr, 0);

@@ -182,13 +180,12 @@ const { leafAddresses, arcAddresses } = getAllLinkedAddresses(

decrementRefCount(externalArgs, carrier, address);
decrementRefCount(carrier.heap, address);
}
// hashmapClearFree(externalArgs, carrier, entry.value);
// Restore real ref count
setRefCount(carrier, mapOrSetPtr, prevCount);
entry.value = createHashMap(carrier, externalArgs.hashMapMinInitialCapacity);
writeEntry(carrier, mapOrSetPtr, entry);
typeAndRc_refsCount_set(carrier.heap, mapOrSetPtr, prevCount);
object_pointerToHashMap_set(
carrier.heap,
mapOrSetPtr,
createHashMap(carrier, externalArgs.hashMapMinInitialCapacity)
);
}

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

/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck

@@ -2,0 +3,0 @@

@@ -1,12 +0,15 @@

import {
primitiveValueToEntry,
isPrimitive,
getOurPointerIfApplicable,
} from "./utils";
import { appendEntry } from "./store";
import { objectSaver, mapSaver, setSaver } from "./objectSaver";
import { arraySaver } from "./arraySaver";
import { getOurPointerIfApplicable, strByteLength } from "./utils";
import { ExternalArgs, GlobalCarrier } from "./interfaces";
import { ENTRY_TYPE } from "./entry-types";
import {
number_size,
number_set_all,
bigint_size,
bigint_set_all,
string_size,
string_set_all,
date_size,
date_set_all,
} from "./generatedStructs";
import {
UNDEFINED_KNOWN_ADDRESS,

@@ -16,81 +19,220 @@ NULL_KNOWN_ADDRESS,

FALSE_KNOWN_ADDRESS,
MAX_64_BIG_INT,
} from "./consts";
import { arraySaverIterative } from "./arraySaverIterative";
import {
objectSaverIterative,
mapSaverIterative,
setSaverIterative,
} from "./objectSaverIterative";
import { stringEncodeInto } from "./stringEncodeInto";
/**
* Returns pointer for the value
*/
export function saveValue(
export function saveValueIterative(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
referencedPointers: number[],
// Not really working yet. we need iterative saving for it
visitedValuesOnCurrentSaveOperation: Map<object, number>,
value: any
referencedExistingPointers: number[],
initialValuePtrToPtr: number,
initialValue: unknown
) {
let valuePointer = 0;
let maybeOurPointer: number | undefined;
const valuesToSave = [initialValue];
const pointersToSaveTo = [initialValuePtrToPtr];
const {
heap: { Uint32Array: uint32 },
allocator,
heap,
} = carrier;
if (value === undefined) {
return UNDEFINED_KNOWN_ADDRESS;
}
while (valuesToSave.length !== 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const valueToSave = valuesToSave.pop()!;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const ptrToPtrToSaveTo = pointersToSaveTo.pop()!;
if (value === null) {
return NULL_KNOWN_ADDRESS;
}
// Handler well-known values
if (valueToSave === undefined) {
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = UNDEFINED_KNOWN_ADDRESS;
continue;
}
if (value === true) {
return TRUE_KNOWN_ADDRESS;
}
if (valueToSave === null) {
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = NULL_KNOWN_ADDRESS;
continue;
}
if (value === false) {
return FALSE_KNOWN_ADDRESS;
}
if (valueToSave === true) {
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = TRUE_KNOWN_ADDRESS;
continue;
}
if (isPrimitive(value)) {
const entry = primitiveValueToEntry(value);
valuePointer = appendEntry(externalArgs, carrier, entry);
} else if (
(maybeOurPointer = getOurPointerIfApplicable(value, carrier.allocator))
) {
valuePointer = maybeOurPointer;
referencedPointers.push(valuePointer);
} else if (
(maybeOurPointer = visitedValuesOnCurrentSaveOperation.get(value))
) {
valuePointer = maybeOurPointer;
referencedPointers.push(valuePointer);
} else if (Array.isArray(value)) {
valuePointer = arraySaver(externalArgs, carrier, referencedPointers, value);
} else if (value instanceof Date) {
valuePointer = appendEntry(externalArgs, carrier, {
type: ENTRY_TYPE.DATE,
refsCount: 1,
value: value.getTime(),
});
} else if (value instanceof Map) {
valuePointer = mapSaver(
externalArgs,
carrier,
referencedPointers,
visitedValuesOnCurrentSaveOperation,
value
if (valueToSave === false) {
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = FALSE_KNOWN_ADDRESS;
continue;
}
switch (typeof valueToSave) {
case "number":
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = allocator.calloc(number_size);
number_set_all(
heap,
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT],
ENTRY_TYPE.NUMBER,
valueToSave
);
continue;
break;
case "string":
// eslint-disable-next-line no-case-declarations
const stringBytesLength = strByteLength(valueToSave);
// eslint-disable-next-line no-case-declarations
const stringDataPointer = allocator.calloc(stringBytesLength);
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = allocator.calloc(string_size);
stringEncodeInto(heap.Uint8Array, stringDataPointer, valueToSave);
string_set_all(
heap,
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT],
ENTRY_TYPE.STRING,
stringBytesLength,
stringDataPointer
);
continue;
break;
case "bigint":
if (valueToSave > MAX_64_BIG_INT || valueToSave < -MAX_64_BIG_INT) {
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = UNDEFINED_KNOWN_ADDRESS;
continue;
// Maybe don't make undefined but throw, or clamp
// throw new Error("MAX_64_BIG_INT");
}
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = allocator.calloc(bigint_size);
bigint_set_all(
heap,
uint32[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT],
valueToSave > 0
? ENTRY_TYPE.BIGINT_POSITIVE
: ENTRY_TYPE.BIGINT_NEGATIVE,
valueToSave * (valueToSave > 0 ? BigInt("1") : BigInt("-1"))
);
continue;
break;
case "function":
// Nope Nope Nope
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = UNDEFINED_KNOWN_ADDRESS;
continue;
break;
case "symbol":
// not supported, write undefined
uint32[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = UNDEFINED_KNOWN_ADDRESS;
continue;
break;
// we will never get here
case "undefined":
continue;
break;
// we will never get here
case "boolean":
continue;
break;
}
const maybeOurPointerFromSymbol = getOurPointerIfApplicable(
valueToSave,
carrier.allocator
);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else if (value instanceof Set) {
valuePointer = setSaver(externalArgs, carrier, value);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else if (typeof value === "object") {
valuePointer = objectSaver(
if (maybeOurPointerFromSymbol) {
referencedExistingPointers.push(maybeOurPointerFromSymbol);
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = maybeOurPointerFromSymbol;
continue;
}
if (Array.isArray(valueToSave)) {
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = arraySaverIterative(
externalArgs.arrayAdditionalAllocation,
carrier,
valuesToSave,
pointersToSaveTo,
valueToSave
);
continue;
}
if (valueToSave instanceof Date) {
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = allocator.calloc(date_size);
date_set_all(
heap,
heap.Uint32Array[ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT],
ENTRY_TYPE.DATE,
1,
0,
valueToSave.getTime()
);
continue;
}
if (valueToSave instanceof Map) {
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = mapSaverIterative(
externalArgs,
carrier,
valuesToSave,
pointersToSaveTo,
valueToSave
);
continue;
}
if (valueToSave instanceof Set) {
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = setSaverIterative(externalArgs, carrier, valueToSave);
continue;
}
// Plain object? I hope so
heap.Uint32Array[
ptrToPtrToSaveTo / Uint32Array.BYTES_PER_ELEMENT
] = objectSaverIterative(
externalArgs,
carrier,
referencedPointers,
visitedValuesOnCurrentSaveOperation,
value
valuesToSave,
pointersToSaveTo,
valueToSave
);
visitedValuesOnCurrentSaveOperation.set(value, valuePointer);
} else {
throw new Error("unsupported yet");
}
return valuePointer;
}

@@ -0,8 +1,3 @@

import { ExternalArgs, GlobalCarrier, InternalAPI } from "./interfaces";
import {
ExternalArgs,
GlobalCarrier,
MapEntry,
InternalAPI,
} from "./interfaces";
import {
deleteObjectPropertyEntryByKey,

@@ -24,5 +19,5 @@ objectSet,

import { entryToFinalJavaScriptValue } from "./entryToFinalJavaScriptValue";
import { object_pointerToHashMap_get } from "./generatedStructs";
export class SetWrapper<K extends string | number>
extends BaseProxyTrap<MapEntry>
export class SetWrapper<K extends string | number> extends BaseProxyTrap
implements Set<K> {

@@ -43,3 +38,6 @@ clear(): void {

get size(): number {
return hashMapSize(this.carrier, this.entry.value);
return hashMapSize(
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
);
}

@@ -54,3 +52,3 @@

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -72,3 +70,3 @@ const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -87,3 +85,3 @@ const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

this.carrier,
this.entry.value
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer)
)) {

@@ -117,3 +115,9 @@ const t = hashMapNodePointerToKeyValue(this.carrier, nodePointer);

return hashMapNodeLookup(this.carrier, this.entry.value, p) !== 0;
return (
hashMapNodeLookup(
this.carrier,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p
) !== 0
);
}

@@ -130,3 +134,3 @@

this.carrier,
this.entry.value,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p,

@@ -146,5 +150,4 @@ undefined

return deleteObjectPropertyEntryByKey(
this.externalArgs,
this.carrier,
this.entry.value,
object_pointerToHashMap_get(this.carrier.heap, this.entryPointer),
p

@@ -151,0 +154,0 @@ );

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

describe("sizeOf tests", () => {
describe.skip("sizeOf tests", () => {
const externalArgs = externalArgsApiToExternalArgsApi({

@@ -35,3 +35,3 @@ arrayAdditionalAllocation: 20,

"calcedSize": 72,
"realSize": 72,
"realSize": 104,
}

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

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

/* istanbul ignore file */
import {

@@ -2,0 +3,0 @@ ExternalArgsApi,

/* eslint-env jest */
import {
writeEntry,
initializeArrayBuffer,
readEntry,
appendEntry,
} from "./store";
import { ENTRY_TYPE } from "./entry-types";
import { initializeArrayBuffer } from "./store";
import { arrayBuffer2HexArray, makeCarrier } from "./testUtils";
import { ObjectEntry } from "./interfaces";
import { externalArgsApiToExternalArgsApi } from "./utils";
import { arrayBuffer2HexArray } from "./testUtils";

@@ -47,498 +39,1 @@ describe("Store tests - Misc", () => {

});
describe("Store tests writeEntry", () => {
test("writeEntry max number", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 8, {
type: ENTRY_TYPE.NUMBER,
value: Number.MAX_VALUE,
});
expect(arrayBuffer2HexArray(arrayBuffer.slice(0, 17)))
.toMatchInlineSnapshot(`
Array [
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x40",
"0xff",
]
`);
});
test("writeEntry min number", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 8, {
type: ENTRY_TYPE.NUMBER,
value: Number.MIN_VALUE,
});
expect(arrayBuffer2HexArray(arrayBuffer.slice(0, 17)))
.toMatchInlineSnapshot(`
Array [
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x40",
"0x01",
]
`);
});
test("writeEntry string", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 8, {
type: ENTRY_TYPE.STRING,
value: "aא弟",
allocatedBytes: 6,
});
expect(arrayBuffer2HexArray(arrayBuffer.slice(0, 19)))
.toMatchInlineSnapshot(`
Array [
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x00",
"0x14",
"0x40",
"0x06",
"0x00",
"0x00",
]
`);
});
});
describe("Store tests readEntry", () => {
const externalArgs = externalArgsApiToExternalArgsApi({
arrayAdditionalAllocation: 20,
});
test("readEntry max number", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 8, {
type: ENTRY_TYPE.NUMBER,
value: Number.MAX_VALUE,
});
const redEntry = readEntry(carrier, 8);
// expect(redBytesLength).toBe(writtenLength);
expect(redEntry).toMatchInlineSnapshot(`
Object {
"type": 2,
"value": 1.7976931348623157e+308,
}
`);
});
test("readEntry min number", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 8, {
type: ENTRY_TYPE.NUMBER,
value: Number.MIN_VALUE,
});
const redEntry = readEntry(carrier, 8);
expect(redEntry).toMatchInlineSnapshot(`
Object {
"type": 2,
"value": 5e-324,
}
`);
});
test("readEntry string", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 0, {
type: ENTRY_TYPE.STRING,
value: "aא弟",
allocatedBytes: 6,
});
const entry = readEntry(carrier, 0);
expect(entry).toMatchInlineSnapshot(`
Object {
"allocatedBytes": 6,
"type": 5,
"value": "aא弟",
}
`);
});
test("readEntry BigInt", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 0, {
type: ENTRY_TYPE.BIGINT_POSITIVE,
value: BigInt("0b0" + "1".repeat(63)),
});
const entry = readEntry(carrier, 0);
expect(entry).toMatchInlineSnapshot(`
Object {
"type": 3,
"value": 9223372036854775807n,
}
`);
});
test("readEntry UBigInt", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 0, {
type: ENTRY_TYPE.BIGINT_POSITIVE,
value: BigInt("0b" + "1".repeat(64)),
});
const entry = readEntry(carrier, 0);
expect(entry).toMatchInlineSnapshot(`
Object {
"type": 3,
"value": 18446744073709551615n,
}
`);
});
test("ENTRY_TYPE.BIGINT_POSITIVE max value", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 0, {
type: ENTRY_TYPE.BIGINT_POSITIVE,
value: BigInt("0b" + "1".repeat(64)),
});
expect(readEntry(carrier, 0)).toMatchInlineSnapshot(`
Object {
"type": 3,
"value": 18446744073709551615n,
}
`);
});
test("ENTRY_TYPE.BIGINT_NEGATIVE min value", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
writeEntry(carrier, 0, {
type: ENTRY_TYPE.BIGINT_NEGATIVE,
value: -BigInt("0b" + "1".repeat(64)),
});
expect(readEntry(carrier, 0)).toMatchInlineSnapshot(`
Object {
"type": 4,
"value": -18446744073709551615n,
}
`);
});
test("BigInt64 overflow error", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
expect(() => {
writeEntry(carrier, 0, {
type: ENTRY_TYPE.BIGINT_POSITIVE,
value: BigInt("0b" + "1".repeat(65)),
});
}).toThrowErrorMatchingInlineSnapshot(`"BigInt64OverflowError"`);
});
describe("Store tests write/read entry", () => {
test("object entry", () => {
const arrayBuffer = new ArrayBuffer(64);
const carrier = makeCarrier(arrayBuffer);
const entryToWrite: ObjectEntry = {
type: ENTRY_TYPE.OBJECT,
refsCount: 0,
value: 10,
};
writeEntry(carrier, 0, entryToWrite);
const entry = readEntry(carrier, 0);
expect(entry).toMatchInlineSnapshot(`
Object {
"refsCount": 0,
"type": 7,
"value": 10,
}
`);
});
});
describe("appendEntry - general", () => {
test("appendEntry", () => {
const arrayBuffer = new ArrayBuffer(96);
initializeArrayBuffer(arrayBuffer);
const carrier = makeCarrier(arrayBuffer);
const r1 = appendEntry(externalArgs, carrier, {
type: ENTRY_TYPE.STRING,
value: "im a string",
allocatedBytes: 11,
});
expect(r1).toMatchInlineSnapshot(`48`);
expect(arrayBuffer2HexArray(arrayBuffer, true)).toMatchInlineSnapshot(`
Array [
"0:0x00",
"1:0x00",
"2:0x00",
"3:0x00",
"4:0x08",
"5:0x00",
"6:0x00",
"7:0x00",
"8:0x00",
"9:0x00",
"10:0x00",
"11:0x00",
"12:0x00",
"13:0x00",
"14:0x00",
"15:0x00",
"16:0x28",
"17:0x00",
"18:0x00",
"19:0x00",
"20:0x48",
"21:0x00",
"22:0x00",
"23:0x00",
"24:0x60",
"25:0x00",
"26:0x00",
"27:0x00",
"28:0x08",
"29:0x00",
"30:0x00",
"31:0x00",
"32:0x03",
"33:0x00",
"34:0x00",
"35:0x00",
"36:0x10",
"37:0x00",
"38:0x00",
"39:0x00",
"40:0x20",
"41:0x00",
"42:0x00",
"43:0x00",
"44:0x00",
"45:0x00",
"46:0x00",
"47:0x00",
"48:0x00",
"49:0x00",
"50:0x00",
"51:0x00",
"52:0x00",
"53:0x00",
"54:0x14",
"55:0x40",
"56:0x0b",
"57:0x00",
"58:0x00",
"59:0x00",
"60:0x69",
"61:0x6d",
"62:0x20",
"63:0x61",
"64:0x20",
"65:0x73",
"66:0x74",
"67:0x72",
"68:0x69",
"69:0x6e",
"70:0x67",
"71:0x00",
"72:0x00",
"73:0x00",
"74:0x00",
"75:0x00",
"76:0x00",
"77:0x00",
"78:0x00",
"79:0x00",
"80:0x00",
"81:0x00",
"82:0x00",
"83:0x00",
"84:0x00",
"85:0x00",
"86:0x00",
"87:0x00",
"88:0x00",
"89:0x00",
"90:0x00",
"91:0x00",
"92:0x00",
"93:0x00",
"94:0x00",
"95:0x00",
]
`);
expect(arrayBuffer2HexArray(arrayBuffer, true)).toMatchInlineSnapshot(`
Array [
"0:0x00",
"1:0x00",
"2:0x00",
"3:0x00",
"4:0x08",
"5:0x00",
"6:0x00",
"7:0x00",
"8:0x00",
"9:0x00",
"10:0x00",
"11:0x00",
"12:0x00",
"13:0x00",
"14:0x00",
"15:0x00",
"16:0x28",
"17:0x00",
"18:0x00",
"19:0x00",
"20:0x48",
"21:0x00",
"22:0x00",
"23:0x00",
"24:0x60",
"25:0x00",
"26:0x00",
"27:0x00",
"28:0x08",
"29:0x00",
"30:0x00",
"31:0x00",
"32:0x03",
"33:0x00",
"34:0x00",
"35:0x00",
"36:0x10",
"37:0x00",
"38:0x00",
"39:0x00",
"40:0x20",
"41:0x00",
"42:0x00",
"43:0x00",
"44:0x00",
"45:0x00",
"46:0x00",
"47:0x00",
"48:0x00",
"49:0x00",
"50:0x00",
"51:0x00",
"52:0x00",
"53:0x00",
"54:0x14",
"55:0x40",
"56:0x0b",
"57:0x00",
"58:0x00",
"59:0x00",
"60:0x69",
"61:0x6d",
"62:0x20",
"63:0x61",
"64:0x20",
"65:0x73",
"66:0x74",
"67:0x72",
"68:0x69",
"69:0x6e",
"70:0x67",
"71:0x00",
"72:0x00",
"73:0x00",
"74:0x00",
"75:0x00",
"76:0x00",
"77:0x00",
"78:0x00",
"79:0x00",
"80:0x00",
"81:0x00",
"82:0x00",
"83:0x00",
"84:0x00",
"85:0x00",
"86:0x00",
"87:0x00",
"88:0x00",
"89:0x00",
"90:0x00",
"91:0x00",
"92:0x00",
"93:0x00",
"94:0x00",
"95:0x00",
]
`);
});
});
});

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

import { ENTRY_TYPE, isPrimitiveEntryType } from "./entry-types";
import { Entry, primitive, GlobalCarrier } from "./interfaces";
import {
isPrimitive,
primitiveValueToEntry,
isKnownAddressValuePointer,
} from "./utils";
import { ENTRY_TYPE } from "./entry-types";
import { Entry, GlobalCarrier } from "./interfaces";
import { isKnownAddressValuePointer, isTypeWithRC } from "./utils";
import { ExternalArgs } from "./interfaces";

@@ -14,6 +10,14 @@ import { BigInt64OverflowError } from "./exceptions";

} from "./consts";
import { saveValue } from "./saveValue";
import { getAllLinkedAddresses } from "./getAllLinkedAddresses";
import { stringEncodeInto } from "./stringEncodeInto";
import { stringDecode } from "./stringDecode";
import {
typeAndRc_refsCount_get,
typeAndRc_refsCount_set,
typeOnly_type_get,
number_value_get,
string_bytesLength_get,
string_charsPointer_get,
} from "./generatedStructs";
import { Heap } from "../structsGenerator/consts";
import { readString } from "./readString";
import { saveValueIterative } from "./saveValue";

@@ -91,4 +95,4 @@ const MAX_64_BIG_INT = BigInt("0xFFFFFFFFFFFFFFFF");

default:
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
throw new Error(ENTRY_TYPE[entry.type] + " Not implemented yet");

@@ -100,238 +104,2 @@ }

export function writeEntry(
carrier: GlobalCarrier,
startingCursor: number,
entry: Entry
) {
let cursor = startingCursor;
// let writtenDataSizeInBytes = 0;
// write type
// undo on throw ?
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.type;
cursor += Float64Array.BYTES_PER_ELEMENT;
switch (entry.type) {
case ENTRY_TYPE.NUMBER:
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Float64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.STRING:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] =
entry.allocatedBytes;
cursor += Uint32Array.BYTES_PER_ELEMENT;
// eslint-disable-next-line no-case-declarations
const writtenBytes = stringEncodeInto(carrier.uint8, cursor, entry.value);
if (writtenBytes !== entry.allocatedBytes) {
// eslint-disable-next-line no-undef
console.warn(
{
value: entry.value,
writtenBytes,
allocatedBytes: entry.allocatedBytes,
},
true
);
throw new Error("WTF???");
}
cursor += entry.allocatedBytes;
break;
case ENTRY_TYPE.BIGINT_NEGATIVE:
case ENTRY_TYPE.BIGINT_POSITIVE:
if (entry.value > MAX_64_BIG_INT || entry.value < -MAX_64_BIG_INT) {
throw new BigInt64OverflowError();
}
carrier.bigUint64[cursor / BigUint64Array.BYTES_PER_ELEMENT] =
entry.type === ENTRY_TYPE.BIGINT_NEGATIVE ? -entry.value : entry.value;
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.SET:
case ENTRY_TYPE.MAP:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.ARRAY:
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.length;
cursor += Uint32Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] =
entry.allocatedLength;
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.DATE:
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT] = entry.value;
cursor += Float64Array.BYTES_PER_ELEMENT;
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT] = entry.refsCount;
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");
}
}
export function appendEntry(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
entry: Entry
) {
const size = sizeOfEntry(entry);
const memoryAddress = carrier.allocator.calloc(size);
writeEntry(carrier, memoryAddress, entry);
return memoryAddress;
}
export function readEntry(
carrier: GlobalCarrier,
startingCursor: number
): Entry {
let cursor = startingCursor;
const entryType: ENTRY_TYPE =
carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
const entry: any = {
type: entryType,
value: undefined as any,
};
// let writtenDataSizeInBytes = 0;
switch (entryType) {
// handled by well-known addresses
// case ENTRY_TYPE.UNDEFINED:
// break;
// case ENTRY_TYPE.NULL:
// break;
// case ENTRY_TYPE.BOOLEAN:
// entry.value = carrier.dataView.getUint8(cursor) !== 0;
// cursor += Uint8Array.BYTES_PER_ELEMENT;
// break;
case ENTRY_TYPE.NUMBER:
entry.value = carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.STRING:
// eslint-disable-next-line no-case-declarations
const stringLength =
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
entry.allocatedBytes = stringLength;
cursor += Uint32Array.BYTES_PER_ELEMENT;
// decode fails with zero length array
if (stringLength > 0) {
// this wrapping is needed until:
// https://github.com/whatwg/encoding/issues/172
// eslint-disable-next-line no-case-declarations
// const tempAB = new ArrayBuffer(stringLength, true);
// arrayBufferCopyTo(dataView.buffer, cursor, stringLength, tempAB, 0, true);
entry.value = stringDecode(carrier.uint8, cursor, stringLength);
} else {
entry.value = "";
}
cursor += stringLength;
break;
case ENTRY_TYPE.BIGINT_POSITIVE:
entry.value =
carrier.bigUint64[cursor / BigUint64Array.BYTES_PER_ELEMENT];
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.BIGINT_NEGATIVE:
entry.value = -carrier.bigUint64[
cursor / BigUint64Array.BYTES_PER_ELEMENT
];
cursor += BigUint64Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.OBJECT:
case ENTRY_TYPE.MAP:
case ENTRY_TYPE.SET:
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.value = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.ARRAY:
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.value = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.length = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
entry.allocatedLength =
carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
case ENTRY_TYPE.DATE:
entry.value = carrier.float64[cursor / Float64Array.BYTES_PER_ELEMENT];
cursor += Float64Array.BYTES_PER_ELEMENT;
entry.refsCount = carrier.uint32[cursor / Uint32Array.BYTES_PER_ELEMENT];
cursor += Uint32Array.BYTES_PER_ELEMENT;
break;
default:
throw new Error(ENTRY_TYPE[entryType] + " Not implemented yet");
}
return entry;
}
export function canReuseMemoryOfEntry(entryA: Entry, value: primitive) {
const typeofTheValue = typeof value;
// number & bigint 64 are the same size
if (
(entryA.type === ENTRY_TYPE.BIGINT_NEGATIVE ||
entryA.type === ENTRY_TYPE.BIGINT_POSITIVE ||
entryA.type === ENTRY_TYPE.NUMBER) &&
(typeofTheValue === "bigint" || typeofTheValue === "number")
) {
return true;
}
// kill for strings for now
// if (
// entryA.type === ENTRY_TYPE.STRING &&
// typeofTheValue === "string" &&
// entryA.allocatedBytes >= strByteLength(value as string)
// ) {
// return true;
// }
return false;
}
export function writeValueInPtrToPtr(

@@ -341,41 +109,15 @@ externalArgs: ExternalArgs,

ptrToPtr: number,
value: any
value: unknown
) {
const existingEntryPointer =
carrier.uint32[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT];
const referencedPointers: number[] = [];
// Might oom here
saveValueIterative(
externalArgs,
carrier,
referencedPointers,
ptrToPtr,
value
);
let reuse = false;
let existingValueEntry: Entry | undefined;
if (!isKnownAddressValuePointer(existingEntryPointer)) {
existingValueEntry = readEntry(carrier, existingEntryPointer);
reuse =
isPrimitive(value) &&
isPrimitiveEntryType(existingValueEntry.type) &&
canReuseMemoryOfEntry(existingValueEntry, value);
}
// try to re use memory
if (reuse) {
const newEntry = primitiveValueToEntry(value);
writeEntry(carrier, existingEntryPointer, newEntry);
} else {
const referencedPointers: number[] = [];
const newEntryPointer = saveValue(
externalArgs,
carrier,
referencedPointers,
new Map(),
value
);
carrier.uint32[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT] = newEntryPointer;
return {
referencedPointers,
existingEntryPointer,
existingValueEntry,
};
}
return referencedPointers;
}

@@ -387,48 +129,30 @@

ptrToPtr: number,
value: any
value: unknown
) {
const {
existingValueEntry = false,
existingEntryPointer = 0,
referencedPointers = [],
} = writeValueInPtrToPtr(externalArgs, carrier, ptrToPtr, value) || {};
const existingEntryPointer =
carrier.heap.Uint32Array[ptrToPtr / Uint32Array.BYTES_PER_ELEMENT];
// Might oom here
const referencedPointers = writeValueInPtrToPtr(
externalArgs,
carrier,
ptrToPtr,
value
);
// -- end of might oom
// commit ref count changes of existing objects
if (referencedPointers.length > 0) {
for (const ptr of referencedPointers) {
incrementRefCount(externalArgs, carrier, ptr);
incrementRefCount(carrier.heap, ptr);
}
}
if (existingValueEntry && "refsCount" in existingValueEntry) {
const newRefCount = decrementRefCount(
externalArgs,
carrier,
existingEntryPointer
);
if (newRefCount === 0) {
const addressesToFree = getAllLinkedAddresses(
carrier,
false,
existingEntryPointer
);
for (const address of addressesToFree.leafAddresses) {
carrier.allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
}
}
} else {
carrier.allocator.free(existingEntryPointer);
}
handleArcForDeletedValuePointer(carrier, existingEntryPointer);
}
export function handleArcForDeletedValuePointer(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
deletedValuePointer: number
): void {
const { heap, allocator } = carrier;
// No memory to free/ARC

@@ -439,106 +163,53 @@ if (isKnownAddressValuePointer(deletedValuePointer)) {

const existingValueEntry = readEntry(carrier, deletedValuePointer);
if (existingValueEntry && "refsCount" in existingValueEntry) {
const newRefCount = decrementRefCount(
externalArgs,
carrier,
deletedValuePointer
);
if (newRefCount === 0) {
const addressesToFree = getAllLinkedAddresses(
carrier,
false,
deletedValuePointer
const entryType = typeOnly_type_get(heap, deletedValuePointer);
if (!isTypeWithRC(entryType)) {
if (entryType === ENTRY_TYPE.STRING) {
allocator.free(
string_charsPointer_get(carrier.heap, deletedValuePointer)
);
for (const address of addressesToFree.leafAddresses) {
carrier.allocator.free(address);
}
for (const address of addressesToFree.arcAddresses) {
decrementRefCount(externalArgs, carrier, address);
}
}
} else {
carrier.allocator.free(deletedValuePointer);
allocator.free(deletedValuePointer);
return;
}
}
export function incrementRefCount(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
entryPointer: number
) {
const entry = readEntry(carrier, entryPointer);
if (decrementRefCount(heap, deletedValuePointer) > 0) {
allocator.free(deletedValuePointer);
return;
}
if ("refsCount" in entry) {
entry.refsCount += 1;
writeEntry(carrier, entryPointer, entry);
const { leafAddresses, arcAddresses } = getAllLinkedAddresses(
carrier,
false,
deletedValuePointer
);
return entry.refsCount;
for (const address of leafAddresses) {
allocator.free(address);
}
throw new Error("unexpected");
}
export function decrementRefCount(
externalArgs: ExternalArgs,
carrier: GlobalCarrier,
entryPointer: number
) {
const entry = readEntry(carrier, entryPointer);
if ("refsCount" in entry) {
entry.refsCount -= 1;
writeEntry(carrier, entryPointer, entry);
return entry.refsCount;
for (const address of arcAddresses) {
decrementRefCount(heap, address);
}
throw new Error("unexpected");
}
export function getRefCount(carrier: GlobalCarrier, entryPointer: number) {
const entry = readEntry(carrier, entryPointer);
export function incrementRefCount(heap: Heap, entryPointer: number) {
typeAndRc_refsCount_set(
heap,
entryPointer,
typeAndRc_refsCount_get(heap, entryPointer) + 1
);
if ("refsCount" in entry) {
return entry.refsCount;
}
throw new Error("unexpected");
return typeAndRc_refsCount_get(heap, entryPointer);
}
export function setRefCount(
carrier: GlobalCarrier,
entryPointer: number,
newRefCount: number
) {
const entry = readEntry(carrier, entryPointer);
export function decrementRefCount(heap: Heap, entryPointer: number) {
typeAndRc_refsCount_set(
heap,
entryPointer,
typeAndRc_refsCount_get(heap, entryPointer) - 1
);
if ("refsCount" in entry) {
const prevCount = entry.refsCount;
entry.refsCount = newRefCount;
writeEntry(carrier, entryPointer, entry);
return prevCount;
}
throw new Error("unexpected");
return typeAndRc_refsCount_get(heap, entryPointer);
}
// export function getObjectPropPtrToPtr(
// { dataView }: GlobalCarrier,
// pointerToEntry: number
// ) {
// const keyStringLength = dataView.getUint16(pointerToEntry + 1);
// const valuePtrToPtr =
// Uint16Array.BYTES_PER_ELEMENT + pointerToEntry + 1 + keyStringLength;
// const nextPtrToPtr = valuePtrToPtr + Uint32Array.BYTES_PER_ELEMENT;
// return {
// valuePtrToPtr,
// nextPtrToPtr
// };
// }
export function getObjectValuePtrToPtr(pointerToEntry: number) {

@@ -571,2 +242,45 @@ return pointerToEntry + 1 + 1;

export function compareStringOrNumberEntriesInPlace(
heap: Heap,
entryAPointer: number,
entryBPointer: number
) {
typeOnly_type_get(heap, entryAPointer);
const entryAType: ENTRY_TYPE.STRING | ENTRY_TYPE.NUMBER = typeOnly_type_get(
heap,
entryAPointer
);
const entryBType: ENTRY_TYPE.STRING | ENTRY_TYPE.NUMBER = typeOnly_type_get(
heap,
entryBPointer
);
if (entryAType !== entryBType) {
return false;
}
if (entryAType === ENTRY_TYPE.STRING) {
const aLength = string_bytesLength_get(heap, entryAPointer);
const bLength = string_bytesLength_get(heap, entryBPointer);
if (aLength !== bLength) {
return false;
}
return memComp(
heap.Uint8Array,
string_charsPointer_get(heap, entryAPointer),
string_charsPointer_get(heap, entryBPointer),
aLength
);
}
// numbers
return (
number_value_get(heap, entryAPointer) ===
number_value_get(heap, entryBPointer)
);
}
export function compareStringOrNumberEntriesInPlaceOld(
carrier: GlobalCarrier,

@@ -615,1 +329,14 @@ entryAPointer: number,

}
export function readNumberOrString(heap: Heap, pointer: number) {
const type: ENTRY_TYPE.NUMBER | ENTRY_TYPE.STRING = typeOnly_type_get(
heap,
pointer
);
if (type === ENTRY_TYPE.NUMBER) {
return number_value_get(heap, pointer);
} else {
return readString(heap, pointer);
}
}

@@ -27,2 +27,3 @@ export function arrayBuffer2HexArray(

import { MEM_POOL_START } from "./consts";
import { createHeap } from "../structsGenerator/consts";

@@ -81,4 +82,4 @@ // extend pool and not monkey patch? need to think about it

// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
pool.free = function free(ptr: number) {

@@ -114,2 +115,3 @@ deallocations.add(ptr);

bigUint64: new BigUint64Array(arrayBuffer),
heap: createHeap(arrayBuffer),
};

@@ -116,0 +118,0 @@

@@ -124,2 +124,6 @@ import {

/**
* Incorrect length (too big) for emojis
* @param str
*/
export function strByteLength(str: string) {

@@ -148,1 +152,11 @@ let s = str.length;

}
export function isTypeWithRC(type: ENTRY_TYPE) {
return (
type === ENTRY_TYPE.OBJECT ||
type === ENTRY_TYPE.ARRAY ||
type === ENTRY_TYPE.DATE ||
type === ENTRY_TYPE.MAP ||
type === ENTRY_TYPE.SET
);
}

@@ -0,1 +1,5 @@

/* istanbul ignore file */
// We can't run test with weakrefs yet
const KEYS = 1;

@@ -2,0 +6,0 @@ const VALUES = 2;

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

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

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 too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

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