diff --git a/src/TransferableDataStructure.ts b/src/TransferableDataStructure.ts index 20f757d..d92627a 100644 --- a/src/TransferableDataStructure.ts +++ b/src/TransferableDataStructure.ts @@ -7,6 +7,19 @@ export default abstract class TransferableDataStructure { private decoderBuffer: ArrayBuffer = new ArrayBuffer(TransferableDataStructure.DECODER_BUFFER_SIZE); private currentDecoderBufferSize: number = TransferableDataStructure.DECODER_BUFFER_SIZE; + // Check if the current environment supports decoding directly from a SharedArrayBuffer view. + protected static readonly SUPPORTS_SAB_VIEW = (() => { + try { + if (typeof SharedArrayBuffer === "undefined") return false; + const sab = new SharedArrayBuffer(0); + const view = new Uint8Array(sab); + new TextDecoder().decode(view); + return true; + } catch { + return false; + } + })(); + protected allocateMemory(byteSize: number): SharedArrayBuffer | ArrayBuffer { try { return new SharedArrayBuffer(byteSize); diff --git a/src/array/ShareableArray.ts b/src/array/ShareableArray.ts index dcea152..bb50b58 100644 --- a/src/array/ShareableArray.ts +++ b/src/array/ShareableArray.ts @@ -887,6 +887,10 @@ export class ShareableArray extends TransferableDataStructure { // Copy from shared memory to a temporary private buffer (since we cannot directly decode from shared memory) const sourceView = new Uint8Array(this.dataView.buffer, dataPos + ShareableArray.DATA_OBJECT_OFFSET, valueLength); + if (ShareableArray.SUPPORTS_SAB_VIEW) { + return encoder.decode(sourceView); + } + const targetView = new Uint8Array(this.getFittingDecoderBuffer(valueLength), 0, valueLength); targetView.set(sourceView); diff --git a/src/encoding/NumberEncoder.ts b/src/encoding/NumberEncoder.ts index 51e2228..0404d18 100644 --- a/src/encoding/NumberEncoder.ts +++ b/src/encoding/NumberEncoder.ts @@ -2,7 +2,7 @@ import Serializable from "./Serializable"; export default class NumberEncoder implements Serializable { decode(buffer: Uint8Array): number { - const bufferView = new DataView(buffer.buffer); + const bufferView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); // First byte indicates if we did store a float or an int const numberType = bufferView.getUint8(0); diff --git a/src/map/ShareableMap.ts b/src/map/ShareableMap.ts index d3ca305..b4c19c5 100644 --- a/src/map/ShareableMap.ts +++ b/src/map/ShareableMap.ts @@ -730,6 +730,10 @@ export class ShareableMap extends TransferableDataStructure { const sourceView = new Uint8Array(this.dataView.buffer, startPos + ShareableMap.DATA_OBJECT_OFFSET, keyLength); + if (ShareableMap.SUPPORTS_SAB_VIEW) { + return this.textDecoder.decode(sourceView); + } + const targetView = new Uint8Array(this.getFittingDecoderBuffer(keyLength), 0, keyLength); targetView.set(sourceView); @@ -762,6 +766,10 @@ export class ShareableMap extends TransferableDataStructure { // Copy from shared memory to a temporary private buffer (since we cannot directly decode from shared memory) const sourceView = new Uint8Array(this.dataView.buffer, startPos + ShareableMap.DATA_OBJECT_OFFSET + keyLength, valueLength); + if (ShareableMap.SUPPORTS_SAB_VIEW) { + return encoder.decode(sourceView); + } + const targetView = new Uint8Array(this.getFittingDecoderBuffer(valueLength), 0, valueLength); targetView.set(sourceView);