emnapi 0.31.0 → 0.33.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.
@@ -1,5 +1,205 @@
1
1
  {{{ ((DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.indexOf("$emnapiInit") === -1 ? DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push("$emnapiInit") : undefined), "") }}}
2
2
  {{{ ((EXPORTED_RUNTIME_METHODS.indexOf("emnapiInit") === -1 ? EXPORTED_RUNTIME_METHODS.push("emnapiInit") : undefined), "") }}}
3
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
4
+ function emnapiCreateIdGenerator() {
5
+ var obj = {
6
+ nextId: 1,
7
+ list: [],
8
+ generate: function () {
9
+ var id;
10
+ if (obj.list.length) {
11
+ id = obj.list.shift();
12
+ }
13
+ else {
14
+ id = obj.nextId;
15
+ obj.nextId++;
16
+ }
17
+ return id;
18
+ },
19
+ reuse: function (id) {
20
+ obj.list.push(id);
21
+ }
22
+ };
23
+ return obj;
24
+ }
25
+ var emnapiAsyncWork = {
26
+ idGen: {},
27
+ values: [undefined],
28
+ queued: new Set(),
29
+ pending: [],
30
+ init: function () {
31
+ emnapiAsyncWork.idGen = emnapiCreateIdGenerator();
32
+ emnapiAsyncWork.values = [undefined];
33
+ emnapiAsyncWork.queued = new Set();
34
+ emnapiAsyncWork.pending = [];
35
+ },
36
+ create: function (env, resource, resourceName, execute, complete, data) {
37
+ var asyncId = 0;
38
+ var triggerAsyncId = 0;
39
+ if (emnapiNodeBinding) {
40
+ var asyncContext = emnapiNodeBinding.node.emitAsyncInit(resource, resourceName, -1);
41
+ asyncId = asyncContext.asyncId;
42
+ triggerAsyncId = asyncContext.triggerAsyncId;
43
+ }
44
+ var id = emnapiAsyncWork.idGen.generate();
45
+ emnapiAsyncWork.values[id] = {
46
+ env: env,
47
+ id: id,
48
+ resource: resource,
49
+ resourceName: resourceName,
50
+ asyncId: asyncId,
51
+ triggerAsyncId: triggerAsyncId,
52
+ status: 0,
53
+ execute: execute,
54
+ complete: complete,
55
+ data: data
56
+ };
57
+ return id;
58
+ },
59
+ callComplete: function (work, status) {
60
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
61
+ var complete = work.complete;
62
+ var env = work.env;
63
+ var data = work.data;
64
+ var callback = function () {
65
+ var envObject = emnapiCtx.envStore.get(env);
66
+ var scope = emnapiCtx.openScope(envObject);
67
+ try {
68
+ envObject.callIntoModule(function () {
69
+ {{{ makeDynCall('vpip', 'complete') }}}(env, status, data);
70
+ });
71
+ }
72
+ finally {
73
+ emnapiCtx.closeScope(envObject, scope);
74
+ }
75
+ };
76
+ if (emnapiNodeBinding) {
77
+ emnapiNodeBinding.node.makeCallback(work.resource, callback, [], {
78
+ asyncId: work.asyncId,
79
+ triggerAsyncId: work.triggerAsyncId
80
+ });
81
+ }
82
+ else {
83
+ callback();
84
+ }
85
+ },
86
+ queue: function (id) {
87
+ var work = emnapiAsyncWork.values[id];
88
+ if (!work)
89
+ return;
90
+ if (work.status === 0) {
91
+ work.status = 1;
92
+ if (emnapiAsyncWork.queued.size >= 4) {
93
+ emnapiAsyncWork.pending.push(id);
94
+ return;
95
+ }
96
+ emnapiAsyncWork.queued.add(id);
97
+ var env_1 = work.env;
98
+ var data_1 = work.data;
99
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
100
+ var execute = work.execute;
101
+ work.status = 2;
102
+ emnapiCtx.feature.setImmediate(function () {
103
+ {{{ makeDynCall('vpp', 'execute') }}}(env_1, data_1);
104
+ emnapiAsyncWork.queued.delete(id);
105
+ work.status = 3;
106
+ emnapiAsyncWork.callComplete(work, 0 /* napi_status.napi_ok */);
107
+ if (emnapiAsyncWork.pending.length > 0) {
108
+ var nextWorkId = emnapiAsyncWork.pending.shift();
109
+ emnapiAsyncWork.values[nextWorkId].status = 0;
110
+ emnapiAsyncWork.queue(nextWorkId);
111
+ }
112
+ });
113
+ }
114
+ },
115
+ cancel: function (id) {
116
+ var index = emnapiAsyncWork.pending.indexOf(id);
117
+ if (index !== -1) {
118
+ var work = emnapiAsyncWork.values[id];
119
+ if (work && (work.status === 1)) {
120
+ work.status = 4;
121
+ emnapiAsyncWork.pending.splice(index, 1);
122
+ emnapiAsyncWork.callComplete(work, 11 /* napi_status.napi_cancelled */);
123
+ return 0 /* napi_status.napi_ok */;
124
+ }
125
+ else {
126
+ return 9 /* napi_status.napi_generic_failure */;
127
+ }
128
+ }
129
+ return 9 /* napi_status.napi_generic_failure */;
130
+ },
131
+ remove: function (id) {
132
+ var work = emnapiAsyncWork.values[id];
133
+ if (!work)
134
+ return;
135
+ if (emnapiNodeBinding) {
136
+ emnapiNodeBinding.node.emitAsyncDestroy({
137
+ asyncId: work.asyncId,
138
+ triggerAsyncId: work.triggerAsyncId
139
+ });
140
+ }
141
+ emnapiAsyncWork.values[id] = undefined;
142
+ emnapiAsyncWork.idGen.reuse(id);
143
+ }
144
+ };
145
+ function _napi_create_async_work(env, resource, resource_name, execute, complete, data, result) {
146
+ if (env == 0)
147
+ return 1 /* napi_status.napi_invalid_arg */;
148
+ var envObject = emnapiCtx.envStore.get(env);
149
+ if (execute == 0)
150
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
151
+ if (result == 0)
152
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
153
+ var resourceObject;
154
+ if (resource) {
155
+ resourceObject = Object(emnapiCtx.handleStore.get(resource).value);
156
+ }
157
+ else {
158
+ resourceObject = {};
159
+ }
160
+ if (resource_name == 0)
161
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
162
+ var resourceName = String(emnapiCtx.handleStore.get(resource_name).value);
163
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
164
+ var id = emnapiAsyncWork.create(env, resourceObject, resourceName, execute, complete, data);
165
+ {{{ makeSetValue('result', 0, 'id', '*') }}};
166
+ return envObject.clearLastError();
167
+ }
168
+ function _napi_delete_async_work(env, work) {
169
+ if (env == 0)
170
+ return 1 /* napi_status.napi_invalid_arg */;
171
+ var envObject = emnapiCtx.envStore.get(env);
172
+ if (work == 0)
173
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
174
+ emnapiAsyncWork.remove(work);
175
+ return envObject.clearLastError();
176
+ }
177
+ function _napi_queue_async_work(env, work) {
178
+ if (env == 0)
179
+ return 1 /* napi_status.napi_invalid_arg */;
180
+ var envObject = emnapiCtx.envStore.get(env);
181
+ if (work == 0)
182
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
183
+ emnapiAsyncWork.queue(work);
184
+ return envObject.clearLastError();
185
+ }
186
+ function _napi_cancel_async_work(env, work) {
187
+ if (env == 0)
188
+ return 1 /* napi_status.napi_invalid_arg */;
189
+ var envObject = emnapiCtx.envStore.get(env);
190
+ if (work == 0)
191
+ return envObject.setLastError(1 /* napi_status.napi_invalid_arg */);
192
+ var status = emnapiAsyncWork.cancel(work);
193
+ if (status === 0 /* napi_status.napi_ok */)
194
+ return envObject.clearLastError();
195
+ return envObject.setLastError(status);
196
+ }
197
+ emnapiImplementHelper('$emnapiCreateIdGenerator', undefined, emnapiCreateIdGenerator, []);
198
+ emnapiDefineVar('$emnapiAsyncWork', emnapiAsyncWork, ['$emnapiCreateIdGenerator'], 'emnapiAsyncWork.init();');
199
+ emnapiImplement('napi_create_async_work', 'ippppppp', _napi_create_async_work, ['$emnapiAsyncWork']);
200
+ emnapiImplement('napi_delete_async_work', 'ipp', _napi_delete_async_work, ['$emnapiAsyncWork']);
201
+ emnapiImplement('napi_queue_async_work', 'ipp', _napi_queue_async_work, ['$emnapiAsyncWork']);
202
+ emnapiImplement('napi_cancel_async_work', 'ipp', _napi_cancel_async_work, ['$emnapiAsyncWork']);
3
203
  function _emnapi_create_memory_view(env, typedarray_type, external_data, byte_length, finalize_cb, finalize_hint, result
4
204
  // @ts-expect-error
5
205
  ) {
@@ -826,10 +1026,18 @@ function emnapiCreateFunction(envObject, utf8name, length, cb, data) {
826
1026
  }
827
1027
  #if DYNAMIC_EXECUTION
828
1028
  if (emnapiCtx.feature.supportNewFunction) {
829
- f = (new Function('_', 'return function ' + functionName + '(){' +
830
- '"use strict";' +
831
- 'return _.apply(this,arguments);' +
832
- '};'))(makeFunction());
1029
+ var _ = makeFunction();
1030
+ try {
1031
+ f = (new Function('_', 'return function ' + functionName + '(){' +
1032
+ '"use strict";' +
1033
+ 'return _.apply(this,arguments);' +
1034
+ '};'))(_);
1035
+ }
1036
+ catch (_err) {
1037
+ f = makeFunction();
1038
+ if (emnapiCtx.feature.canSetFunctionName)
1039
+ Object.defineProperty(f, 'name', { value: functionName });
1040
+ }
833
1041
  }
834
1042
  else {
835
1043
  f = makeFunction();
@@ -1250,7 +1458,9 @@ var emnapiExternalMemory = {
1250
1458
  }
1251
1459
  return view;
1252
1460
  }
1253
- if (emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) && emnapiExternalMemory.wasmMemoryViewTable.has(view)) {
1461
+ var maybeOldWasmMemory = emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) ||
1462
+ ((typeof SharedArrayBuffer === 'function') && (view.buffer instanceof SharedArrayBuffer));
1463
+ if (maybeOldWasmMemory && emnapiExternalMemory.wasmMemoryViewTable.has(view)) {
1254
1464
  var info = emnapiExternalMemory.wasmMemoryViewTable.get(view);
1255
1465
  var Ctor = info.Ctor;
1256
1466
  var newView = void 0;
@@ -2180,7 +2390,7 @@ function napi_define_properties(env, object, property_count, properties
2180
2390
  var value_2 = {{{ makeGetValue("propPtr", POINTER_SIZE * 5, "*") }}};
2181
2391
  attributes = {{{ makeGetValue("propPtr", POINTER_SIZE * 6, POINTER_WASM_TYPE) }}};
2182
2392
  {{{ from64("attributes") }}};
2183
- var data_1 = {{{ makeGetValue("propPtr", POINTER_SIZE * 7, "*") }}};
2393
+ var data_2 = {{{ makeGetValue("propPtr", POINTER_SIZE * 7, "*") }}};
2184
2394
  if (utf8Name_1) {
2185
2395
  propertyName_1 = UTF8ToString(utf8Name_1);
2186
2396
  }
@@ -2193,7 +2403,7 @@ function napi_define_properties(env, object, property_count, properties
2193
2403
  return envObject_32.setLastError(4 /* napi_status.napi_name_expected */);
2194
2404
  }
2195
2405
  }
2196
- emnapiDefineProperty(envObject_32, maybeObject_1, propertyName_1, method_1, getter_1, setter_1, value_2, attributes, data_1);
2406
+ emnapiDefineProperty(envObject_32, maybeObject_1, propertyName_1, method_1, getter_1, setter_1, value_2, attributes, data_2);
2197
2407
  }
