emnapi 0.31.0 → 0.32.2
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 +22 -1
- package/README.md +19 -16
- package/dist/library_napi.js +217 -9
- 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_common.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
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#include "emnapi.h"
|
|
2
|
+
|
|
3
|
+
#if defined(__EMSCRIPTEN__) || defined(__wasi__)
|
|
4
|
+
#include <assert.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#else
|
|
7
|
+
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
|
8
|
+
#define static_assert _Static_assert
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#include <stddef.h>
|
|
12
|
+
|
|
13
|
+
EXTERN_C_START
|
|
14
|
+
void* malloc(size_t size);
|
|
15
|
+
void* calloc(size_t count, size_t size);
|
|
16
|
+
void free(void* p);
|
|
17
|
+
EXTERN_C_END
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#ifdef __EMSCRIPTEN__
|
|
21
|
+
#include <emscripten.h>
|
|
22
|
+
|
|
23
|
+
#if __EMSCRIPTEN_major__ * 10000 + __EMSCRIPTEN_minor__ * 100 + __EMSCRIPTEN_tiny__ >= 30114 // NOLINT
|
|
24
|
+
#include <emscripten/eventloop.h>
|
|
25
|
+
#endif
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#ifdef NDEBUG
|
|
29
|
+
#define EMNAPI_ASSERT_CALL(the_call) (the_call)
|
|
30
|
+
#else
|
|
31
|
+
#if defined(__EMSCRIPTEN__) || defined(__wasi__)
|
|
32
|
+
#define EMNAPI_ASSERT_CALL(the_call) (assert(napi_ok == (the_call)))
|
|
33
|
+
#else
|
|
34
|
+
#define EMNAPI_ASSERT_CALL(the_call) (the_call)
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#define CHECK_ENV(env) \
|
|
39
|
+
do { \
|
|
40
|
+
if ((env) == NULL) { \
|
|
41
|
+
return napi_invalid_arg; \
|
|
42
|
+
} \
|
|
43
|
+
} while (0)
|
|
44
|
+
|
|
45
|
+
#define RETURN_STATUS_IF_FALSE(env, condition, status) \
|
|
46
|
+
do { \
|
|
47
|
+
if (!(condition)) { \
|
|
48
|
+
return napi_set_last_error((env), (status), 0, NULL); \
|
|
49
|
+
} \
|
|
50
|
+
} while (0)
|
|
51
|
+
|
|
52
|
+
#define CHECK_ARG(env, arg) \
|
|
53
|
+
RETURN_STATUS_IF_FALSE((env), ((arg) != NULL), napi_invalid_arg)
|
|
54
|
+
|
|
55
|
+
#define CHECK(expr) \
|
|
56
|
+
do { \
|
|
57
|
+
if (!(expr)) { \
|
|
58
|
+
__builtin_trap(); \
|
|
59
|
+
} \
|
|
60
|
+
} while (0)
|
|
61
|
+
|
|
62
|
+
#define CHECK_NOT_NULL(val) CHECK((val) != NULL)
|
|
63
|
+
|
|
64
|
+
#define CHECK_EQ(a, b) CHECK((a) == (b))
|
|
65
|
+
#define CHECK_LE(a, b) CHECK((a) <= (b))
|
|
66
|
+
|
|
67
|
+
EXTERN_C_START
|
|
68
|
+
|
|
69
|
+
EMNAPI_INTERNAL_EXTERN napi_status napi_set_last_error(napi_env env,
|
|
70
|
+
napi_status error_code,
|
|
71
|
+
uint32_t engine_error_code,
|
|
72
|
+
void* engine_reserved);
|
|
73
|
+
EMNAPI_INTERNAL_EXTERN napi_status napi_clear_last_error(napi_env env);
|
|
74
|
+
|
|
75
|
+
#ifdef __EMSCRIPTEN__
|
|
76
|
+
#if __EMSCRIPTEN_major__ * 10000 + __EMSCRIPTEN_minor__ * 100 + __EMSCRIPTEN_tiny__ >= 30114 // NOLINT
|
|
77
|
+
#define EMNAPI_KEEPALIVE_PUSH emscripten_runtime_keepalive_push
|
|
78
|
+
#define EMNAPI_KEEPALIVE_POP emscripten_runtime_keepalive_pop
|
|
79
|
+
#else
|
|
80
|
+
|
|
81
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_runtime_keepalive_push();
|
|
82
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_runtime_keepalive_pop();
|
|
83
|
+
|
|
84
|
+
#define EMNAPI_KEEPALIVE_PUSH _emnapi_runtime_keepalive_push
|
|
85
|
+
#define EMNAPI_KEEPALIVE_POP _emnapi_runtime_keepalive_pop
|
|
86
|
+
#endif
|
|
87
|
+
#else
|
|
88
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_runtime_keepalive_push();
|
|
89
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_runtime_keepalive_pop();
|
|
90
|
+
|
|
91
|
+
#define EMNAPI_KEEPALIVE_PUSH _emnapi_runtime_keepalive_push
|
|
92
|
+
#define EMNAPI_KEEPALIVE_POP _emnapi_runtime_keepalive_pop
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_env_ref(napi_env env);
|
|
96
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_env_unref(napi_env env);
|
|
97
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_ctx_increase_waiting_request_counter();
|
|
98
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_ctx_decrease_waiting_request_counter();
|
|
99
|
+
|
|
100
|
+
#if defined(__EMSCRIPTEN_PTHREADS__) || defined(_REENTRANT)
|
|
101
|
+
#define EMNAPI_HAVE_THREADS 1
|
|
102
|
+
#else
|
|
103
|
+
#define EMNAPI_HAVE_THREADS 0
|
|
104
|
+
#endif
|
|
105
|
+
|
|
106
|
+
#if EMNAPI_HAVE_THREADS
|
|
107
|
+
|
|
108
|
+
#define container_of(ptr, type, member) \
|
|
109
|
+
((type *) ((char *) (ptr) - offsetof(type, member)))
|
|
110
|
+
|
|
111
|
+
typedef void (*_emnapi_call_into_module_callback)(napi_env env, void* args);
|
|
112
|
+
EMNAPI_INTERNAL_EXTERN
|
|
113
|
+
void _emnapi_call_into_module(napi_env env,
|
|
114
|
+
_emnapi_call_into_module_callback callback,
|
|
115
|
+
void* args,
|
|
116
|
+
int close_scope_if_throw);
|
|
117
|
+
|
|
118
|
+
#endif
|
|
119
|
+
|
|
120
|
+
typedef double async_id_t;
|
|
121
|
+
typedef struct async_context {
|
|
122
|
+
async_id_t async_id;
|
|
123
|
+
async_id_t trigger_async_id;
|
|
124
|
+
} async_context;
|
|
125
|
+
|
|
126
|
+
#define ASYNC_RESOURCE_FIELD \
|
|
127
|
+
napi_ref resource_; \
|
|
128
|
+
async_context async_context_;
|
|
129
|
+
|
|
130
|
+
typedef struct emnapi_async_resource {
|
|
131
|
+
ASYNC_RESOURCE_FIELD
|
|
132
|
+
} emnapi_async_resource;
|
|
133
|
+
|
|
134
|
+
// call node::EmitAsyncInit
|
|
135
|
+
EMNAPI_INTERNAL_EXTERN
|
|
136
|
+
void _emnapi_node_emit_async_init(napi_value async_resource,
|
|
137
|
+
napi_value async_resource_name,
|
|
138
|
+
async_id_t trigger_async_id,
|
|
139
|
+
async_context* result);
|
|
140
|
+
// call node::EmitAsyncDestroy
|
|
141
|
+
EMNAPI_INTERNAL_EXTERN
|
|
142
|
+
void _emnapi_node_emit_async_destroy(async_id_t id, async_id_t trigger_async_id);
|
|
143
|
+
|
|
144
|
+
// EMNAPI_INTERNAL_EXTERN void _emnapi_node_open_callback_scope(napi_value async_resource, async_id_t id, async_id_t trigger_async_id, int64_t* result);
|
|
145
|
+
// EMNAPI_INTERNAL_EXTERN void _emnapi_node_close_callback_scope(int64_t* scope);
|
|
146
|
+
|
|
147
|
+
// call node:MakeCallback
|
|
148
|
+
EMNAPI_INTERNAL_EXTERN
|
|
149
|
+
napi_status _emnapi_node_make_callback(napi_env env,
|
|
150
|
+
napi_value async_resource,
|
|
151
|
+
napi_value cb,
|
|
152
|
+
napi_value* argv,
|
|
153
|
+
size_t size,
|
|
154
|
+
double async_id,
|
|
155
|
+
double trigger_async_id,
|
|
156
|
+
napi_value* result);
|
|
157
|
+
|
|
158
|
+
#define EMNAPI_ASYNC_RESOURCE_CTOR(env, res, name, ar) \
|
|
159
|
+
do { \
|
|
160
|
+
EMNAPI_ASSERT_CALL(napi_create_reference((env), (res), 1, &(ar)->resource_)); \
|
|
161
|
+
_emnapi_node_emit_async_init((res), (name), -1.0, &(ar)->async_context_); \
|
|
162
|
+
} while (0)
|
|
163
|
+
|
|
164
|
+
#define EMNAPI_ASYNC_RESOURCE_DTOR(env, ar) \
|
|
165
|
+
do { \
|
|
166
|
+
EMNAPI_ASSERT_CALL(napi_delete_reference((env), (ar)->resource_)); \
|
|
167
|
+
_emnapi_node_emit_async_destroy((ar)->async_context_.async_id, \
|
|
168
|
+
(ar)->async_context_.trigger_async_id); \
|
|
169
|
+
} while (0)
|
|
170
|
+
|
|
171
|
+
EXTERN_C_END
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#include "emnapi_common.h"
|
|
2
|
+
|
|
3
|
+
#ifdef __EMSCRIPTEN__
|
|
4
|
+
#include <emscripten/heap.h>
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
EXTERN_C_START
|
|
8
|
+
|
|
9
|
+
static const char* emnapi_error_messages[] = {
|
|
10
|
+
NULL,
|
|
11
|
+
"Invalid argument",
|
|
12
|
+
"An object was expected",
|
|
13
|
+
"A string was expected",
|
|
14
|
+
"A string or symbol was expected",
|
|
15
|
+
"A function was expected",
|
|
16
|
+
"A number was expected",
|
|
17
|
+
"A boolean was expected",
|
|
18
|
+
"An array was expected",
|
|
19
|
+
"Unknown failure",
|
|
20
|
+
"An exception is pending",
|
|
21
|
+
"The async work item was cancelled",
|
|
22
|
+
"napi_escape_handle already called on scope",
|
|
23
|
+
"Invalid handle scope usage",
|
|
24
|
+
"Invalid callback scope usage",
|
|
25
|
+
"Thread-safe function queue is full",
|
|
26
|
+
"Thread-safe function handle is closing",
|
|
27
|
+
"A bigint was expected",
|
|
28
|
+
"A date was expected",
|
|
29
|
+
"An arraybuffer was expected",
|
|
30
|
+
"A detachable arraybuffer was expected",
|
|
31
|
+
"Main thread would deadlock",
|
|
32
|
+
"External buffers are not allowed"
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_get_last_error_info(napi_env env,
|
|
36
|
+
napi_status* error_code,
|
|
37
|
+
uint32_t* engine_error_code,
|
|
38
|
+
void** engine_reserved);
|
|
39
|
+
|
|
40
|
+
napi_status napi_get_last_error_info(
|
|
41
|
+
napi_env env, const napi_extended_error_info** result) {
|
|
42
|
+
static napi_extended_error_info last_error;
|
|
43
|
+
CHECK_ENV(env);
|
|
44
|
+
CHECK_ARG(env, result);
|
|
45
|
+
|
|
46
|
+
const int last_status = napi_no_external_buffers_allowed;
|
|
47
|
+
|
|
48
|
+
static_assert((sizeof(emnapi_error_messages) / sizeof(const char*)) == napi_no_external_buffers_allowed + 1,
|
|
49
|
+
"Count of error messages must match count of error values");
|
|
50
|
+
|
|
51
|
+
_emnapi_get_last_error_info(env,
|
|
52
|
+
&last_error.error_code,
|
|
53
|
+
&last_error.engine_error_code,
|
|
54
|
+
&last_error.engine_reserved);
|
|
55
|
+
|
|
56
|
+
CHECK_LE(last_error.error_code, last_status);
|
|
57
|
+
|
|
58
|
+
last_error.error_message = emnapi_error_messages[last_error.error_code];
|
|
59
|
+
|
|
60
|
+
if (last_error.error_code == napi_ok) {
|
|
61
|
+
napi_clear_last_error(env);
|
|
62
|
+
last_error.engine_error_code = 0;
|
|
63
|
+
last_error.engine_reserved = NULL;
|
|
64
|
+
}
|
|
65
|
+
*result = &last_error;
|
|
66
|
+
return napi_ok;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#define PAGESIZE 65536
|
|
70
|
+
|
|
71
|
+
napi_status napi_adjust_external_memory(napi_env env,
|
|
72
|
+
int64_t change_in_bytes,
|
|
73
|
+
int64_t* adjusted_value) {
|
|
74
|
+
CHECK_ENV(env);
|
|
75
|
+
CHECK_ARG(env, adjusted_value);
|
|
76
|
+
|
|
77
|
+
if (change_in_bytes < 0) {
|
|
78
|
+
return napi_set_last_error(env, napi_invalid_arg, 0, NULL);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
size_t old_size = __builtin_wasm_memory_size(0) << 16;
|
|
82
|
+
size_t new_size = old_size + (size_t) change_in_bytes;
|
|
83
|
+
#ifdef __EMSCRIPTEN__
|
|
84
|
+
if (!emscripten_resize_heap(new_size)) {
|
|
85
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
86
|
+
}
|
|
87
|
+
#else
|
|
88
|
+
new_size = new_size + (PAGESIZE - new_size % PAGESIZE) % PAGESIZE;
|
|
89
|
+
if (-1 == __builtin_wasm_memory_grow(0, (new_size - old_size + 65535) >> 16)) {
|
|
90
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
91
|
+
}
|
|
92
|
+
#endif
|
|
93
|
+
|
|
94
|
+
*adjusted_value = (int64_t) (__builtin_wasm_memory_size(0) << 16);
|
|
95
|
+
|
|
96
|
+
return napi_clear_last_error(env);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
napi_status napi_get_version(napi_env env, uint32_t* result) {
|
|
100
|
+
CHECK_ENV(env);
|
|
101
|
+
CHECK_ARG(env, result);
|
|
102
|
+
*result = NAPI_VERSION;
|
|
103
|
+
return napi_clear_last_error(env);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
EXTERN_C_END
|
package/src/node_api.c
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#include "emnapi_common.h"
|
|
2
|
+
#include "node_api.h"
|
|
3
|
+
|
|
4
|
+
#if EMNAPI_HAVE_THREADS
|
|
5
|
+
#include "uv.h"
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
EXTERN_C_START
|
|
9
|
+
|
|
10
|
+
EMNAPI_INTERNAL_EXTERN void _emnapi_get_node_version(uint32_t* major,
|
|
11
|
+
uint32_t* minor,
|
|
12
|
+
uint32_t* patch);
|
|
13
|
+
|
|
14
|
+
napi_status
|
|
15
|
+
napi_get_node_version(napi_env env,
|
|
16
|
+
const napi_node_version** version) {
|
|
17
|
+
CHECK_ENV(env);
|
|
18
|
+
CHECK_ARG(env, version);
|
|
19
|
+
static napi_node_version node_version = {
|
|
20
|
+
0,
|
|
21
|
+
0,
|
|
22
|
+
0,
|
|
23
|
+
"node"
|
|
24
|
+
};
|
|
25
|
+
_emnapi_get_node_version(&node_version.major,
|
|
26
|
+
&node_version.minor,
|
|
27
|
+
&node_version.patch);
|
|
28
|
+
*version = &node_version;
|
|
29
|
+
return napi_clear_last_error(env);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
napi_status napi_get_uv_event_loop(napi_env env,
|
|
33
|
+
struct uv_loop_s** loop) {
|
|
34
|
+
#if EMNAPI_HAVE_THREADS
|
|
35
|
+
CHECK_ENV(env);
|
|
36
|
+
CHECK_ARG(env, loop);
|
|
37
|
+
// Though this is fake libuv loop
|
|
38
|
+
*loop = uv_default_loop();
|
|
39
|
+
return napi_clear_last_error(env);
|
|
40
|
+
#else
|
|
41
|
+
return napi_set_last_error(env, napi_generic_failure, 0, NULL);
|
|
42
|
+
#endif
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
EMNAPI_INTERNAL_EXTERN int _emnapi_get_filename(char* buf, int len);
|
|
46
|
+
|
|
47
|
+
napi_status node_api_get_module_file_name(napi_env env,
|
|
48
|
+
const char** result) {
|
|
49
|
+
CHECK_ENV(env);
|
|
50
|
+
CHECK_ARG(env, result);
|
|
51
|
+
|
|
52
|
+
static char* filename = NULL;
|
|
53
|
+
static const char* empty_string = "";
|
|
54
|
+
|
|
55
|
+
if (filename != NULL) {
|
|
56
|
+
free(filename);
|
|
57
|
+
filename = NULL;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
int len = _emnapi_get_filename(NULL, 0);
|
|
61
|
+
if (len == 0) {
|
|
62
|
+
*result = empty_string;
|
|
63
|
+
} else {
|
|
64
|
+
filename = (char*) malloc(len + 1);
|
|
65
|
+
len = _emnapi_get_filename(filename, len + 1);
|
|
66
|
+
*(filename + len) = '\0';
|
|
67
|
+
*result = filename;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return napi_clear_last_error(env);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
EXTERN_C_END
|