emnapi 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/library_napi.js +108 -40
  2. package/include/node/emnapi.h +2 -2
  3. package/lib/wasm32/libdlmalloc-mt.a +0 -0
  4. package/lib/wasm32/libdlmalloc.a +0 -0
  5. package/lib/wasm32/libemmalloc-mt.a +0 -0
  6. package/lib/wasm32/libemmalloc.a +0 -0
  7. package/lib/wasm32/libemnapi-basic-mt.a +0 -0
  8. package/lib/wasm32/libemnapi-basic.a +0 -0
  9. package/lib/wasm32/libemnapi.a +0 -0
  10. package/lib/wasm32-emscripten/libemnapi-basic.a +0 -0
  11. package/lib/wasm32-emscripten/libemnapi-mt.a +0 -0
  12. package/lib/wasm32-emscripten/libemnapi.a +0 -0
  13. package/lib/wasm32-wasi/libemnapi-basic-mt.a +0 -0
  14. package/lib/wasm32-wasi/libemnapi-basic.a +0 -0
  15. package/lib/wasm32-wasi/libemnapi.a +0 -0
  16. package/lib/wasm32-wasi-threads/libemnapi-basic-mt.a +0 -0
  17. package/lib/wasm32-wasi-threads/libemnapi-basic-napi-rs-mt.a +0 -0
  18. package/lib/wasm32-wasi-threads/libemnapi-basic.a +0 -0
  19. package/lib/wasm32-wasi-threads/libemnapi-mt.a +0 -0
  20. package/lib/wasm32-wasi-threads/libemnapi-napi-rs-mt.a +0 -0
  21. package/lib/wasm32-wasi-threads/libemnapi.a +0 -0
  22. package/lib/wasm32-wasip1/libemnapi-basic-mt.a +0 -0
  23. package/lib/wasm32-wasip1/libemnapi-basic.a +0 -0
  24. package/lib/wasm32-wasip1/libemnapi.a +0 -0
  25. package/lib/wasm32-wasip1-threads/libemnapi-basic-mt.a +0 -0
  26. package/lib/wasm32-wasip1-threads/libemnapi-basic-napi-rs-mt.a +0 -0
  27. package/lib/wasm32-wasip1-threads/libemnapi-basic.a +0 -0
  28. package/lib/wasm32-wasip1-threads/libemnapi-mt.a +0 -0
  29. package/lib/wasm32-wasip1-threads/libemnapi-napi-rs-mt.a +0 -0
  30. package/lib/wasm32-wasip1-threads/libemnapi.a +0 -0
  31. package/lib/wasm64-emscripten/libemnapi-basic.a +0 -0
  32. package/lib/wasm64-emscripten/libemnapi-mt.a +0 -0
  33. package/lib/wasm64-emscripten/libemnapi.a +0 -0
  34. package/package.json +1 -1