2198
2408
  return 0 /* napi_status.napi_ok */;
2199
2409
  }
@@ -2840,7 +3050,7 @@ function napi_define_class(env, utf8name, length, constructor, callback_data, pr
2840
3050
  var value_3 = {{{ makeGetValue("propPtr", POINTER_SIZE * 5, "*") }}};
2841
3051
  attributes = {{{ makeGetValue("propPtr", POINTER_SIZE * 6, POINTER_WASM_TYPE) }}};
2842
3052
  {{{ from64("attributes") }}};
2843
- var data_2 = {{{ makeGetValue("propPtr", POINTER_SIZE * 7, "*") }}};
3053
+ var data_3 = {{{ makeGetValue("propPtr", POINTER_SIZE * 7, "*") }}};
2844
3054
  if (utf8Name_2) {
2845
3055
  propertyName_2 = UTF8ToString(utf8Name_2);
2846
3056
  }
@@ -2854,10 +3064,10 @@ function napi_define_class(env, utf8name, length, constructor, callback_data, pr
2854
3064
  }
2855
3065
  }
2856
3066
  if ((attributes & 1024 /* napi_property_attributes.napi_static */) !== 0) {
2857
- emnapiDefineProperty(envObject_43, F_1, propertyName_2, method_2, getter_2, setter_2, value_3, attributes, data_2);
3067
+ emnapiDefineProperty(envObject_43, F_1, propertyName_2, method_2, getter_2, setter_2, value_3, attributes, data_3);
2858
3068
  continue;
2859
3069
  }
