Source: MemoryManager.js

// @filename: types.d.ts

/**
 * TypedArrayType
 * @typedef {Int8ArrayConstructor|Int16ArrayConstructor|Int32ArrayConstructor|BigInt64ArrayConstructor|Uint8ArrayConstructor|Uint16ArrayConstructor|Uint32ArrayConstructor|BigUint64ArrayConstructor|Float32ArrayConstructor|Float64ArrayConstructor} TypedArrayType
 */

 /**
 * TypedArray
 * @typedef {Int8Array|Int16Array|Int32Array|BigInt64Array|Uint8Array|Uint16Array|Uint32Array|BigUint64Array|Float32Array|Float64Array} TypedArray
 */

/**
 * The memory manager
 */
export class MemoryManager {
  /**
   * Construct a memory manager.
   * @param {WebAssembly.Memory} memory The memory fro the WebAssembly instance.
   * @param {malloc} malloc Allocate memory
   * @param {free} free Free memory
   */
  constructor (memory, malloc, free) {
    this.memory = memory
    this.malloc = malloc
    this.free = free
    this._dataView = null
    this._registry = typeof FinalizationRegistry === 'undefined'
      ? null
      : new FinalizationRegistry(addresses => {
          for (const address of addresses) {
            free(address)
          }
        })
  }

  /**
   * @poperty {DataView}
   */
  get dataView() {
    if (this._dataView == null || this._dataView.byteLength === 0) {
      this._dataView = new DataView(this.memory.buffer)
    }
    return this._dataView
  }

  /**
   * Free an address when finalized.
   * @param {*} target The object that will be finalized
   * @param {number} address The address to be freed
   */
  freeWhenFinalized(target, address) {
    if (this._registry === null) {
      throw new Error('FinalizationRegistry is not implemented')
    }
    this._registry.register(target, address)
  }

  /**
   * Create a typed array
   * @template {number|bigint} T
   * @param {TypedArrayType} typedArrayType The typed array type
   * @param {number|Array<T>} lengthOrArray Either an array to be copied or the required length
   * @returns {TypedArray} The typed array
   */
  createTypedArray (typedArrayType, lengthOrArray) {
    const length = lengthOrArray instanceof Array ? lengthOrArray.length : lengthOrArray
    const address = this.malloc(length * typedArrayType.BYTES_PER_ELEMENT)
    const typedArray = new typedArrayType(this.memory.buffer, address, length)
    if (lengthOrArray instanceof Array) {
      // @ts-ignore
      typedArray.set(lengthOrArray)
    }
    this.freeWhenFinalized(typedArray, address)
    return typedArray
  }
}