从 JavaScript 使用时如何确保释放 wasm 内存

How to ensure wasm memory is freed when using it from JavaScript

我有一个如下所示的 C 库:

struct timeseries *ts_create(void) {
    /* Allocate some memory and return a pointer. */
}

void ts_free(struct timeseries *p) {
    /* Free the memory block pointed to by p. */
}

/* And many other functions that receive a struct timeseries * and
 * do things to it.
 */

我用 emscripten 编译了它,我正在为它创建一个 JavaScript 接口(包装器),如下所示:

const timeseries = {
  ptimeseries: 0,

  initialize() {
    this.ptimeseries = cfunctions.ts_create();
  },

  destroy() {
    cfunctions.ts_free(this.ptimeseries);
  },

  // And many other functions
}

你可以这样使用它:

const myTimeseries = Object.create(timeseries);
try {
  myTimeseries.initialize();
  // do more things
} finally {
  myTimeseries.destroy();
}

问题是我想在 C 中(或 JavaScript 包装器中)保留“危险”的东西,即内存分配和释放,以便 JavaScript程序员可以安全地使用生成的库。 JavaScript 程序员习惯于对象自动释放自己,要求他们添加某种 try ... finally 语句很容易出错。

但据我所知,JavaScript 没有任何对象析构函数或任何类型的 onGarbageCollect(object) 事件。

我该怎么办?

有一个名为 FinalizationRegistry 的新 JavaScript 功能,您可以使用它来实现此功能,但请注意,并非所有浏览器都支持它 (https://caniuse.com/mdn-javascript_builtins_finalizationregistry)

const registry = new FinalizationRegistry((heldValue) => {
  cfunctions.ts_free(heldValue);
});

class Timeseries {
  constructor() {
    this.ptimeseries = cfunctions.ts_create();
    registry.register(this, this.ptimeseries, this);
  }

  destroy() { // manual destructor for backup, you don't have to call this
    registry.unregister(this);
    cfunctions.ts_free(this.ptimeseries);
  }
}