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.
- package/CMakeLists.txt +23 -2
- package/README.md +213 -94
- package/dist/library_napi.js +258 -33
- package/include/emnapi.h +1 -1
- package/include/js_native_api.h +1 -1
- package/index.js +6 -0
- package/lib/wasm32/libemnapi-basic.a +0 -0
- package/lib/wasm32/libemnapi.a +0 -0
- package/lib/wasm32-emscripten/libemnapi-basic.a +0 -0
- package/lib/wasm32-emscripten/libemnapi-mt.a +0 -0
- package/lib/wasm32-emscripten/libemnapi.a +0 -0
- package/lib/wasm32-emscripten.txt +2 -2
- package/lib/wasm32-wasi/libemnapi-basic.a +0 -0
- package/lib/wasm32-wasi/libemnapi.a +0 -0
- package/package.json +1 -1
- package/src/async_cleanup_hook.c +126 -0
- package/src/async_context.c +53 -0
- package/src/async_work.c +236 -0
- package/src/emnapi.c +1 -1324
- package/src/emnapi_internal.h +171 -0
- package/src/js_native_api.c +106 -0
- package/src/node_api.c +73 -0
- package/src/threadsafe_function.c +617 -0
- package/src/uv/threadpool.c +36 -5
- package/src/uv/unix/async.c +1 -1
- package/src/uv/unix/thread.c +10 -1
- /package/include/{common.h → emnapi_common.h} +0 -0
package/src/async_work.c
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#include "node_api.h"
|
|
2
|
+
#include "emnapi_internal.h"
|
|
3
|
+
|
|
4
|
+
#if EMNAPI_HAVE_THREADS
|
|
5
|
+
|
|
6
|
+
#include <pthread.h>
|
|
7
|
+
#include <errno.h>
|
|
8
|
+
#include "uv.h"
|
|
9
|
+
|
|
10
|
+
EXTERN_C_START
|
|
11
|
+
|
|
12
|
+
struct napi_async_work__ {
|
|
13
|
+
ASYNC_RESOURCE_FIELD
|
|
14
|
+
uv_work_t work_req_;
|
|
15
|
+
napi_env env;
|
|
16
|
+
void* data;
|
|
17
|
+
napi_async_execute_callback execute;
|
|
18
|
+
napi_async_complete_callback complete;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
static napi_async_work async_work_init(
|
|
22
|
+
napi_env env,
|
|
23
|
+
napi_value async_resource,
|
|
24
|
+
napi_value async_resource_name,
|
|
25
|
+
napi_async_execute_callback execute,
|
|
26
|
+
napi_async_complete_callback complete,
|
|
27
|
+
void* data
|
|
28
|
+
) {
|
|
29
|
+
napi_async_work work = (napi_async_work)calloc(1, sizeof(struct napi_async_work__));
|
|
30
|
+
if (work == NULL) return NULL;
|
|
31
|
+
EMNAPI_ASYNC_RESOURCE_CTOR(env, async_resource, async_resource_name, (emnapi_async_resource*)work);
|
|
32
|
+
work->env = env;
|
|
33
|
+
work->execute = execute;
|
|
34
|
+
work->complete = complete;
|
|
35
|
+
work->data = data;
|
|
36
|
+
return work;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static void async_work_delete(napi_async_work work) {
|
|
40
|
+
EMNAPI_ASYNC_RESOURCE_DTOR(work->env, (emnapi_async_resource*)work);
|
|
41
|
+
free(work);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static void async_work_do_thread_pool_work(napi_async_work work) {
|
|
45
|
+
work->execute(work->env, work->data);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
typedef struct complete_wrap_s {
|
|
49
|
+
int status;
|
|
50
|
+
napi_async_work work;
|
|
51
|
+
} complete_wrap_t;
|
|
52
|
+
|
|
53
|
+
static napi_status convert_error_code(int code) {
|
|
54
|
+
switch (code) {
|
|
55
|
+
case 0:
|
|
56
|
+
return napi_ok;
|
|
57
|
+
case EINVAL:
|
|
58
|
+
return napi_invalid_arg;
|
|
59
|
+
case ECANCELED:
|
|
60
|
+
return napi_cancelled;
|
|
61
|
+
default:
|
|
62
|
+
return napi_generic_failure;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static void async_work_on_complete(napi_env env, void* args) {
|
|
67
|
+
complete_wrap_t* wrap = (complete_wrap_t*) args;
|
|
68
|
+
napi_status status = convert_error_code(wrap->status);
|
|
69
|
+
napi_async_work work = wrap->work;
|
|
70
|
+
free(wrap);
|
|
71
|
+
napi_env _env = work->env;
|
|
72
|
+
void* data = work->data;
|
|
73
|
+
work->complete(_env, status, data);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static napi_value async_work_after_cb(napi_env env, napi_callback_info info) {
|
|
77
|
+
void* data = NULL;
|
|
78
|
+
EMNAPI_ASSERT_CALL(napi_get_cb_info(env, info, NULL, NULL, NULL, &data));
|
|
79
|
+
complete_wrap_t* wrap = (complete_wrap_t*) data;
|
|
80
|
+
_emnapi_call_into_module(env, async_work_on_complete, wrap, 1);
|
|
81
|
+
return NULL;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static void async_work_after_thread_pool_work(napi_async_work work, int status) {
|
|
85
|
+
if (work->complete == NULL) return;
|
|
86
|
+
napi_handle_scope scope;
|
|
87
|
+
napi_value resource, cb;
|
|
88
|
+
napi_env env = work->env;
|
|
89
|
+
EMNAPI_ASSERT_CALL(napi_open_handle_scope(env, &scope));
|
|
90
|
+
EMNAPI_ASSERT_CALL(napi_get_reference_value(env, work->resource_, &resource));
|
|
91
|
+
complete_wrap_t* wrap = (complete_wrap_t*) malloc(sizeof(complete_wrap_t));
|
|
92
|
+
assert(wrap != NULL);
|
|
93
|
+
wrap->status = status;
|
|
94
|
+
wrap->work = work;
|
|
95
|
+
if (emnapi_is_node_binding_available()) {
|
|
96
|
+
EMNAPI_ASSERT_CALL(napi_create_function(env, NULL, 0, async_work_after_cb, wrap, &cb));
|
|
97
|
+
_emnapi_node_make_callback(env,
|
|
98
|
+
resource,
|
|
99
|
+
cb,
|
|
100
|
+
NULL,
|
|
101
|
+
0,
|
|
102
|
+
work->async_context_.async_id,
|
|
103
|
+
work->async_context_.trigger_async_id,
|
|
104
|
+
NULL);
|
|
105
|
+
} else {
|
|
106
|
+
_emnapi_call_into_module(env, async_work_on_complete, wrap, 1);
|
|
107
|
+
}
|
|
108
|
+
EMNAPI_ASSERT_CALL(napi_close_handle_scope(env, scope));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static void async_work_schedule_work_on_execute(uv_work_t* req) {
|
|
112
|
+
napi_async_work self = container_of(req, struct napi_async_work__, work_req_);
|
|
113
|
+
async_work_do_thread_pool_work(self);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static void async_work_schedule_work_on_complete(uv_work_t* req, int status) {
|
|
117
|
+
napi_async_work self = container_of(req, struct napi_async_work__, work_req_);
|
|
118
|
+
EMNAPI_KEEPALIVE_POP();
|
|
119
|
+
_emnapi_ctx_decrease_waiting_request_counter();
|
|
120
|
+
async_work_after_thread_pool_work(self, status);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static void async_work_schedule_work(napi_async_work work) {
|
|
124
|
+
EMNAPI_KEEPALIVE_PUSH();
|
|
125
|
+
_emnapi_ctx_increase_waiting_request_counter();
|
|
126
|
+
int status = uv_queue_work(uv_default_loop(),
|
|
127
|
+
&work->work_req_,
|
|
128
|
+
async_work_schedule_work_on_execute,
|
|
129
|
+
async_work_schedule_work_on_complete);
|
|
130
|
+
CHECK_EQ(status, 0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static int async_work_cancel_work(napi_async_work work) {
|
|
134
|
+
return uv_cancel((uv_req_t*)&work->work_req_);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
EXTERN_C_END
|
|
138
|
+
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
EXTERN_C_START
|
|
142
|
+
|
|
143
|
+
napi_status napi_create_async_work(napi_env env,
|
|
144
|
+
napi_value async_resource,
|
|
145
|
+
napi_value async_resource_name,
|
|
146
|
+
napi_async_execute_callback execute,
|
|
147
|
+
napi_async_complete_callback complete,
|
|
148
|
+
void* data,
|
|
149
|
+
napi_async_work* result) {
|
|
150
|
+
#if EMNAPI_HAVE_THREADS
|
|
151
|
+
CHECK_ENV(env);
|
|
152
|
+
CHECK_ARG(env, execute);
|
|
153
|
+
CHECK_ARG(env, result);
|
|
154
|
+
|
|
155
|
+
napi_status status;
|
|
156
|
+
napi_value resource;
|
|
157
|
+
napi_value resource_name;
|
|
158
|
+
if (async_resource != NULL) {
|
|
159
|
+
status = napi_coerce_to_object(env, async_resource, &resource);
|
|
160
|
+
if (status != napi_ok) return status;
|
|
161
|
+
} else {
|
|
162
|
+
status = napi_create_object(env, &resource);
|
|
163
|
+
if (status != napi_ok) return status;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
CHECK_ARG(env, async_resource_name);
|
|
167
|
+
status = napi_coerce_to_string(env, async_resource_name, &resource_name);
|
|
168
|
+
if (status != napi_ok) return status;
|
|
169
|
+
|
|
170
|
+
napi_async_work work = async_work_init(env,
|
|
171
|
+
resource,
|
|
172
|
+
resource_name,
|
|
173
|
+
execute,
|
|
174
|
+
complete,
|
|
175
|
+
data);
|
|
176
|
+
if (work == NULL) {
|
|
177
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
*result = work;
|
|
181
|
+
|
|
182
|
+
return napi_clear_last_error(env);
|
|
183
|
+
#else
|
|
184
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
185
|
+
#endif
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
napi_status napi_delete_async_work(napi_env env, napi_async_work work) {
|
|
189
|
+
#if EMNAPI_HAVE_THREADS
|
|
190
|
+
CHECK_ENV(env);
|
|
191
|
+
CHECK_ARG(env, work);
|
|
192
|
+
|
|
193
|
+
async_work_delete(work);
|
|
194
|
+
|
|
195
|
+
return napi_clear_last_error(env);
|
|
196
|
+
#else
|
|
197
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
198
|
+
#endif
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
napi_status napi_queue_async_work(napi_env env, napi_async_work work) {
|
|
202
|
+
#if EMNAPI_HAVE_THREADS
|
|
203
|
+
CHECK_ENV(env);
|
|
204
|
+
CHECK_ARG(env, work);
|
|
205
|
+
|
|
206
|
+
async_work_schedule_work(work);
|
|
207
|
+
|
|
208
|
+
return napi_clear_last_error(env);
|
|
209
|
+
#else
|
|
210
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
211
|
+
#endif
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#define CALL_UV(env, condition) \
|
|
215
|
+
do { \
|
|
216
|
+
int result = (condition); \
|
|
217
|
+
napi_status status = convert_error_code(result); \
|
|
218
|
+
if (status != napi_ok) { \
|
|
219
|
+
return napi_set_last_error(env, status, result, NULL); \
|
|
220
|
+
} \
|
|
221
|
+
} while (0)
|
|
222
|
+
|
|
223
|
+
napi_status napi_cancel_async_work(napi_env env, napi_async_work work) {
|
|
224
|
+
#if EMNAPI_HAVE_THREADS
|
|
225
|
+
CHECK_ENV(env);
|
|
226
|
+
CHECK_ARG(env, work);
|
|
227
|
+
|
|
228
|
+
CALL_UV(env, async_work_cancel_work(work));
|
|
229
|
+
|
|
230
|
+
return napi_clear_last_error(env);
|
|
231
|
+
#else
|
|
232
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
233
|
+
#endif
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
EXTERN_C_END
|