@@ -236,8 +236,8 @@ function __emnapi_close_handle_scope(_scope) {
236
236
  /* eslint-disable @typescript-eslint/indent */
237
237
  /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
238
238
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
239
+ /* eslint-disable @typescript-eslint/indent */
239
240
  /**
240
- * @__deps emscripten_resize_heap
241
241
  * @__sig ipjp
242
242
  */
243
243
  function _napi_adjust_external_memory(env, low, high, adjusted_value) {
@@ -248,33 +248,24 @@ function _napi_adjust_external_memory(env, low, high, adjusted_value) {
248
248
  #if WASM_BIGINT
249
249
  if (!high)
250
250
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
251
- change_in_bytes = Number(low);
251
+ change_in_bytes = BigInt(low);
252
252
  #else
253
253
  if (!adjusted_value)
254
254
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
255
- change_in_bytes = (low >>> 0) + (high * Math.pow(2, 32));
255
+ change_in_bytes = BigInt(low >>> 0) + (BigInt(high) << BigInt(32));
256
256
  #endif
257
- if (change_in_bytes < 0) {
258
- return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
259
- }
260
- if (change_in_bytes > 0) {
261
- var old_size = wasmMemory.buffer.byteLength;
262
- var new_size = old_size + change_in_bytes;
263
- if (!_emscripten_resize_heap(new_size)) {
264
- return envObject.setLastError(9 /* napi_status.napi_generic_failure */);
265
- }
266
- }
257
+ var adjusted_memory = emnapiCtx.adjustAmountOfExternalAllocatedMemory(change_in_bytes);
267
258
  #if WASM_BIGINT
268
259
  {{{ from64('high') }}};
269
260
  if (emnapiCtx.feature.supportBigInt) {
270
- {{{ makeSetValue('high', 0, 'wasmMemory.buffer.byteLength', 'i64') }}};
261
+ {{{ makeSetValue('high', 0, 'adjusted_memory', 'i64') }}};
271
262
  }
272
263
  else {
273
- emnapiSetValueI64(high, wasmMemory.buffer.byteLength);
264
+ emnapiSetValueI64(high, Number(adjusted_memory));
274
265
  }
275
266
  #else
276
267
  {{{ from64('adjusted_value') }}};
277
- {{{ makeSetValue('adjusted_value', 0, 'wasmMemory.buffer.byteLength', 'i64') }}};
268
+ {{{ makeSetValue('adjusted_value', 0, 'adjusted_memory', 'i64') }}};
278
269
  #endif
279
270
  return envObject.clearLastError();
280
271
  }
@@ -1064,8 +1055,7 @@ var emnapiExternalMemory = {
1064
1055
  }
1065
1056
  return view;
1066
1057
  }
1067
- var maybeOldWasmMemory = emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) ||
1068
- ((typeof SharedArrayBuffer === 'function') && (view.buffer instanceof SharedArrayBuffer));
1058
+ var maybeOldWasmMemory = emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) || emnapiExternalMemory.isSharedArrayBuffer(view.buffer);
1069
1059
  if (maybeOldWasmMemory && emnapiExternalMemory.wasmMemoryViewTable.has(view)) {
1070
1060
  var info = emnapiExternalMemory.wasmMemoryViewTable.get(view);
1071
1061
  var Ctor = info.Ctor;
@@ -1296,13 +1286,12 @@ function _napi_get_typedarray_info(env, typedarray, type, length, data, arraybuf
1296
1286
  }
1297
1287
  {{{ makeSetValue('type', 0, 't', 'i32') }}};
1298
1288
  }
1289
+ v = emnapiExternalMemory.getOrUpdateMemoryView(v);
1299
1290
  if (length) {
1300
1291
  {{{ from64('length') }}};
1301
1292
  {{{ makeSetValue('length', 0, 'v.length', SIZE_TYPE) }}};
1302
1293
  }
