emnapi 1.8.0 → 1.9.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 (48) hide show
  1. package/CMakeLists.txt +12 -13
  2. package/dist/library_napi.js +252 -120
  3. package/emnapi.gyp +8 -1
  4. package/include/node/emnapi.h +2 -1
  5. package/include/node/js_native_api.h +6 -6
  6. package/include/node/js_native_api_types.h +8 -7
  7. package/index.d.ts +12 -0
  8. package/index.js +36 -0
  9. package/lib/wasm32/libdlmalloc-mt.a +0 -0
  10. package/lib/wasm32/libdlmalloc.a +0 -0
  11. package/lib/wasm32/libemmalloc-mt.a +0 -0
  12. package/lib/wasm32/libemmalloc.a +0 -0
  13. package/lib/wasm32/libemnapi-basic-mt.a +0 -0
  14. package/lib/wasm32/libemnapi-basic.a +0 -0
  15. package/lib/wasm32/libemnapi.a +0 -0
  16. package/lib/wasm32-emscripten/libemnapi-basic.a +0 -0
  17. package/lib/wasm32-emscripten/libemnapi-mt.a +0 -0
  18. package/lib/wasm32-emscripten/libemnapi.a +0 -0
  19. package/lib/wasm32-wasi/libemnapi-basic-mt.a +0 -0
  20. package/lib/wasm32-wasi/libemnapi-basic.a +0 -0
  21. package/lib/wasm32-wasi/libemnapi.a +0 -0
  22. package/lib/wasm32-wasi-threads/libemnapi-basic-mt.a +0 -0
  23. package/lib/wasm32-wasi-threads/libemnapi-basic-napi-rs-mt.a +0 -0
  24. package/lib/wasm32-wasi-threads/libemnapi-basic.a +0 -0
  25. package/lib/wasm32-wasi-threads/libemnapi-mt.a +0 -0
  26. package/lib/wasm32-wasi-threads/libemnapi-napi-rs-mt.a +0 -0
  27. package/lib/wasm32-wasi-threads/libemnapi.a +0 -0
  28. package/lib/wasm32-wasip1/libemnapi-basic-mt.a +0 -0
  29. package/lib/wasm32-wasip1/libemnapi-basic.a +0 -0
  30. package/lib/wasm32-wasip1/libemnapi.a +0 -0
  31. package/lib/wasm32-wasip1-threads/libemnapi-basic-mt.a +0 -0
  32. package/lib/wasm32-wasip1-threads/libemnapi-basic-napi-rs-mt.a +0 -0
  33. package/lib/wasm32-wasip1-threads/libemnapi-basic.a +0 -0
  34. package/lib/wasm32-wasip1-threads/libemnapi-mt.a +0 -0
  35. package/lib/wasm32-wasip1-threads/libemnapi-napi-rs-mt.a +0 -0
  36. package/lib/wasm32-wasip1-threads/libemnapi.a +0 -0
  37. package/lib/wasm64-emscripten/libemnapi-basic.a +0 -0
  38. package/lib/wasm64-emscripten/libemnapi-mt.a +0 -0
  39. package/lib/wasm64-emscripten/libemnapi.a +0 -0
  40. package/package.json +5 -2
  41. package/src/async_cleanup_hook.c +0 -2
  42. package/src/emnapi_internal.h +12 -0
  43. package/src/node_api.c +1 -7
  44. package/src/thread/async_worker_create.c +24 -1
  45. package/src/threadsafe_function.c +110 -94
  46. package/src/threadsafe_function.h +51 -0
  47. package/src/uv/uv-common.c +9 -1
  48. package/src/wasi_wait.c +3 -0
@@ -2,11 +2,7 @@
2
2
  #include "emnapi_internal.h"
3
3
 
4
4
  #if NAPI_VERSION >= 4 && EMNAPI_HAVE_THREADS