2860
- emnapiDefineProperty(envObject_43, F_1.prototype, propertyName_2, method_2, getter_2, setter_2, value_3, attributes, data_2);
3070
+ emnapiDefineProperty(envObject_43, F_1.prototype, propertyName_2, method_2, getter_2, setter_2, value_3, attributes, data_3);
2861
3071
  }
2862
3072
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2863
3073
  var valueHandle_2 = emnapiCtx.addToCurrentScope(F_1);
@@ -4459,29 +4669,41 @@ mergeInto(LibraryManager.library, {
4459
4669
  'return r;' +
4460
4670
  '}; })();',
4461
4671
  $emnapiAddSendListener: function (worker) {
4462
- if (worker && !worker._emnapiSendListener) {
4463
- worker._emnapiSendListener = function _emnapiSendListener(e) {
4464
- var data = ENVIRONMENT_IS_NODE ? e : e.data;
4465
- if (data.emnapiAsyncSend) {
4466
- if (ENVIRONMENT_IS_PTHREAD) {
4467
- postMessage({
4468
- emnapiAsyncSend: data.emnapiAsyncSend
4469
- });
4470
- }
4471
- else {
4472
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
4473
- var callback = data.emnapiAsyncSend.callback;
4474
- {{{ makeDynCall('vp', 'callback') }}}(data.emnapiAsyncSend.data);
4475
- }
4672
+ if (!worker)
4673
+ return false;
4674
+ if (worker._emnapiSendListener)
4675
+ return true;
4676
+ var handler = function (e) {
4677
+ var data = ENVIRONMENT_IS_NODE ? e : e.data;
4678
+ var __emnapi__ = data.__emnapi__;
4679
+ if (__emnapi__ && __emnapi__.type === 'async-send') {
4680
+ if (ENVIRONMENT_IS_PTHREAD) {
4681
+ postMessage({ __emnapi__: __emnapi__ });
4476
4682
  }
4477
- };
4683
+ else {
4684
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
4685
+ var callback = __emnapi__.payload.callback;
4686
+ {{{ makeDynCall('vp', 'callback') }}}(__emnapi__.payload.data);
4687
+ }
4688
+ }
4689
+ };
4690
+ var dispose = function () {
4478
4691
  if (ENVIRONMENT_IS_NODE) {
4479
- worker.on('message', worker._emnapiSendListener);
4692
+ worker.off('message', handler);
4480
4693
  }
4481
4694
  else {
4482
- worker.addEventListener('message', worker._emnapiSendListener, false);
4695
+ worker.removeEventListener('message', handler, false);
4483
4696
  }
4697
+ delete worker._emnapiSendListener;
4698
+ };
4699
+ worker._emnapiSendListener = { handler: handler, dispose: dispose };
4700
+ if (ENVIRONMENT_IS_NODE) {
4701
+ worker.on('message', handler);
4484
4702
  }
4703
+ else {
4704
+ worker.addEventListener('message', handler, false);
4705
+ }
4706
+ return true;
4485
4707
  },
4486
4708
  _emnapi_async_send_js__sig: 'vipp',
4487
4709
  _emnapi_async_send_js__deps: [
@@ -4492,9 +4714,12 @@ mergeInto(LibraryManager.library, {
4492
4714
  _emnapi_async_send_js: function (type, callback, data) {
4493
4715
  if (ENVIRONMENT_IS_PTHREAD) {
4494
4716
  postMessage({
4495
- emnapiAsyncSend: {
4496
- callback: callback,
4497
- data: data
4717
+ __emnapi__: {
4718
+ type: 'async-send',
4719
+ payload: {
4720
+ callback: callback,
4721
+ data: data
4722
+ }
4498
4723
  }
4499
4724
  });
4500
4725
  }
@@ -4760,14 +4985,14 @@ function emnapiImplement(name, sig, compilerTimeFunction, deps) {
4760
4985
  mergeInto(LibraryManager.library, sym);
4761
4986
  }
4762
4987
  function emnapiImplement2() {
4763
- return emnapiImplement.apply(null, arguments);
4988
+ emnapiImplement.apply(null, arguments);
4764
4989
  }
4765
4990
  function emnapiImplementInternal() {
4766
- return emnapiImplement.apply(null, arguments);
4991
+ emnapiImplement.apply(null, arguments);
4767
4992
  }
4768
4993
  // $emnapi*
4769
4994
  function emnapiImplementHelper(name, sig, compilerTimeFunction, deps, _exportName) {
4770
- return emnapiImplement(name, sig, compilerTimeFunction, deps);
4995
+ emnapiImplement(name, sig, compilerTimeFunction, deps);
4771
4996
  }
4772
4997
  function emnapiDefineVar(name, value, deps, postset) {
4773
4998
  var _a;
package/include/emnapi.h CHANGED
@@ -2,7 +2,7 @@
2
2
  #define EMNAPI_INCLUDE_EMNAPI_H_
3
3
 
4
4
  #include "js_native_api.h"
5
- #include "common.h"
5
+ #include "emnapi_common.h"
6
6
 
7
7
  typedef enum {
8
8
  emnapi_runtime,
@@ -22,7 +22,7 @@
22
22
  #endif
23
23
 
24
24
  #include "js_native_api_types.h"
25
- #include "common.h"
25
+ #include "emnapi_common.h"
26
26
 
27
27
  #define NAPI_AUTO_LENGTH SIZE_MAX
28
28
 
package/index.js CHANGED
@@ -7,7 +7,13 @@ const include = path.join(__dirname, 'include')
7
7
  const includeDir = path.relative(process.cwd(), include)
8
8
  const jsLibrary = path.join(__dirname, './dist/library_napi.js')
9
9
  const sources = [
10
+ path.join(__dirname, './src/js_native_api.c'),
11
+ path.join(__dirname, './src/node_api.c'),
10
12
  path.join(__dirname, './src/emnapi.c'),
13
+ path.join(__dirname, './src/async_cleanup_hook.c'),
14
+ path.join(__dirname, './src/async_context.c'),
15
+ path.join(__dirname, './src/async_work.c'),
16
+ path.join(__dirname, './src/threadsafe_function.c'),
11
17
  path.join(__dirname, './src/uv/uv-common.c'),
12
18
  path.join(__dirname, './src/uv/threadpool.c'),
13
19
  path.join(__dirname, './src/uv/unix/loop.c'),
Binary file
Binary file
Binary file
@@ -1,5 +1,5 @@
1
- emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.29 (43074846f216abad2a1c35b5a631f2a9481d9e07)
2
- clang version 16.0.0 (https://github.com/llvm/llvm-project 947d529e4194e0567cfbbea99127066f76c87269)
1
+ emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.32 (eab98adf462c39f3c31d348331c4830bcaa36949)
2
+ clang version 17.0.0 (https://github.com/llvm/llvm-project df82394e7a2d06506718cafa347bf7827c79fc4f)
3
3
  Target: wasm32-unknown-emscripten
4
4
  Thread model: posix
5
5
  InstalledDir: /home/runner/work/emnapi/emnapi/emsdk-cache/emsdk-main/upstream/bin
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emnapi",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "description": "Node-API implementation for Emscripten",
5
5
  "main": "index.js",
6
6
  "devDependencies": {
@@ -0,0 +1,126 @@
1
+ #include "emnapi_internal.h"
2
+ #include "node_api.h"
3
+
4
+ EXTERN_C_START
5
+
6
+ typedef void (*async_cleanup_hook)(void* arg, void(*)(void*), void*);
7
+
8
+ struct async_cleanup_hook_info {
9
+ napi_env env;
10
+ async_cleanup_hook fun;
11
+ void* arg;
12
+ bool started;
13
+ };
14
+
15
+ struct napi_async_cleanup_hook_handle__ {
16
+ struct async_cleanup_hook_info* handle_;
17
+ napi_env env_;
18
+ napi_async_cleanup_hook user_hook_;
19
+ void* user_data_;
20
+ void (*done_cb_)(void*);
21
+ void* done_data_;
22
+ };
23
+
24
+ static void _emnapi_ach_handle_hook(void* data, void (*done_cb)(void*), void* done_data) {
25
+ napi_async_cleanup_hook_handle handle =
26
+ (napi_async_cleanup_hook_handle) (data);
27
+ handle->done_cb_ = done_cb;
28
+ handle->done_data_ = done_data;
29
+ handle->user_hook_(handle, handle->user_data_);
30
+ }
31
+
32
+ static void _emnapi_finish_async_cleanup_hook(void* arg) {
33
+ // struct async_cleanup_hook_info* info = (struct async_cleanup_hook_info*) (arg);
34
+ EMNAPI_KEEPALIVE_POP();
35
+ _emnapi_ctx_decrease_waiting_request_counter();
36
+ }
37
+
38
+ static void _emnapi_run_async_cleanup_hook(void* arg) {
39
+ struct async_cleanup_hook_info* info = (struct async_cleanup_hook_info*) (arg);
40
+ EMNAPI_KEEPALIVE_PUSH();
41
+ _emnapi_ctx_increase_waiting_request_counter();
42
+ info->started = true;
43
+ info->fun(info->arg, _emnapi_finish_async_cleanup_hook, info);
44
+ }
45
+
46
+ static struct async_cleanup_hook_info*
47
+ _emnapi_add_async_environment_cleanup_hook(napi_env env,
48
+ async_cleanup_hook fun,
49
+ void* arg) {
50
+ struct async_cleanup_hook_info* info =
51
+ (struct async_cleanup_hook_info*) malloc(sizeof(struct async_cleanup_hook_info));
52
+ info->env = env;
53
+ info->fun = fun;
54
+ info->arg = arg;
55
+ info->started = false;
56
+
57
+ EMNAPI_ASSERT_CALL(napi_add_env_cleanup_hook(env, _emnapi_run_async_cleanup_hook, info));
58
+
59
+ return info;
60
+ }
61
+
62
+ static void _emnapi_remove_async_environment_cleanup_hook(
63
+ struct async_cleanup_hook_info* info) {
64
+ if (info->started) return;
65
+ EMNAPI_ASSERT_CALL(napi_remove_env_cleanup_hook(info->env, _emnapi_run_async_cleanup_hook, info));
66
+ }
67
+
68
+ static napi_async_cleanup_hook_handle
69
+ _emnapi_ach_handle_create(napi_env env,
70
+ napi_async_cleanup_hook user_hook,
71
+ void* user_data) {
72
+ napi_async_cleanup_hook_handle handle =
73
+ (napi_async_cleanup_hook_handle) calloc(1, sizeof(struct napi_async_cleanup_hook_handle__));
74
+ handle->env_ = env;
75
+ handle->user_hook_ = user_hook;
76
+ handle->user_data_ = user_data;
77
+ handle->handle_ = _emnapi_add_async_environment_cleanup_hook(env, _emnapi_ach_handle_hook, handle);
78
+ _emnapi_env_ref(env);
79
+
80
+ return handle;
81
+ }
82
+
83
+ EMNAPI_INTERNAL_EXTERN void _emnapi_set_immediate(void (*callback)(void*), void* data);
84
+
85
+ static void _emnapi_ach_handle_env_unref(void* arg) {
86
+ napi_env env = (napi_env) arg;
87
+ _emnapi_env_unref(env);
88
+ }
89
+
90
+ static void
91
+ _emnapi_ach_handle_delete(napi_async_cleanup_hook_handle handle) {
92
+ _emnapi_remove_async_environment_cleanup_hook(handle->handle_);
93
+ if (handle->done_cb_ != NULL) handle->done_cb_(handle->done_data_);
94
+
95
+ _emnapi_set_immediate(_emnapi_ach_handle_env_unref, handle->env_);
96
+
97
+ free(handle->handle_);
98
+ free(handle);
99
+ }
100
+
101
+ napi_status
102
+ napi_add_async_cleanup_hook(napi_env env,
103
+ napi_async_cleanup_hook hook,
104
+ void* arg,
105
+ napi_async_cleanup_hook_handle* remove_handle) {
106
+ CHECK_ENV(env);
107
+ CHECK_ARG(env, hook);
108
+
109
+ napi_async_cleanup_hook_handle handle =
110
+ _emnapi_ach_handle_create(env, hook, arg);
111
+
112
+ if (remove_handle != NULL) *remove_handle = handle;
113
+
114
+ return napi_clear_last_error(env);
115
+ }
116
+
117
+ napi_status
118
+ napi_remove_async_cleanup_hook(napi_async_cleanup_hook_handle remove_handle) {
119
+ if (remove_handle == NULL) return napi_invalid_arg;
120
+
121
+ _emnapi_ach_handle_delete(remove_handle);
122
+
123
+ return napi_ok;
124
+ }
125
+
126
+ EXTERN_C_END
@@ -0,0 +1,53 @@
1
+ #include <node_api.h>
2
+ #include "emnapi_internal.h"
3
+
4
+ EXTERN_C_START
5
+
6
+ struct napi_async_context__ {
7
+ int32_t low;
8
+ int32_t high;
9
+ };
10
+
11
+ EMNAPI_INTERNAL_EXTERN napi_status
12
+ _emnapi_async_init_js(napi_value async_resource,
13
+ napi_value async_resource_name,
14
+ napi_async_context result);
15
+ EMNAPI_INTERNAL_EXTERN napi_status
16
+ _emnapi_async_destroy_js(napi_async_context async_context);
17
+
18
+ napi_status
19
+ napi_async_init(napi_env env,
20
+ napi_value async_resource,
21
+ napi_value async_resource_name,
22
+ napi_async_context* result) {
23
+ CHECK_ENV(env);
24
+ CHECK_ARG(env, async_resource_name);
25
+ CHECK_ARG(env, result);
26
+
27
+ napi_async_context ret = (napi_async_context) malloc(sizeof(struct napi_async_context__));
28
+
29
+ napi_status status = _emnapi_async_init_js(async_resource, async_resource_name, ret);
30
+ if (status != napi_ok) {
31
+ free(ret);
32
+ return napi_set_last_error(env, status, 0, NULL);
33
+ }
34
+
35
+ *result = ret;
36
+ return napi_clear_last_error(env);
37
+ }
38
+
39
+ napi_status napi_async_destroy(napi_env env,
40
+ napi_async_context async_context) {
41
+ CHECK_ENV(env);
42
+ CHECK_ARG(env, async_context);
43
+
44
+ napi_status status = _emnapi_async_destroy_js(async_context);
45
+ if (status != napi_ok) {
46
+ return napi_set_last_error(env, status, 0, NULL);
47
+ }
48
+ free(async_context);
49
+
50
+ return napi_clear_last_error(env);
51
+ }
52
+
53
+ EXTERN_C_END