1303
- var buffer;
1304
1294
  if (data || arraybuffer) {
1305
- buffer = v.buffer;
1306
1295
  if (data) {
1307
1296
  {{{ from64('data') }}};
1308
1297
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1312,7 +1301,7 @@ function _napi_get_typedarray_info(env, typedarray, type, length, data, arraybuf
1312
1301
  if (arraybuffer) {
1313
1302
  {{{ from64('arraybuffer') }}};
1314
1303
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1315
- var ab = envObject.ensureHandleId(buffer);
1304
+ var ab = envObject.ensureHandleId(v.buffer);
1316
1305
  {{{ makeSetValue('arraybuffer', 0, 'ab', '*') }}};
1317
1306
  }
1318
1307
  }
@@ -1356,14 +1345,12 @@ function _napi_get_dataview_info(env, dataview, byte_length, data, arraybuffer,
1356
1345
  if (!handle.isDataView()) {
1357
1346
  return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
1358
1347
  }
1359
- var v = handle.value;
1348
+ var v = emnapiExternalMemory.getOrUpdateMemoryView(handle.value);
1360
1349
  if (byte_length) {
1361
1350
  {{{ from64('byte_length') }}};
1362
1351
  {{{ makeSetValue('byte_length', 0, 'v.byteLength', SIZE_TYPE) }}};
1363
1352
  }
1364
- var buffer;
1365
1353
  if (data || arraybuffer) {
1366
- buffer = v.buffer;
1367
1354
  if (data) {
1368
1355
  {{{ from64('data') }}};
1369
1356
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1373,7 +1360,7 @@ function _napi_get_dataview_info(env, dataview, byte_length, data, arraybuffer,
1373
1360
  if (arraybuffer) {
1374
1361
  {{{ from64('arraybuffer') }}};
1375
1362
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1376
- var ab = envObject.ensureHandleId(buffer);
1363
+ var ab = envObject.ensureHandleId(v.buffer);
1377
1364
  {{{ makeSetValue('arraybuffer', 0, 'ab', '*') }}};
1378
1365
  }
1379
1366
  }
@@ -5541,6 +5528,7 @@ function _napi_run_script(env, script, result) {
5541
5528
  * ```
5542
5529
  */
5543
5530
  var emnapiTSFN = {
5531
+ _liveSet: {},
5544
5532
  offset: {
5545
5533
  __size__: 0,
5546
5534
  /* napi_ref */ resource: 0,
@@ -5549,6 +5537,9 @@ var emnapiTSFN = {
5549
5537
  /* size_t */ queue_size: 0,
5550
5538
  /* bool */ is_some: 0,
5551
5539
  /* void* */ queue: 0,
5540
+ // Reuse uv_async_t storage as JS-side wakeup state: pending event + scheduled drain.
5541
+ async_pending: 0,
5542
+ async_u_fd: 0,
5552
5543
  /* size_t */ thread_count: 0,
5553
5544
  /* int32_t */ state: 0,
5554
5545
  /* atomic_uchar */ dispatch_state: 0,
@@ -5565,6 +5556,7 @@ var emnapiTSFN = {
5565
5556
  /* int32_t */ cond: 0
5566
5557
  },
5567
5558
  init: function () {
5559
+ emnapiTSFN._liveSet = new Set();
5568
5560
  #if MEMORY64
5569
5561
  emnapiTSFN.offset.__size__ = 320 /* NapiTSFNOffset64.__size__ */;
5570
5562
  emnapiTSFN.offset.resource = 0 /* NapiTSFNOffset64.async_resource_resource */;
@@ -5573,6 +5565,8 @@ var emnapiTSFN = {
5573
5565
  emnapiTSFN.offset.queue_size = 88 /* NapiTSFNOffset64.queue_size */;
5574
5566
  emnapiTSFN.offset.is_some = 24 /* NapiTSFNOffset64.async_resource_is_some */;
5575
5567
  emnapiTSFN.offset.queue = 96 /* NapiTSFNOffset64.queue */;
5568
+ emnapiTSFN.offset.async_pending = 232 /* NapiTSFNOffset64.async_pending */;
5569
+ emnapiTSFN.offset.async_u_fd = 160 /* NapiTSFNOffset64.async_u_fd */;
5576
5570
  emnapiTSFN.offset.thread_count = 240 /* NapiTSFNOffset64.thread_count */;
5577
5571
  emnapiTSFN.offset.state = 248 /* NapiTSFNOffset64.state */;
5578
5572
  emnapiTSFN.offset.dispatch_state = 252 /* NapiTSFNOffset64.dispatch_state */;
@@ -5595,6 +5589,8 @@ var emnapiTSFN = {
5595
5589
  emnapiTSFN.offset.queue_size = 60 /* NapiTSFNOffset32.queue_size */;
5596
5590
  emnapiTSFN.offset.is_some = 24 /* NapiTSFNOffset32.async_resource_is_some */;
5597
5591
  emnapiTSFN.offset.queue = 64 /* NapiTSFNOffset32.queue */;
5592
+ emnapiTSFN.offset.async_pending = 132 /* NapiTSFNOffset32.async_pending */;
5593
+ emnapiTSFN.offset.async_u_fd = 96 /* NapiTSFNOffset32.async_u_fd */;
5598
5594
  emnapiTSFN.offset.thread_count = 136 /* NapiTSFNOffset32.thread_count */;
5599
5595
  emnapiTSFN.offset.state = 140 /* NapiTSFNOffset32.state */;
5600
5596
  emnapiTSFN.offset.dispatch_state = 144 /* NapiTSFNOffset32.dispatch_state */;
@@ -5634,7 +5630,10 @@ var emnapiTSFN = {
5634
5630
  var type = __emnapi__.type;
5635
5631
  var payload = __emnapi__.payload;
5636
5632
  if (type === 'tsfn-send') {
5637
- emnapiTSFN.dispatch(payload.tsfn);
5633
+ var pendng = payload.tsfn + emnapiTSFN.offset.async_pending;
5634
+ if (Atomics.load(new Int32Array(wasmMemory.buffer), pendng >>> 2) !== 0) {
5635
+ emnapiTSFN.enqueue(payload.tsfn);
5636
+ }
5638
5637
  }
5639
5638
  }
5640
5639
  };
@@ -5669,6 +5668,12 @@ var emnapiTSFN = {
5669
5668
  destroyQueue: function (func) {
5670
5669
  var queue = emnapiTSFN.loadSizeTypeValue(func + emnapiTSFN.offset.queue, false);
5671
5670
  if (queue) {
5671
+ var node = emnapiTSFN.loadSizeTypeValue(queue, false);
5672
+ while (node !== 0) {
5673
+ var next = emnapiTSFN.loadSizeTypeValue(node + {{{ POINTER_SIZE }}}, false);
5674
+ _free({{{ to64('node') }}});
5675
+ node = next;
5676
+ }
5672
5677
  _free({{{ to64('queue') }}});
5673
5678
  }
5674
5679
  },
@@ -6027,6 +6032,7 @@ var emnapiTSFN = {
6027
6032
  }
6028
6033
  },
6029
6034
  destroy: function (func) {
6035
+ emnapiTSFN._liveSet.delete(func);
6030
6036
  emnapiTSFN.destroyQueue(func);
6031
6037
  emnapiTSFN.releaseResources(func);
6032
6038
  _free({{{ to64('func') }}});
@@ -6121,6 +6127,7 @@ var emnapiTSFN = {
6121
6127
  return;
6122
6128
  }
6123
6129
  emnapiTSFN.setHandlesClosing(func, 1);
6130
+ Atomics.store(new Int32Array(wasmMemory.buffer), (func + emnapiTSFN.offset.async_pending) >>> 2, 1);
6124
6131
  emnapiCtx.feature.setImmediate(function () {
6125
6132
  emnapiTSFN.finalize(func);
6126
6133
  });
@@ -6224,25 +6231,85 @@ var emnapiTSFN = {
6224
6231
  emnapiTSFN.send(func);
6225
6232
  }
6226
6233
  },
6227
- send: function (func) {
6228
- var current_state = Atomics.or(new Uint32Array(wasmMemory.buffer), (func + emnapiTSFN.offset.dispatch_state) >>> 2, 1 << 1);
6229
- if ((current_state & 1) === 1) {
6234
+ enqueue: function (func) {
6235
+ // `pending` means a worker thread has requested a wakeup that has not
6236
+ // been drained on the main thread yet.
6237
+ var pending = func + emnapiTSFN.offset.async_pending;
6238
+ // `scheduled` prevents queueing the same main-thread drain chain more than
6239
+ // once while a previous wakeup is still in flight.
6240
+ var scheduled = func + emnapiTSFN.offset.async_u_fd;
6241
+ var i32a = new Int32Array(wasmMemory.buffer);
6242
+ if (Atomics.exchange(i32a, scheduled >>> 2, 1) !== 0) {
6230
6243
  return;
6231
6244
  }
6232
- if ((typeof ENVIRONMENT_IS_PTHREAD !== 'undefined') && ENVIRONMENT_IS_PTHREAD) {
6233
- postMessage({
6234
- __emnapi__: {
6235
- type: 'tsfn-send',
6236
- payload: {
6237
- tsfn: func
6245
+ // Match uv_async_send-style coalescing in JS: the first turn represents
6246
+ // the wakeup reaching the main thread, and the second turn performs the
6247
+ // actual TSFN drain after nearby Send/Signal calls have had a chance to
6248
+ // collapse into the shared AsyncProgressWorker state.
6249
+ emnapiCtx.feature.setImmediate(function () {
6250
+ if (!emnapiTSFN._liveSet.has(func)) {
6251
+ return;
6252
+ }
6253
+ if (Atomics.load(i32a, pending >>> 2) === 0) {
6254
+ Atomics.store(i32a, scheduled >>> 2, 0);
6255
+ return;
6256
+ }
6257
+ emnapiCtx.feature.setImmediate(function () {
6258
+ try {
6259
+ // Consume the coalesced wakeup once, then let dispatch() observe any
6260
+ // queue mutations through dispatch_state like the C implementation.
6261
+ if (Atomics.exchange(i32a, pending >>> 2, 0) === 0) {
6262
+ return;
6263
+ }
6264
+ // After destroy(), the func address is freed. Skip dispatch
6265
+ // to avoid use-after-free (JS-side lifecycle check).
6266
+ if (!emnapiTSFN._liveSet.has(func)) {
6267
+ return;
6268
+ }
6269
+ emnapiTSFN.dispatch(func);
6270
+ }
6271
+ finally {
6272
+ // Allow a later wakeup to schedule a new drain chain. If another
6273
+ // worker-thread send raced with this drain, enqueue one more turn.
6274
+ if (emnapiTSFN._liveSet.has(func)) {
6275
+ Atomics.store(i32a, scheduled >>> 2, 0);
6276
+ if (Atomics.load(i32a, pending >>> 2) !== 0) {
6277
+ emnapiTSFN.enqueue(func);
6278
+ }
6238
6279
  }
6239
6280
  }
6240
6281
  });
6282
+ });
6283
+ },
6284
+ send: function (func) {
6285
+ var current_state = Atomics.or(new Uint32Array(wasmMemory.buffer), (func + emnapiTSFN.offset.dispatch_state) >>> 2, 1 << 1);
6286
+ if ((current_state & 1) === 1) {
6287
+ return;
6241
6288
  }
6242
- else {
6243
- emnapiCtx.feature.setImmediate(function () {
6244
- emnapiTSFN.dispatch(func);
6245
- });
6289
+ var pendng = func + emnapiTSFN.offset.async_pending;
6290
+ // A wakeup is already pending, so this send only needs to leave the queued
6291
+ // work in the TSFN queue and let the existing drain pick it up.
6292
+ if (Atomics.load(new Int32Array(wasmMemory.buffer), pendng >>> 2) !== 0) {
6293
+ return;
6294
+ }
6295
+ if (Atomics.exchange(new Int32Array(wasmMemory.buffer), pendng >>> 2, 1) === 0) {
6296
+ if ((typeof ENVIRONMENT_IS_PTHREAD !== 'undefined') && ENVIRONMENT_IS_PTHREAD) {
6297
+ // Worker threads only post a wakeup token. Main-thread draining is
6298
+ // serialized by enqueue() once the message is received.
6299
+ postMessage({
6300
+ __emnapi__: {
6301
+ type: 'tsfn-send',
6302
+ payload: {
6303
+ tsfn: func
6304
+ }
6305
+ }
6306
+ });
6307
+ }
6308
+ else {
6309
+ // On the main thread we can skip the cross-thread hop and schedule the
6310
+ // coalesced drain chain directly.
6311
+ emnapiTSFN.enqueue(func);
6312
+ }
6246
6313
  }
6247
6314
  }
6248
6315
  };
@@ -6329,6 +6396,7 @@ function _napi_create_threadsafe_function(env, func, async_resource, async_resou
6329
6396
  {{{ makeSetValue('tsfn', 'emnapiTSFN.offset.finalize_cb', 'thread_finalize_cb', '*') }}};
6330
6397
  {{{ makeSetValue('tsfn', 'emnapiTSFN.offset.call_js_cb', 'call_js_cb', '*') }}};
6331
6398
  emnapiCtx.addCleanupHook(envObject, emnapiTSFN.cleanup, tsfn);
6399
+ emnapiTSFN._liveSet.add(tsfn);
6332
6400
  envObject.ref();
6333
6401
  __emnapi_runtime_keepalive_push();
6334
6402
  emnapiCtx.increaseWaitingRequestCounter();
@@ -7079,7 +7147,7 @@ function _napi_get_version(env, result) {
7079
7147
  napi_add_env_cleanup_hook__deps: ["$emnapiCtx"],
7080
7148
  napi_add_env_cleanup_hook__sig: "ippp",
7081
7149
  napi_adjust_external_memory: _napi_adjust_external_memory,
7082
- napi_adjust_external_memory__deps: ["$emnapiCtx", "$emnapiSetValueI64", "emscripten_resize_heap"],
7150
+ napi_adjust_external_memory__deps: ["$emnapiCtx", "$emnapiSetValueI64"],
7083
7151
  napi_adjust_external_memory__sig: "ipjp",
7084
7152
  napi_call_function: _napi_call_function,
7085
7153
  napi_call_function__deps: ["$emnapiCtx"],
@@ -6,8 +6,8 @@
6
6
  #include "emnapi_common.h"
7
7
 
8
8
  #define EMNAPI_MAJOR_VERSION 1
9
- #define EMNAPI_MINOR_VERSION 9
10
- #define EMNAPI_PATCH_VERSION 2
9
+ #define EMNAPI_MINOR_VERSION 10
10
+ #define EMNAPI_PATCH_VERSION 0
11
11
 
12
12
  typedef enum {
13
13
  emnapi_runtime,
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emnapi",
3
- "version": "1.9.2",
3
+ "version": "1.10.0",
4
4
  "description": "Node-API implementation for Emscripten",
5
5
  "main": "index.js",
6
6
  "gypfile": false,