5
- #include <stdatomic.h>
6
- #include <pthread.h>
7
- #include <errno.h>
8
- #include "uv.h"
9
- #include "uv/queue.h"
5
+ #include "threadsafe_function.h"
10
6
 
11
7
  EXTERN_C_START
12
8
 
@@ -23,33 +19,6 @@ struct data_queue_node {
23
19
  struct uv__queue q;
24
20
  };
25
21
 
26
- struct napi_threadsafe_function__ {
27
- ASYNC_RESOURCE_FIELD
28
- // These are variables protected by the mutex.
29
- pthread_mutex_t mutex;
30
- pthread_cond_t* cond;
31
- size_t queue_size;
32
- struct uv__queue queue;
33
- uv_async_t async;
34
- size_t thread_count;
35
- bool is_closing;
36
- atomic_uchar dispatch_state;
37
-
38
- // These are variables set once, upon creation, and then never again, which
39
- // means we don't need the mutex to read them.
40
- void* context;
41
- size_t max_queue_size;
42
-
43
- // These are variables accessed only from the loop thread.
44
- napi_ref ref;
45
- napi_env env;
46
- void* finalize_data;
47
- napi_finalize finalize_cb;
48
- napi_threadsafe_function_call_js call_js_cb;
49
- bool handles_closing;
50
- bool async_ref;
51
- };
52
-
53
22
  static void _emnapi_tsfn_default_call_js(napi_env env, napi_value cb, void* context, void* data) {
54
23
  if (!(env == NULL || cb == NULL)) {
55
24
  napi_value recv;
@@ -87,13 +56,14 @@ _emnapi_tsfn_create(napi_env env,
87
56
  napi_threadsafe_function ts_fn =
88
57
  (napi_threadsafe_function) calloc(1, sizeof(struct napi_threadsafe_function__));
89
58
  if (ts_fn == NULL) return NULL;
90
- EMNAPI_ASYNC_RESOURCE_CTOR(env, async_resource, async_resource_name, (emnapi_async_resource*) ts_fn);
59
+ EMNAPI_ASYNC_RESOURCE_CTOR(env, async_resource, async_resource_name, (emnapi_async_resource*) &ts_fn->async_resource);
60
+ ts_fn->async_resource.is_some = true;
91
61
  pthread_mutex_init(&ts_fn->mutex, NULL);
92
62
  ts_fn->cond = NULL;
93
63
  ts_fn->queue_size = 0;
94
64
  uv__queue_init(&ts_fn->queue);
95
65
  ts_fn->thread_count = initial_thread_count;
96
- ts_fn->is_closing = false;
66
+ ts_fn->state = napi_tsfn_state_open;
97
67
  ts_fn->dispatch_state = kDispatchIdle;
98
68
 
99
69
  ts_fn->context = context;
@@ -109,12 +79,29 @@ _emnapi_tsfn_create(napi_env env,
109
79
  EMNAPI_ASSERT_CALL(napi_add_env_cleanup_hook(env, _emnapi_tsfn_cleanup, ts_fn));
110
80
  _emnapi_env_ref(env);
111
81
 
112
- EMNAPI_KEEPALIVE_PUSH();
113
- _emnapi_ctx_increase_waiting_request_counter();
114
- ts_fn->async_ref = true;
82
+ ts_fn->async_ref = 0;
115
83
  return ts_fn;
116
84
  }
117
85
 
86
+ static void _emnapi_tsfn_release_resources(napi_threadsafe_function func) {
87
+ if (func->state != napi_tsfn_state_closed) {
88
+ func->state = napi_tsfn_state_closed;
89
+ if (func->ref != NULL) {
90
+ EMNAPI_ASSERT_CALL(napi_delete_reference(func->env, func->ref));
91
+ func->ref = NULL;
92
+ }
93
+ EMNAPI_ASYNC_RESOURCE_DTOR(func->env, (emnapi_async_resource*) &func->async_resource);
94
+ func->async_resource.is_some = false;
95
+ EMNAPI_ASSERT_CALL(napi_remove_env_cleanup_hook(func->env, _emnapi_tsfn_cleanup, func));
96
+ _emnapi_env_unref(func->env);
97
+ if (func->async_ref > 0) {
98
+ func->async_ref = 0;
99
+ EMNAPI_KEEPALIVE_POP();
100
+ _emnapi_ctx_decrease_waiting_request_counter();
101
+ }
102
+ }
103
+ }
104
+
118
105
  static void _emnapi_tsfn_destroy(napi_threadsafe_function func) {
119
106
  if (func == NULL) return;
120
107
  pthread_mutex_destroy(&func->mutex);
@@ -131,20 +118,7 @@ static void _emnapi_tsfn_destroy(napi_threadsafe_function func) {
131
118
  free(node);
132
119
  }
133
120
  uv__queue_init(&func->queue);
134
-
135
- if (func->ref != NULL) {
136
- EMNAPI_ASSERT_CALL(napi_delete_reference(func->env, func->ref));
137
- }
138
-
139
- EMNAPI_ASYNC_RESOURCE_DTOR(func->env, (emnapi_async_resource*) func);
140
-
141
- EMNAPI_ASSERT_CALL(napi_remove_env_cleanup_hook(func->env, _emnapi_tsfn_cleanup, func));
142
- _emnapi_env_unref(func->env);
143
- if (func->async_ref) {
144
- EMNAPI_KEEPALIVE_POP();
145
- _emnapi_ctx_decrease_waiting_request_counter();
146
- func->async_ref = false;
147
- }
121
+ _emnapi_tsfn_release_resources(func);
148
122
 
149
123
  free(func);
150
124
  }
@@ -165,8 +139,12 @@ static void _emnapi_tsfn_async_cb(uv_async_t* data) {
165
139
  // only main thread
166
140
  static napi_status _emnapi_tsfn_init(napi_threadsafe_function func) {
167
141
  uv_loop_t* loop = uv_default_loop();
142
+ bool should_delete = true;
168
143
  if (uv_async_init(loop, &func->async, _emnapi_tsfn_async_cb) == 0) {
169
144
  int r;
145
+ func->async_ref = 1;
146
+ EMNAPI_KEEPALIVE_PUSH();
147
+ _emnapi_ctx_increase_waiting_request_counter();
170
148
  if (func->max_queue_size > 0) {
171
149
  func->cond = (pthread_cond_t*) malloc(sizeof(pthread_cond_t));
172
150
  if (func->cond != NULL) {
@@ -181,23 +159,44 @@ static napi_status _emnapi_tsfn_init(napi_threadsafe_function func) {
181
159
  return napi_ok;
182
160
  }
183
161
  uv_close((uv_handle_t*) &func->async, _emnapi_tsfn_do_destroy);
162
+ should_delete = false;
163
+ }
164
+ if (should_delete) {
165
+ _emnapi_tsfn_destroy(func);
184
166
  }
185
- _emnapi_tsfn_destroy(func);
186
167
  return napi_generic_failure;
187
168
  }
188
169
 
189
- static void _emnapi_tsfn_empty_queue_and_delete(napi_threadsafe_function func) {
190
- while (!uv__queue_empty(&func->queue)) {
191
- struct uv__queue* q = uv__queue_head(&func->queue);
170
+ static void _emnapi_tsfn_empty_queue(napi_threadsafe_function func) {
171
+ struct uv__queue drain_queue;
172
+ uv__queue_init(&drain_queue);
173
+ pthread_mutex_lock(&func->mutex);
174
+ uv__queue_move(&func->queue, &drain_queue);
175
+ uv__queue_init(&func->queue);
176
+ func->queue_size = 0;
177
+ pthread_mutex_unlock(&func->mutex);
178
+
179
+ while (!uv__queue_empty(&drain_queue)) {
180
+ struct uv__queue* q = uv__queue_head(&drain_queue);
192
181
  struct data_queue_node* node = uv__queue_data(q, struct data_queue_node, q);
193
182
 
194
183
  func->call_js_cb(NULL, NULL, func->context, node->data);
195
184
 
196
185
  uv__queue_remove(q);
197
186
  uv__queue_init(q);
198
- func->queue_size--;
199
187
  free(node);
200
188
  }
189
+ }
190
+
191
+ static void _emnapi_tsfn_maybe_delete(napi_threadsafe_function func) {
192
+ pthread_mutex_lock(&func->mutex);
193
+ if (func->thread_count > 0) {
194
+ _emnapi_tsfn_release_resources(func);
195
+ pthread_mutex_unlock(&func->mutex);
196
+ return;
197
+ } else {
198
+ pthread_mutex_unlock(&func->mutex);
199
+ }
201
200
  _emnapi_tsfn_destroy(func);
202
201
  }
203
202
 
@@ -211,24 +210,25 @@ static napi_value _emnapi_tsfn_finalize_in_callback_scope(napi_env env, napi_cal
211
210
 
212
211
  static void _emnapi_tsfn_finalize(napi_threadsafe_function func) {
213
212
  napi_handle_scope scope = _emnapi_open_handle_scope();
213
+ _emnapi_tsfn_empty_queue(func);
214
214
  if (func->finalize_cb) {
215
215
  if (emnapi_is_node_binding_available()) {
216
216
  napi_value resource, cb;
217
- EMNAPI_ASSERT_CALL(napi_get_reference_value(func->env, func->resource_, &resource));
218
- EMNAPI_ASSERT_CALL(napi_create_function(func->env, NULL, 0, _emnapi_tsfn_finalize_in_callback_scope, func, &cb));
217
+ EMNAPI_ASSERT_CALL(napi_get_reference_value(func->env, func->async_resource.resource_, &resource));
218
+ EMNAPI_ASSERT_CALL(_emnapi_create_function(func->env, NULL, 0, _emnapi_tsfn_finalize_in_callback_scope, func, &cb));
219
219
  _emnapi_node_make_callback(func->env,
220
220
  resource,
221
221
  cb,
222
222
  NULL,
223
223
  0,
224
- func->async_context_.async_id,
225
- func->async_context_.trigger_async_id,
224
+ func->async_resource.async_context_.async_id,
225
+ func->async_resource.async_context_.trigger_async_id,
226
226
  NULL);
227
227
  } else {
228
228
  _emnapi_call_finalizer(0, func->env, func->finalize_cb, func->finalize_data, func->context);
229
229
  }
230
230
  }
231
- _emnapi_tsfn_empty_queue_and_delete(func);
231
+ _emnapi_tsfn_maybe_delete(func);
232
232
  _emnapi_close_handle_scope(scope);
233
233
  }
234
234
 
@@ -244,13 +244,14 @@ static void _emnapi_tsfn_close_handles_and_maybe_delete(
244
244
 
245
245
  if (set_closing) {
246
246
  pthread_mutex_lock(&func->mutex);
247
- func->is_closing = true;
247
+ func->state = napi_tsfn_state_closing;
248
248
  if (func->max_queue_size > 0) {
249
249
  pthread_cond_signal(func->cond);
250
250
  }
251
251
  pthread_mutex_unlock(&func->mutex);
252
252
  }
253
253
  if (func->handles_closing) {
254
+ EMNAPI_ASSERT_CALL(napi_close_handle_scope(func->env, scope));
254
255
  return;
255
256
  }
256
257
  func->handles_closing = true;
@@ -289,9 +290,7 @@ static bool _emnapi_tsfn_dispatch_one(napi_threadsafe_function func) {
289
290
  {
290
291
  pthread_mutex_lock(&func->mutex);
291
292
 
292
- if (func->is_closing) {
293
- _emnapi_tsfn_close_handles_and_maybe_delete(func, false);
294
- } else {
293
+ if (func->state == napi_tsfn_state_open) {
295
294
  size_t size = func->queue_size;
296
295
  if (size > 0) {
297
296
  struct uv__queue* q = uv__queue_head(&func->queue);
@@ -310,7 +309,7 @@ static bool _emnapi_tsfn_dispatch_one(napi_threadsafe_function func) {
310
309
 
311
310
  if (size == 0) {
312
311
  if (func->thread_count == 0) {
313
- func->is_closing = true;
312
+ func->state = napi_tsfn_state_closing;
314
313
  if (func->max_queue_size > 0) {
315
314
  pthread_cond_signal(func->cond);
316
315
  }
@@ -319,6 +318,8 @@ static bool _emnapi_tsfn_dispatch_one(napi_threadsafe_function func) {
319
318
  } else {
320
319
  has_more = true;
321
320
  }
321
+ } else {
322
+ _emnapi_tsfn_close_handles_and_maybe_delete(func, false);
322
323
  }
323
324
  pthread_mutex_unlock(&func->mutex);
324
325
  }
@@ -335,15 +336,15 @@ static bool _emnapi_tsfn_dispatch_one(napi_threadsafe_function func) {
335
336
 
336
337
  if (emnapi_is_node_binding_available()) {
337
338
  napi_value resource, cb;
338
- EMNAPI_ASSERT_CALL(napi_get_reference_value(func->env, func->resource_, &resource));
339
- EMNAPI_ASSERT_CALL(napi_create_function(func->env, NULL, 0, _emnapi_tsfn_call_js_cb_in_callback_scope, jscb_data, &cb));
339
+ EMNAPI_ASSERT_CALL(napi_get_reference_value(func->env, func->async_resource.resource_, &resource));
340
+ EMNAPI_ASSERT_CALL(_emnapi_create_function(func->env, NULL, 0, _emnapi_tsfn_call_js_cb_in_callback_scope, jscb_data, &cb));
340
341
  _emnapi_node_make_callback(func->env,
341
342
  resource,
342
343
  cb,
343
344
  NULL,
344
345
  0,
345
- func->async_context_.async_id,
346
- func->async_context_.trigger_async_id,
346
+ func->async_resource.async_context_.async_id,
347
+ func->async_resource.async_context_.trigger_async_id,
347
348
  NULL);
348
349
  } else {
349
350
  _emnapi_callback_into_module(0, func->env, _emnapi_tsfn_call_js_cb, jscb_data, 1);
@@ -494,7 +495,7 @@ napi_call_threadsafe_function(napi_threadsafe_function func,
494
495
 
495
496
  while (func->queue_size >= func->max_queue_size &&
496
497
  func->max_queue_size > 0 &&
497
- !func->is_closing) {
498
+ func->state == napi_tsfn_state_open) {
498
499
  if (mode == napi_tsfn_nonblocking) {
499
500
  pthread_mutex_unlock(&func->mutex);
500
501
  return napi_queue_full;
@@ -502,16 +503,7 @@ napi_call_threadsafe_function(napi_threadsafe_function func,
502
503
  pthread_cond_wait(func->cond, &func->mutex);
503
504
  }
504
505
 
505
- if (func->is_closing) {
506
- if (func->thread_count == 0) {
507
- pthread_mutex_unlock(&func->mutex);
508
- return napi_invalid_arg;
509
- } else {
510
- func->thread_count--;
511
- pthread_mutex_unlock(&func->mutex);
512
- return napi_closing;
513
- }
514
- } else {
506
+ if (func->state == napi_tsfn_state_open) {
515
507
  struct data_queue_node* queue_node = (struct data_queue_node*) malloc(sizeof(struct data_queue_node));
516
508
  if (queue_node == NULL) {
517
509
  pthread_mutex_unlock(&func->mutex);
@@ -524,6 +516,20 @@ napi_call_threadsafe_function(napi_threadsafe_function func,
524
516
  pthread_mutex_unlock(&func->mutex);
525
517
  return napi_ok;
526
518
  }
519
+
520
+ if (func->thread_count == 0) {
521
+ pthread_mutex_unlock(&func->mutex);
522
+ return napi_invalid_arg;
523
+ }
524
+ func->thread_count--;
525
+
526
+ if (!(func->state == napi_tsfn_state_closed && func->thread_count == 0)) {
527
+ pthread_mutex_unlock(&func->mutex);
528
+ return napi_closing;
529
+ }
530
+ pthread_mutex_unlock(&func->mutex);
531
+ _emnapi_tsfn_destroy(func);
532
+ return napi_closing;
527
533
  #else
528
534
  return napi_generic_failure;
529
535
  #endif
@@ -535,15 +541,14 @@ napi_acquire_threadsafe_function(napi_threadsafe_function func) {
535
541
  CHECK_NOT_NULL(func);
536
542
  pthread_mutex_lock(&func->mutex);
537
543
 
538
- if (func->is_closing) {
544
+ if (func->state == napi_tsfn_state_open) {
545
+ func->thread_count++;
539
546
  pthread_mutex_unlock(&func->mutex);
540
- return napi_closing;
547
+ return napi_ok;
541
548
  }
542
549
 
543
- func->thread_count++;
544
-
545
550
  pthread_mutex_unlock(&func->mutex);
546
- return napi_ok;
551
+ return napi_closing;
547
552
  #else
548
553
  return napi_generic_failure;
549
554
  #endif
@@ -564,9 +569,11 @@ napi_release_threadsafe_function(napi_threadsafe_function func,
564
569
  func->thread_count--;
565
570
 
566
571
  if (func->thread_count == 0 || mode == napi_tsfn_abort) {
567
- if (!func->is_closing) {
568
- func->is_closing = (mode == napi_tsfn_abort);
569
- if (func->is_closing && func->max_queue_size > 0) {
572
+ if (func->state == napi_tsfn_state_open) {
573
+ if (mode == napi_tsfn_abort) {
574
+ func->state = napi_tsfn_state_closing;
575
+ }
576
+ if (func->state == napi_tsfn_state_closing && func->max_queue_size > 0) {
570
577
  pthread_cond_signal(func->cond);
571
578
  }
572
579
 
@@ -574,7 +581,12 @@ napi_release_threadsafe_function(napi_threadsafe_function func,
574
581
  }
575
582
  }
576
583
 
584
+ if (!(func->state == napi_tsfn_state_closed && func->thread_count == 0)) {
585
+ pthread_mutex_unlock(&func->mutex);
586
+ return napi_ok;
587
+ }
577
588
  pthread_mutex_unlock(&func->mutex);
589
+ _emnapi_tsfn_destroy(func);
578
590
 
579
591
  return napi_ok;
580
592
  #else
@@ -585,10 +597,13 @@ napi_release_threadsafe_function(napi_threadsafe_function func,
585
597
  napi_status
586
598
  napi_unref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func) {
587
599
  #if EMNAPI_HAVE_THREADS
588
- if (func->async_ref) {
589
- EMNAPI_KEEPALIVE_POP();
590
- _emnapi_ctx_decrease_waiting_request_counter();
591
- func->async_ref = false;
600
+ CHECK_NOT_NULL(func);
601
+ if (func->async_ref > 0) {
602
+ func->async_ref--;
603
+ if (func->async_ref == 0) {
604
+ EMNAPI_KEEPALIVE_POP();
605
+ _emnapi_ctx_decrease_waiting_request_counter();
606
+ }
592
607
  }
593
608
  return napi_ok;
594
609
  #else
@@ -599,11 +614,12 @@ napi_unref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function
599
614
  napi_status
600
615
  napi_ref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func) {
601
616
  #if EMNAPI_HAVE_THREADS
617
+ CHECK_NOT_NULL(func);
602
618
  if (!func->async_ref) {
603
619
  EMNAPI_KEEPALIVE_PUSH();
604
620
  _emnapi_ctx_increase_waiting_request_counter();
605
- func->async_ref = true;
606
621
  }
622
+ func->async_ref++;
607
623
  return napi_ok;
608
624
  #else
609
625
  return napi_generic_failure;
@@ -0,0 +1,51 @@
1
+ #ifndef SRC_THREADSAFE_FUNCTION_H_
2
+ #define SRC_THREADSAFE_FUNCTION_H_
3
+
4
+ #include "node_api.h"
5
+ #include "emnapi_internal.h"
6
+
7
+ #include <stdatomic.h>
8
+ #include <pthread.h>
9
+ #include <errno.h>
10
+ #include "uv.h"
11
+ #include "uv/queue.h"
12
+
13
+ typedef struct optional_async_resource {
14
+ ASYNC_RESOURCE_FIELD
15
+ bool is_some;
16
+ } optional_async_resource;
17
+
18
+ typedef enum napi_threadsafe_function_state {
19
+ napi_tsfn_state_open,
20
+ napi_tsfn_state_closing,
21
+ napi_tsfn_state_closed
22
+ } napi_threadsafe_function_state;
23
+
24
+ struct napi_threadsafe_function__ {
25
+ optional_async_resource async_resource;
26
+ // These are variables protected by the mutex.
27
+ pthread_mutex_t mutex;
28
+ pthread_cond_t* cond;
29
+ size_t queue_size;
30
+ struct uv__queue queue;
31
+ uv_async_t async;
32
+ size_t thread_count;
33
+ napi_threadsafe_function_state state;
34
+ atomic_uchar dispatch_state;
35
+
36
+ // These are variables set once, upon creation, and then never again, which
37
+ // means we don't need the mutex to read them.
38
+ void* context;
39
+ size_t max_queue_size;
40
+
41
+ // These are variables accessed only from the loop thread.
42
+ napi_ref ref;
43
+ napi_env env;
44
+ void* finalize_data;
45
+ napi_finalize finalize_cb;
46
+ napi_threadsafe_function_call_js call_js_cb;
47
+ bool handles_closing;
48
+ unsigned int async_ref;
49
+ };
50
+
51
+ #endif
@@ -1,7 +1,8 @@
1
+ #include <stddef.h>
2
+
1
3
  #if defined(__EMSCRIPTEN_PTHREADS__) || defined(_REENTRANT)
2
4
 
3
5
  #include <errno.h>
4
- #include <stddef.h>
5
6
  #include <stdlib.h>
6
7
  #include <string.h>
7
8
  #include "uv-common.h"
@@ -183,4 +184,11 @@ uint64_t uv_metrics_idle_time(uv_loop_t* loop) {
183
184
  return idle_time;
184
185
  }
185
186
 
187
+ #else
188
+
189
+ typedef struct uv_loop_s uv_loop_t;
190
+ uv_loop_t* uv_default_loop(void) {
191
+ return NULL;
192
+ }
193
+
186
194
  #endif
package/src/wasi_wait.c CHANGED
@@ -6,6 +6,8 @@
6
6
  #include <stdio.h>
7
7
  #include "emnapi_internal.h"
8
8
 
9
+ EMNAPI_INTERNAL_EXTERN void _emnapi_worker_ref(pthread_t pid);
10
+
9
11
  struct __pthread {
10
12
  unsigned char _[32];
11
13
  volatile int cancel;
@@ -28,6 +30,7 @@ void emnapi_thread_crashed() {
28
30
 
29
31
  void _emnapi_yield() {
30
32
  if (crashed_thread_id) {
33
+ _emnapi_worker_ref(crashed_thread_id);
31
34
  _emnapi_runtime_keepalive_push();
32
35
  _emnapi_unwind();
33
36
  }