@node-3d/addon-tools 10.0.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/LICENSE +21 -0
- package/README.md +252 -0
- package/dist/include.d.ts +12 -0
- package/dist/include.js +43 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/utils/action-pack.d.ts +1 -0
- package/dist/utils/action-pack.js +16 -0
- package/dist/utils/check-gypi.d.ts +1 -0
- package/dist/utils/check-gypi.js +10 -0
- package/dist/utils/cpbin.d.ts +1 -0
- package/dist/utils/cpbin.js +18 -0
- package/dist/utils/cpclangformat.d.ts +1 -0
- package/dist/utils/cpclangformat.js +11 -0
- package/dist/utils/cpcpplint.d.ts +1 -0
- package/dist/utils/cpcpplint.js +12 -0
- package/dist/utils/download.d.ts +1 -0
- package/dist/utils/download.js +6 -0
- package/dist/utils/files.d.ts +8 -0
- package/dist/utils/files.js +57 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/install.d.ts +1 -0
- package/dist/utils/install.js +43 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.js +62 -0
- package/dist/utils/oxfmt.d.ts +3 -0
- package/dist/utils/oxfmt.js +29 -0
- package/dist/utils/oxlint.d.ts +141 -0
- package/dist/utils/oxlint.js +215 -0
- package/include/addon-tools.hpp +895 -0
- package/package.json +100 -0
- package/tsconfig.json +27 -0
- package/utils/.clang-format +30 -0
- package/utils/CPPLINT.cfg +18 -0
- package/utils/common.gypi +32 -0
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#define NODE_ADDON_API_DISABLE_DEPRECATED
|
|
4
|
+
#define NAPI_DISABLE_CPP_EXCEPTIONS
|
|
5
|
+
#include <napi.h>
|
|
6
|
+
#include <cstring>
|
|
7
|
+
#include <type_traits>
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
#ifdef _WIN32
|
|
11
|
+
#include <string.h>
|
|
12
|
+
inline const char* strcasestr_crossplatform(
|
|
13
|
+
const char *haystack,
|
|
14
|
+
const char *needle
|
|
15
|
+
) {
|
|
16
|
+
if (!haystack || !needle) {
|
|
17
|
+
return nullptr;
|
|
18
|
+
}
|
|
19
|
+
if (*needle == '\0') {
|
|
20
|
+
return haystack;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
for (const char *h = haystack; *h != '\0'; ++h) {
|
|
24
|
+
const char *hs = h;
|
|
25
|
+
const char *ns = needle;
|
|
26
|
+
while (*hs != '\0' && *ns != '\0' && _strnicmp(hs, ns, 1) == 0) {
|
|
27
|
+
++hs;
|
|
28
|
+
++ns;
|
|
29
|
+
}
|
|
30
|
+
if (*ns == '\0') {
|
|
31
|
+
return h;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return nullptr;
|
|
36
|
+
}
|
|
37
|
+
#else
|
|
38
|
+
#include <strings.h>
|
|
39
|
+
#define strcasestr_crossplatform strcasestr
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
#ifdef _WIN32
|
|
44
|
+
#define DBG_EXPORT __declspec(dllexport)
|
|
45
|
+
#else
|
|
46
|
+
#define DBG_EXPORT
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#define NAPI_ENV Napi::Env env = info.Env();
|
|
50
|
+
#define NAPI_HS Napi::HandleScope scope(env);
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
#define JS_UNDEFINED env.Undefined()
|
|
54
|
+
#define JS_NULL env.Null()
|
|
55
|
+
#define JS_STR(VAL) Napi::String::New(env, VAL)
|
|
56
|
+
#define JS_NUM(VAL) Napi::Number::New(env, static_cast<double>(VAL))
|
|
57
|
+
#define JS_EXT(VAL) Napi::External<void>::New(env, static_cast<void*>(VAL))
|
|
58
|
+
#define JS_BOOL(VAL) Napi::Boolean::New(env, static_cast<bool>(VAL))
|
|
59
|
+
#define JS_OBJECT Napi::Object::New(env)
|
|
60
|
+
#define JS_ARRAY Napi::Array::New(env)
|
|
61
|
+
|
|
62
|
+
#define RET_VALUE(VAL) return VAL;
|
|
63
|
+
#define RET_UNDEFINED RET_VALUE(JS_UNDEFINED)
|
|
64
|
+
#define RET_NULL RET_VALUE(JS_NULL)
|
|
65
|
+
#define RET_STR(VAL) RET_VALUE(JS_STR(VAL))
|
|
66
|
+
#define RET_NUM(VAL) RET_VALUE(JS_NUM(VAL))
|
|
67
|
+
#define RET_EXT(VAL) RET_VALUE(JS_EXT(VAL))
|
|
68
|
+
#define RET_BOOL(VAL) RET_VALUE(JS_BOOL(VAL))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#define JS_THROW(VAL) \
|
|
72
|
+
Napi::Error::New(env, VAL).ThrowAsJavaScriptException();
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
#define REQ_ARGS(N) \
|
|
76
|
+
if (info.Length() < (N)) { \
|
|
77
|
+
JS_THROW("Expected at least " #N " arguments"); \
|
|
78
|
+
RET_UNDEFINED; \
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
#define IS_EMPTY(VAL) (VAL.IsNull() || VAL.IsUndefined())
|
|
83
|
+
#define IS_ARG_EMPTY(I) IS_EMPTY(info[I])
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
#define CHECK_REQ_ARG(I, C, T) \
|
|
87
|
+
if (info.Length() <= (I) || !info[I].C) { \
|
|
88
|
+
JS_THROW("Argument " #I " must be of type `" T "`"); \
|
|
89
|
+
RET_UNDEFINED; \
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#define CHECK_LET_ARG(I, C, T) \
|
|
93
|
+
if (!(IS_ARG_EMPTY(I) || info[I].C)) { \
|
|
94
|
+
JS_THROW( \
|
|
95
|
+
"Argument " #I \
|
|
96
|
+
" must be of type `" T \
|
|
97
|
+
"` or be `null`/`undefined`" \
|
|
98
|
+
); \
|
|
99
|
+
RET_UNDEFINED; \
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
#define REQ_STR_ARG(I, VAR) \
|
|
104
|
+
CHECK_REQ_ARG(I, IsString(), "String"); \
|
|
105
|
+
std::string VAR = info[I].As<Napi::String>().Utf8Value();
|
|
106
|
+
|
|
107
|
+
#define USE_STR_ARG(I, VAR, DEF) \
|
|
108
|
+
CHECK_LET_ARG(I, IsString(), "String"); \
|
|
109
|
+
std::string VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::String>().Utf8Value();
|
|
110
|
+
|
|
111
|
+
#define WEAK_STR_ARG(I, VAR) \
|
|
112
|
+
std::string VAR = info[I].ToString().Utf8Value();
|
|
113
|
+
|
|
114
|
+
#define LET_STR_ARG(I, VAR) USE_STR_ARG(I, VAR, "")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
#define REQ_INT32_ARG(I, VAR) \
|
|
118
|
+
CHECK_REQ_ARG(I, IsNumber(), "Int32"); \
|
|
119
|
+
int32_t VAR = info[I].As<Napi::Number>().Int32Value();
|
|
120
|
+
|
|
121
|
+
#define USE_INT32_ARG(I, VAR, DEF) \
|
|
122
|
+
CHECK_LET_ARG(I, IsNumber(), "Int32"); \
|
|
123
|
+
int32_t VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Number>().Int32Value();
|
|
124
|
+
|
|
125
|
+
#define WEAK_INT32_ARG(I, VAR) \
|
|
126
|
+
int32_t VAR = info[I].ToNumber().Int32Value();
|
|
127
|
+
|
|
128
|
+
#define LET_INT32_ARG(I, VAR) USE_INT32_ARG(I, VAR, 0)
|
|
129
|
+
|
|
130
|
+
#define REQ_INT_ARG(I, VAR) REQ_INT32_ARG(I, VAR)
|
|
131
|
+
#define USE_INT_ARG(I, VAR, DEF) USE_INT32_ARG(I, VAR, DEF)
|
|
132
|
+
#define WEAK_INT_ARG(I, VAR) WEAK_INT32_ARG(I, VAR)
|
|
133
|
+
#define LET_INT_ARG(I, VAR) LET_INT32_ARG(I, VAR)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
#define REQ_UINT32_ARG(I, VAR) \
|
|
137
|
+
CHECK_REQ_ARG(I, IsNumber(), "Uint32"); \
|
|
138
|
+
uint32_t VAR = info[I].As<Napi::Number>().Uint32Value();
|
|
139
|
+
|
|
140
|
+
#define USE_UINT32_ARG(I, VAR, DEF) \
|
|
141
|
+
CHECK_LET_ARG(I, IsNumber(), "Uint32"); \
|
|
142
|
+
uint32_t VAR = IS_ARG_EMPTY(I) \
|
|
143
|
+
? (DEF) \
|
|
144
|
+
: info[I].As<Napi::Number>().Uint32Value();
|
|
145
|
+
|
|
146
|
+
#define WEAK_UINT32_ARG(I, VAR) \
|
|
147
|
+
uint32_t VAR = info[I].ToNumber().Uint32Value();
|
|
148
|
+
|
|
149
|
+
#define LET_UINT32_ARG(I, VAR) USE_UINT32_ARG(I, VAR, 0)
|
|
150
|
+
|
|
151
|
+
#define REQ_UINT_ARG(I, VAR) REQ_UINT32_ARG(I, VAR)
|
|
152
|
+
#define USE_UINT_ARG(I, VAR, DEF) USE_UINT32_ARG(I, VAR, DEF)
|
|
153
|
+
#define WEAK_UINT_ARG(I, VAR) WEAK_UINT32_ARG(I, VAR)
|
|
154
|
+
#define LET_UINT_ARG(I, VAR) LET_UINT32_ARG(I, VAR)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
#define REQ_INT64_ARG(I, VAR) \
|
|
158
|
+
CHECK_REQ_ARG(I, IsNumber(), "Int64"); \
|
|
159
|
+
int64_t VAR = info[I].As<Napi::Number>().Int64Value();
|
|
160
|
+
|
|
161
|
+
#define USE_INT64_ARG(I, VAR, DEF) \
|
|
162
|
+
CHECK_LET_ARG(I, IsNumber(), "Int64"); \
|
|
163
|
+
int64_t VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Number>().Int64Value();
|
|
164
|
+
|
|
165
|
+
#define WEAK_INT64_ARG(I, VAR) \
|
|
166
|
+
int64_t VAR = info[I].ToNumber().Int64Value();
|
|
167
|
+
|
|
168
|
+
#define LET_INT64_ARG(I, VAR) USE_INT64_ARG(I, VAR, 0)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
#define REQ_UINT64_ARG(I, VAR) \
|
|
172
|
+
CHECK_REQ_ARG(I, IsNumber(), "Uint64"); \
|
|
173
|
+
uint64_t VAR = static_cast<uint64_t>(info[I].As<Napi::Number>().Int64Value());
|
|
174
|
+
|
|
175
|
+
#define USE_UINT64_ARG(I, VAR, DEF) \
|
|
176
|
+
CHECK_LET_ARG(I, IsNumber(), "Uint64"); \
|
|
177
|
+
uint64_t VAR = IS_ARG_EMPTY(I) \
|
|
178
|
+
? (DEF) \
|
|
179
|
+
: static_cast<uint64_t>(info[I].As<Napi::Number>().Int64Value());
|
|
180
|
+
|
|
181
|
+
#define WEAK_UINT64_ARG(I, VAR) \
|
|
182
|
+
uint64_t VAR = static_cast<uint64_t>(info[I].ToNumber().Int64Value());
|
|
183
|
+
|
|
184
|
+
#define LET_UINT64_ARG(I, VAR) USE_UINT64_ARG(I, VAR, 0)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
#define REQ_BOOL_ARG(I, VAR) \
|
|
188
|
+
CHECK_REQ_ARG(I, IsBoolean(), "Bool"); \
|
|
189
|
+
bool VAR = info[I].As<Napi::Boolean>().Value();
|
|
190
|
+
|
|
191
|
+
#define USE_BOOL_ARG(I, VAR, DEF) \
|
|
192
|
+
CHECK_LET_ARG(I, IsBoolean(), "Bool"); \
|
|
193
|
+
bool VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Boolean>().Value();
|
|
194
|
+
|
|
195
|
+
#define WEAK_BOOL_ARG(I, VAR) \
|
|
196
|
+
bool VAR = info[I].ToBoolean().Value();
|
|
197
|
+
|
|
198
|
+
#define LET_BOOL_ARG(I, VAR) USE_BOOL_ARG(I, VAR, false)
|
|
199
|
+
|
|
200
|
+
#define SOFT_BOOL_ARG(I, VAR) \
|
|
201
|
+
bool VAR = (info.Length() > (I) && info[I].ToBoolean().Value()) || false;
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
#define REQ_OFFS_ARG(I, VAR) \
|
|
205
|
+
CHECK_REQ_ARG(I, IsNumber(), "Number"); \
|
|
206
|
+
size_t VAR = static_cast<size_t>(info[I].As<Napi::Number>().Int64Value());
|
|
207
|
+
|
|
208
|
+
#define USE_OFFS_ARG(I, VAR, DEF) \
|
|
209
|
+
CHECK_LET_ARG(I, IsNumber(), "Number"); \
|
|
210
|
+
size_t VAR = IS_ARG_EMPTY(I) \
|
|
211
|
+
? (DEF) \
|
|
212
|
+
: static_cast<size_t>(info[I].As<Napi::Number>().Int64Value());
|
|
213
|
+
|
|
214
|
+
#define WEAK_OFFS_ARG(I, VAR) \
|
|
215
|
+
size_t VAR = static_cast<size_t>(info[I].ToNumber().Int64Value());
|
|
216
|
+
|
|
217
|
+
#define LET_OFFS_ARG(I, VAR) USE_OFFS_ARG(I, VAR, 0)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
#define REQ_DOUBLE_ARG(I, VAR) \
|
|
221
|
+
CHECK_REQ_ARG(I, IsNumber(), "Number"); \
|
|
222
|
+
double VAR = info[I].As<Napi::Number>().DoubleValue();
|
|
223
|
+
|
|
224
|
+
#define USE_DOUBLE_ARG(I, VAR, DEF) \
|
|
225
|
+
CHECK_LET_ARG(I, IsNumber(), "Number"); \
|
|
226
|
+
double VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Number>().DoubleValue();
|
|
227
|
+
|
|
228
|
+
#define WEAK_DOUBLE_ARG(I, VAR) \
|
|
229
|
+
double VAR = info[I].ToNumber().DoubleValue();
|
|
230
|
+
|
|
231
|
+
#define LET_DOUBLE_ARG(I, VAR) USE_DOUBLE_ARG(I, VAR, 0.0)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
#define REQ_FLOAT_ARG(I, VAR) \
|
|
235
|
+
CHECK_REQ_ARG(I, IsNumber(), "Number"); \
|
|
236
|
+
float VAR = info[I].As<Napi::Number>().FloatValue();
|
|
237
|
+
|
|
238
|
+
#define USE_FLOAT_ARG(I, VAR, DEF) \
|
|
239
|
+
CHECK_LET_ARG(I, IsNumber(), "Number"); \
|
|
240
|
+
float VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Number>().FloatValue();
|
|
241
|
+
|
|
242
|
+
#define WEAK_FLOAT_ARG(I, VAR) \
|
|
243
|
+
float VAR = info[I].ToNumber().FloatValue();
|
|
244
|
+
|
|
245
|
+
#define LET_FLOAT_ARG(I, VAR) USE_FLOAT_ARG(I, VAR, 0.f)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
#define REQ_EXT_ARG(I, VAR) \
|
|
249
|
+
CHECK_REQ_ARG(I, IsExternal(), "Pointer"); \
|
|
250
|
+
void *VAR = info[I].As< Napi::External<void> >().Data();
|
|
251
|
+
|
|
252
|
+
#define USE_EXT_ARG(I, VAR, DEF) \
|
|
253
|
+
CHECK_LET_ARG(I, IsExternal(), "Pointer"); \
|
|
254
|
+
void *VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As< Napi::External<void> >().Data();
|
|
255
|
+
|
|
256
|
+
#define LET_EXT_ARG(I, VAR) USE_EXT_ARG(I, VAR, nullptr)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
#define REQ_FUN_ARG(I, VAR) \
|
|
260
|
+
CHECK_REQ_ARG(I, IsFunction(), "Function"); \
|
|
261
|
+
Napi::Function VAR = info[I].As<Napi::Function>();
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
#define REQ_OBJ_ARG(I, VAR) \
|
|
265
|
+
CHECK_REQ_ARG(I, IsObject(), "Object"); \
|
|
266
|
+
Napi::Object VAR = info[I].As<Napi::Object>();
|
|
267
|
+
|
|
268
|
+
#define USE_OBJ_ARG(I, VAR, DEF) \
|
|
269
|
+
CHECK_LET_ARG(I, IsObject(), "Object"); \
|
|
270
|
+
Napi::Object VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Object>();
|
|
271
|
+
|
|
272
|
+
#define LET_OBJ_ARG(I, VAR) USE_OBJ_ARG(I, VAR, JS_OBJECT)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
#define REQ_ARRV_ARG(I, VAR) \
|
|
276
|
+
CHECK_REQ_ARG(I, IsArrayBuffer(), "ArrayBuffer"); \
|
|
277
|
+
Napi::ArrayBuffer VAR = info[I].As<Napi::ArrayBuffer>();
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
#define REQ_BUF_ARG(I, VAR) \
|
|
281
|
+
CHECK_REQ_ARG(I, IsBuffer(), "Buffer"); \
|
|
282
|
+
Napi::Buffer<uint8_t> VAR = info[I].As< Napi::Buffer<uint8_t> >();
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
#define REQ_ARRAY_ARG(I, VAR) \
|
|
286
|
+
CHECK_REQ_ARG(I, IsArray(), "Array"); \
|
|
287
|
+
Napi::Array VAR = info[I].As<Napi::Array>();
|
|
288
|
+
|
|
289
|
+
#define USE_ARRAY_ARG(I, VAR, DEF) \
|
|
290
|
+
CHECK_LET_ARG(I, IsArray(), "Array"); \
|
|
291
|
+
Napi::Array VAR = IS_ARG_EMPTY(I) ? (DEF) : info[I].As<Napi::Array>();
|
|
292
|
+
|
|
293
|
+
#define LET_ARRAY_ARG(I, VAR) USE_ARRAY_ARG(I, VAR, JS_ARRAY)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
inline std::vector<std::string> arrayStrToVec(const Napi::Array &arr) {
|
|
297
|
+
uint32_t count = arr.Length();
|
|
298
|
+
std::vector<std::string> result(count);
|
|
299
|
+
for (uint32_t i = 0; i < count; i++) {
|
|
300
|
+
Napi::Value item = arr[i];
|
|
301
|
+
if (item.IsString()) {
|
|
302
|
+
result[i] = item.As<Napi::String>().Utf8Value();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
inline Napi::Array stringsToArray(Napi::Env env, const char **strings, size_t count) {
|
|
310
|
+
Napi::Array arr = JS_ARRAY;
|
|
311
|
+
for (size_t i = 0; i < count; i++) {
|
|
312
|
+
arr.Set(i, strings[i]);
|
|
313
|
+
}
|
|
314
|
+
return arr;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
inline Napi::Array vecStrToArray(Napi::Env env, const std::vector<std::string> &strings) {
|
|
319
|
+
Napi::Array arr = JS_ARRAY;
|
|
320
|
+
size_t count = strings.size();
|
|
321
|
+
for (size_t i = 0; i < count; i++) {
|
|
322
|
+
arr.Set(i, strings[i]);
|
|
323
|
+
}
|
|
324
|
+
return arr;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
#define LET_ARRAY_STR_ARG(I, VAR) \
|
|
329
|
+
USE_ARRAY_ARG(I, __ARRAY_ ## VAR, JS_ARRAY); \
|
|
330
|
+
std::vector<std::string> VAR = arrayStrToVec(__ARRAY_ ## VAR);
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
#define RET_ARRAY_STR(VAL) RET_VALUE(vecStrToArray(env, VAL))
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
#define REQ_TYPED_ARRAY_ARG(I, VAR) \
|
|
337
|
+
CHECK_REQ_ARG(I, IsTypedArray(), "TypedArray"); \
|
|
338
|
+
Napi::TypedArray VAR = info[I].As<Napi::TypedArray>();
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
#define DES_CHECK \
|
|
342
|
+
if (_isDestroyed) return;
|
|
343
|
+
|
|
344
|
+
#define THIS_CHECK \
|
|
345
|
+
NAPI_ENV; \
|
|
346
|
+
if (_isDestroyed) RET_UNDEFINED;
|
|
347
|
+
|
|
348
|
+
#define CACHE_CAS(CACHE, V) \
|
|
349
|
+
if (CACHE == V) { \
|
|
350
|
+
RET_UNDEFINED; \
|
|
351
|
+
} \
|
|
352
|
+
CACHE = V;
|
|
353
|
+
|
|
354
|
+
#define SETTER_CHECK(C, T) \
|
|
355
|
+
if (!value.C) { \
|
|
356
|
+
JS_THROW("Value must be " T); \
|
|
357
|
+
RET_UNDEFINED; \
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
#define JS_METHOD(NAME) Napi::Value NAME(const Napi::CallbackInfo &info)
|
|
362
|
+
|
|
363
|
+
#define ACCESSOR_RW(CLASS, NAME) \
|
|
364
|
+
InstanceAccessor(#NAME, &CLASS::NAME ## Getter, &CLASS::NAME ## Setter)
|
|
365
|
+
|
|
366
|
+
#define ACCESSOR_R(CLASS, NAME) \
|
|
367
|
+
InstanceAccessor(#NAME, &CLASS::NAME ## Getter, nullptr)
|
|
368
|
+
|
|
369
|
+
#define ACCESSOR_M(CLASS, NAME) \
|
|
370
|
+
InstanceMethod(#NAME, &CLASS::NAME)
|
|
371
|
+
|
|
372
|
+
#define THIS_OBJ(VAR) \
|
|
373
|
+
Napi::Object VAR = info.This().As<Napi::Object>();
|
|
374
|
+
|
|
375
|
+
#define SETTER_STR_ARG \
|
|
376
|
+
SETTER_CHECK(IsString(), "String"); \
|
|
377
|
+
std::string v = value.As<Napi::String>().Utf8Value();
|
|
378
|
+
|
|
379
|
+
#define SETTER_INT32_ARG \
|
|
380
|
+
SETTER_CHECK(IsNumber(), "Int32"); \
|
|
381
|
+
int32_t v = value.As<Napi::Number>().Int32Value();
|
|
382
|
+
|
|
383
|
+
#define SETTER_INT_ARG SETTER_INT32_ARG
|
|
384
|
+
|
|
385
|
+
#define SETTER_BOOL_ARG \
|
|
386
|
+
SETTER_CHECK(IsBoolean(), "Bool"); \
|
|
387
|
+
bool v = value.As<Napi::Boolean>().Value();
|
|
388
|
+
|
|
389
|
+
#define SETTER_UINT32_ARG \
|
|
390
|
+
SETTER_CHECK(IsNumber(), "Uint32"); \
|
|
391
|
+
uint32_t v = value.As<Napi::Number>().Uint32Value();
|
|
392
|
+
|
|
393
|
+
#define SETTER_UINT_ARG SETTER_UINT32_ARG
|
|
394
|
+
|
|
395
|
+
#define SETTER_INT64_ARG \
|
|
396
|
+
SETTER_CHECK(IsNumber(), "Int64"); \
|
|
397
|
+
int64_t v = value.As<Napi::Number>().Int64Value();
|
|
398
|
+
|
|
399
|
+
#define SETTER_UINT64_ARG \
|
|
400
|
+
SETTER_CHECK(IsNumber(), "Uint64"); \
|
|
401
|
+
uint64_t v = static_cast<uint64_t>(value.As<Napi::Number>().Int64Value());
|
|
402
|
+
|
|
403
|
+
#define SETTER_OFFS_ARG \
|
|
404
|
+
SETTER_CHECK(IsNumber(), "Number"); \
|
|
405
|
+
size_t v = static_cast<size_t>(value.As<Napi::Number>().Int64Value());
|
|
406
|
+
|
|
407
|
+
#define SETTER_DOUBLE_ARG \
|
|
408
|
+
SETTER_CHECK(IsNumber(), "Number"); \
|
|
409
|
+
double v = value.As<Napi::Number>().DoubleValue();
|
|
410
|
+
|
|
411
|
+
#define SETTER_FLOAT_ARG \
|
|
412
|
+
SETTER_CHECK(IsNumber(), "Number"); \
|
|
413
|
+
float v = value.As<Napi::Number>().FloatValue();
|
|
414
|
+
|
|
415
|
+
#define SETTER_EXT_ARG \
|
|
416
|
+
SETTER_CHECK(IsExternal(), "Pointer"); \
|
|
417
|
+
void *v = value.As< Napi::External<void> >().Data();
|
|
418
|
+
|
|
419
|
+
#define SETTER_FUN_ARG \
|
|
420
|
+
SETTER_CHECK(IsFunction(), "Function"); \
|
|
421
|
+
Napi::Function v = value.As<Napi::Function>()
|
|
422
|
+
|
|
423
|
+
#define SETTER_OBJ_ARG \
|
|
424
|
+
SETTER_CHECK(IsObject(), "Object"); \
|
|
425
|
+
Napi::Object v = value.As<Napi::Object>()
|
|
426
|
+
|
|
427
|
+
#define SETTER_ARRV_ARG \
|
|
428
|
+
SETTER_CHECK(IsArrayBuffer(), "TypedArray"); \
|
|
429
|
+
Napi::ArrayBuffer v = value.As<Napi::ArrayBuffer>();
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
#define GET_AND_THROW_LAST_ERROR() \
|
|
433
|
+
do { \
|
|
434
|
+
const napi_extended_error_info *error_info; \
|
|
435
|
+
napi_get_last_error_info((env), &error_info); \
|
|
436
|
+
bool is_pending; \
|
|
437
|
+
napi_is_exception_pending((env), &is_pending); \
|
|
438
|
+
/* If an exception is already pending, don't rethrow it */ \
|
|
439
|
+
if (!is_pending) { \
|
|
440
|
+
const char* error_message = error_info->error_message != NULL \
|
|
441
|
+
? error_info->error_message \
|
|
442
|
+
: "empty error message"; \
|
|
443
|
+
JS_THROW(error_message); \
|
|
444
|
+
} \
|
|
445
|
+
} while (0)
|
|
446
|
+
|
|
447
|
+
#define NAPI_CALL(the_call) \
|
|
448
|
+
do { \
|
|
449
|
+
if ((the_call) != napi_ok) { \
|
|
450
|
+
GET_AND_THROW_LAST_ERROR(); \
|
|
451
|
+
RET_UNDEFINED; \
|
|
452
|
+
} \
|
|
453
|
+
} while (0)
|
|
454
|
+
|
|
455
|
+
#define JS_RUN(code, VAR) \
|
|
456
|
+
napi_value __RESULT_ ## VAR; \
|
|
457
|
+
NAPI_CALL( \
|
|
458
|
+
napi_run_script(env, napi_value(JS_STR(code)), &__RESULT_ ## VAR) \
|
|
459
|
+
); \
|
|
460
|
+
Napi::Value VAR(env, __RESULT_ ## VAR);
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
template<typename Type = const uint8_t>
|
|
464
|
+
inline Type* getArrayData(
|
|
465
|
+
Napi::Env env,
|
|
466
|
+
Napi::Object obj,
|
|
467
|
+
int32_t *num = nullptr
|
|
468
|
+
) {
|
|
469
|
+
using ValueType = std::remove_cv_t<Type>;
|
|
470
|
+
using ByteType = std::conditional_t<std::is_const_v<Type>, const uint8_t, uint8_t>;
|
|
471
|
+
|
|
472
|
+
Type *out = nullptr;
|
|
473
|
+
if (num) {
|
|
474
|
+
*num = 0;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (obj.IsTypedArray()) {
|
|
478
|
+
Napi::TypedArray ta = obj.As<Napi::TypedArray>();
|
|
479
|
+
size_t offset = ta.ByteOffset();
|
|
480
|
+
size_t byteLength = ta.ByteLength();
|
|
481
|
+
Napi::ArrayBuffer arr = ta.ArrayBuffer();
|
|
482
|
+
if (byteLength > 0 && byteLength < sizeof(ValueType)) {
|
|
483
|
+
JS_THROW("Array data does not contain a complete item of the requested type.");
|
|
484
|
+
return nullptr;
|
|
485
|
+
}
|
|
486
|
+
if ((byteLength % sizeof(ValueType)) != 0) {
|
|
487
|
+
JS_THROW("Array byte length must be a multiple of the requested type size.");
|
|
488
|
+
return nullptr;
|
|
489
|
+
}
|
|
490
|
+
ByteType *base = reinterpret_cast<ByteType *>(arr.Data());
|
|
491
|
+
ByteType *raw = base == nullptr ? nullptr : base + offset;
|
|
492
|
+
if (
|
|
493
|
+
raw != nullptr &&
|
|
494
|
+
(reinterpret_cast<uintptr_t>(raw) % alignof(ValueType)) != 0
|
|
495
|
+
) {
|
|
496
|
+
JS_THROW("Array data is not properly aligned for the requested type.");
|
|
497
|
+
return nullptr;
|
|
498
|
+
}
|
|
499
|
+
if (num) {
|
|
500
|
+
*num = static_cast<int32_t>(byteLength / sizeof(ValueType));
|
|
501
|
+
}
|
|
502
|
+
out = reinterpret_cast<Type *>(raw);
|
|
503
|
+
} else if (obj.IsArrayBuffer()) {
|
|
504
|
+
Napi::ArrayBuffer arr = obj.As<Napi::ArrayBuffer>();
|
|
505
|
+
size_t byteLength = arr.ByteLength();
|
|
506
|
+
if (byteLength > 0 && byteLength < sizeof(ValueType)) {
|
|
507
|
+
JS_THROW("Array data does not contain a complete item of the requested type.");
|
|
508
|
+
return nullptr;
|
|
509
|
+
}
|
|
510
|
+
if ((byteLength % sizeof(ValueType)) != 0) {
|
|
511
|
+
JS_THROW("Array byte length must be a multiple of the requested type size.");
|
|
512
|
+
return nullptr;
|
|
513
|
+
}
|
|
514
|
+
ByteType *raw = reinterpret_cast<ByteType *>(arr.Data());
|
|
515
|
+
if (
|
|
516
|
+
raw != nullptr &&
|
|
517
|
+
(reinterpret_cast<uintptr_t>(raw) % alignof(ValueType)) != 0
|
|
518
|
+
) {
|
|
519
|
+
JS_THROW("Array data is not properly aligned for the requested type.");
|
|
520
|
+
return nullptr;
|
|
521
|
+
}
|
|
522
|
+
if (num) {
|
|
523
|
+
*num = static_cast<int32_t>(byteLength / sizeof(ValueType));
|
|
524
|
+
}
|
|
525
|
+
out = reinterpret_cast<Type *>(raw);
|
|
526
|
+
} else {
|
|
527
|
+
JS_THROW("Argument must be of type `TypedArray`.");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return out;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
template<typename Type = const uint8_t>
|
|
535
|
+
inline Type* getBufferData(
|
|
536
|
+
Napi::Env env,
|
|
537
|
+
Napi::Object obj,
|
|
538
|
+
int32_t *num = nullptr
|
|
539
|
+
) {
|
|
540
|
+
using ValueType = std::remove_cv_t<Type>;
|
|
541
|
+
using ByteType = std::conditional_t<std::is_const_v<Type>, const uint8_t, uint8_t>;
|
|
542
|
+
|
|
543
|
+
if (num) {
|
|
544
|
+
*num = 0;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!obj.IsBuffer()) {
|
|
548
|
+
JS_THROW("Argument must be of type `Buffer`.");
|
|
549
|
+
return nullptr;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
Napi::Buffer<uint8_t> arr = obj.As< Napi::Buffer<uint8_t> >();
|
|
553
|
+
size_t byteLength = arr.Length();
|
|
554
|
+
if (byteLength > 0 && byteLength < sizeof(ValueType)) {
|
|
555
|
+
JS_THROW("Buffer does not contain a complete item of the requested type.");
|
|
556
|
+
return nullptr;
|
|
557
|
+
}
|
|
558
|
+
if ((byteLength % sizeof(ValueType)) != 0) {
|
|
559
|
+
JS_THROW("Buffer byte length must be a multiple of the requested type size.");
|
|
560
|
+
return nullptr;
|
|
561
|
+
}
|
|
562
|
+
ByteType *raw = reinterpret_cast<ByteType *>(arr.Data());
|
|
563
|
+
if (
|
|
564
|
+
raw != nullptr &&
|
|
565
|
+
(reinterpret_cast<uintptr_t>(raw) % alignof(ValueType)) != 0
|
|
566
|
+
) {
|
|
567
|
+
JS_THROW("Buffer data is not properly aligned for the requested type.");
|
|
568
|
+
return nullptr;
|
|
569
|
+
}
|
|
570
|
+
if (num) {
|
|
571
|
+
*num = static_cast<int32_t>(byteLength / sizeof(ValueType));
|
|
572
|
+
}
|
|
573
|
+
return reinterpret_cast<Type*>(raw);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
template<typename Type = const uint8_t>
|
|
578
|
+
inline Type *getData(
|
|
579
|
+
Napi::Env env,
|
|
580
|
+
Napi::Object obj,
|
|
581
|
+
int32_t *num = nullptr
|
|
582
|
+
) {
|
|
583
|
+
Type *out = nullptr;
|
|
584
|
+
if (num) {
|
|
585
|
+
*num = 0;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (obj.IsTypedArray() || obj.IsArrayBuffer()) {
|
|
589
|
+
out = getArrayData<Type>(env, obj, num);
|
|
590
|
+
} else if (obj.IsBuffer()) {
|
|
591
|
+
out = getBufferData<Type>(env, obj, num);
|
|
592
|
+
} else {
|
|
593
|
+
bool hasData = false;
|
|
594
|
+
napi_status hasStatus = napi_has_named_property(
|
|
595
|
+
env, obj, "data", &hasData
|
|
596
|
+
);
|
|
597
|
+
if (hasStatus != napi_ok) {
|
|
598
|
+
if (env.IsExceptionPending()) {
|
|
599
|
+
env.GetAndClearPendingException();
|
|
600
|
+
}
|
|
601
|
+
return nullptr;
|
|
602
|
+
}
|
|
603
|
+
if (!hasData) {
|
|
604
|
+
return nullptr;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
napi_value rawData;
|
|
608
|
+
napi_status getStatus = napi_get_named_property(
|
|
609
|
+
env, obj, "data", &rawData
|
|
610
|
+
);
|
|
611
|
+
if (getStatus != napi_ok) {
|
|
612
|
+
if (env.IsExceptionPending()) {
|
|
613
|
+
env.GetAndClearPendingException();
|
|
614
|
+
}
|
|
615
|
+
return nullptr;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
Napi::Value dataValue(env, rawData);
|
|
619
|
+
if (
|
|
620
|
+
dataValue.IsTypedArray() ||
|
|
621
|
+
dataValue.IsArrayBuffer() ||
|
|
622
|
+
dataValue.IsBuffer()
|
|
623
|
+
) {
|
|
624
|
+
Napi::Object data = dataValue.As<Napi::Object>();
|
|
625
|
+
if (data.IsTypedArray() || data.IsArrayBuffer()) {
|
|
626
|
+
out = getArrayData<Type>(env, data, num);
|
|
627
|
+
} else if (data.IsBuffer()) {
|
|
628
|
+
out = getBufferData<Type>(env, data, num);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return out;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
inline Napi::Value consoleLog(
|
|
638
|
+
Napi::Env env,
|
|
639
|
+
int32_t argc,
|
|
640
|
+
const Napi::Value *argv
|
|
641
|
+
) {
|
|
642
|
+
JS_RUN("console.log", log);
|
|
643
|
+
std::vector<napi_value> args;
|
|
644
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
645
|
+
args.push_back(napi_value(argv[i]));
|
|
646
|
+
}
|
|
647
|
+
log.As<Napi::Function>().Call(args);
|
|
648
|
+
RET_UNDEFINED;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
inline Napi::Value consoleLog(Napi::Env env, const std::string &message) {
|
|
653
|
+
Napi::Value arg = JS_STR(message);
|
|
654
|
+
consoleLog(env, 1, &arg);
|
|
655
|
+
RET_UNDEFINED;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
inline Napi::Value globalLog(
|
|
659
|
+
Napi::Env env,
|
|
660
|
+
const std::string &name,
|
|
661
|
+
const std::string &level,
|
|
662
|
+
int32_t argc,
|
|
663
|
+
const Napi::Value *argv
|
|
664
|
+
) {
|
|
665
|
+
JS_RUN("global.AddonTools.log", log);
|
|
666
|
+
std::vector<napi_value> args;
|
|
667
|
+
args.push_back(napi_value(JS_STR(name)));
|
|
668
|
+
args.push_back(napi_value(JS_STR(level)));
|
|
669
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
670
|
+
args.push_back(napi_value(argv[i]));
|
|
671
|
+
}
|
|
672
|
+
log.As<Napi::Function>().Call(args);
|
|
673
|
+
RET_UNDEFINED;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
inline Napi::Value globalLog(
|
|
678
|
+
Napi::Env env,
|
|
679
|
+
const std::string &name,
|
|
680
|
+
const std::string &level,
|
|
681
|
+
const std::string &message
|
|
682
|
+
) {
|
|
683
|
+
Napi::Value arg = JS_STR(message);
|
|
684
|
+
globalLog(env, name, level, 1, &arg);
|
|
685
|
+
RET_UNDEFINED;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
inline void eventEmit(
|
|
690
|
+
Napi::Object that,
|
|
691
|
+
const std::string &name,
|
|
692
|
+
int32_t argc = 0,
|
|
693
|
+
const Napi::Value *argv = nullptr,
|
|
694
|
+
napi_async_context context = nullptr
|
|
695
|
+
) {
|
|
696
|
+
if (!that.Has("emit")) {
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
Napi::Env env = that.Env();
|
|
701
|
+
|
|
702
|
+
Napi::String eventName = JS_STR(name);
|
|
703
|
+
Napi::Function thatEmit = that.Get("emit").As<Napi::Function>();
|
|
704
|
+
|
|
705
|
+
std::vector<napi_value> args;
|
|
706
|
+
args.push_back(napi_value(eventName));
|
|
707
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
708
|
+
args.push_back(napi_value(argv[i]));
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
if (context) {
|
|
712
|
+
thatEmit.MakeCallback(that, args, context);
|
|
713
|
+
} else {
|
|
714
|
+
thatEmit.Call(that, args);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
typedef Napi::Value (*Es5MethodCallback)(const Napi::CallbackInfo& info);
|
|
720
|
+
typedef Napi::Value (*Es5GetterCallback)(const Napi::CallbackInfo& info);
|
|
721
|
+
typedef void (*Es5SetterCallback)(const Napi::CallbackInfo& info);
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
#define DECLARE_ES5_CLASS(CLASS, NAME) \
|
|
725
|
+
public: \
|
|
726
|
+
inline static CLASS *unwrap(Napi::Object thatObj) { \
|
|
727
|
+
CLASS *that = nullptr; \
|
|
728
|
+
napi_status ns = napi_unwrap( \
|
|
729
|
+
thatObj.Env(), \
|
|
730
|
+
thatObj.Get(_nameEs5), \
|
|
731
|
+
reinterpret_cast<void**>(&that) \
|
|
732
|
+
); \
|
|
733
|
+
if (ns != napi_ok) { \
|
|
734
|
+
return nullptr; \
|
|
735
|
+
} \
|
|
736
|
+
return that; \
|
|
737
|
+
} \
|
|
738
|
+
private: \
|
|
739
|
+
inline static CLASS *unwrapChecked( \
|
|
740
|
+
const Napi::CallbackInfo &info \
|
|
741
|
+
) { \
|
|
742
|
+
CLASS *that = unwrap(info.This().As<Napi::Object>()); \
|
|
743
|
+
if (that == nullptr) { \
|
|
744
|
+
Napi::TypeError::New( \
|
|
745
|
+
info.Env(), \
|
|
746
|
+
"Invalid `this` for `" #CLASS "`" \
|
|
747
|
+
).ThrowAsJavaScriptException(); \
|
|
748
|
+
} \
|
|
749
|
+
return that; \
|
|
750
|
+
} \
|
|
751
|
+
static Napi::FunctionReference _ctorEs5; \
|
|
752
|
+
static const char *_nameEs5; \
|
|
753
|
+
static void _finalizeEs5(napi_env e, void *dest, void* hint); \
|
|
754
|
+
static napi_value _createEs5(napi_env e, napi_callback_info i); \
|
|
755
|
+
inline void super( \
|
|
756
|
+
const Napi::CallbackInfo& info, \
|
|
757
|
+
int32_t argc, \
|
|
758
|
+
const Napi::Value *argv \
|
|
759
|
+
) { \
|
|
760
|
+
Napi::Function ctor = _ctorEs5.Value(); \
|
|
761
|
+
if (ctor.Has("super_")) { \
|
|
762
|
+
Napi::Function _super = ctor.Get("super_").As<Napi::Function>(); \
|
|
763
|
+
std::vector<napi_value> args; \
|
|
764
|
+
for (int32_t i = 0; i < argc; i++) { \
|
|
765
|
+
args.push_back(argv[i]); \
|
|
766
|
+
} \
|
|
767
|
+
_super.Call(info.This(), args); \
|
|
768
|
+
} \
|
|
769
|
+
} \
|
|
770
|
+
inline void super( \
|
|
771
|
+
const Napi::CallbackInfo& info, \
|
|
772
|
+
int32_t argc = 0, \
|
|
773
|
+
const napi_value *argv = nullptr \
|
|
774
|
+
) { \
|
|
775
|
+
Napi::Function ctor = _ctorEs5.Value(); \
|
|
776
|
+
if (ctor.Has("super_")) { \
|
|
777
|
+
Napi::Function _super = ctor.Get("super_").As<Napi::Function>(); \
|
|
778
|
+
_super.Call(info.This(), argc, argv); \
|
|
779
|
+
} \
|
|
780
|
+
} \
|
|
781
|
+
inline static Napi::Function wrap(Napi::Env env) { \
|
|
782
|
+
napi_value __initResult; \
|
|
783
|
+
napi_create_function( \
|
|
784
|
+
env, #NAME, 0, _createEs5, nullptr, &__initResult \
|
|
785
|
+
); \
|
|
786
|
+
Napi::Function ctor = Napi::Function(env, __initResult); \
|
|
787
|
+
_ctorEs5 = Napi::Persistent(ctor); \
|
|
788
|
+
_ctorEs5.SuppressDestruct(); \
|
|
789
|
+
return ctor; \
|
|
790
|
+
} \
|
|
791
|
+
inline static void method( \
|
|
792
|
+
const char *name, \
|
|
793
|
+
Es5MethodCallback cb \
|
|
794
|
+
) { \
|
|
795
|
+
Napi::Object proto = ( \
|
|
796
|
+
_ctorEs5.Value().Get("prototype").As<Napi::Object>() \
|
|
797
|
+
); \
|
|
798
|
+
proto.DefineProperty( \
|
|
799
|
+
Napi::PropertyDescriptor::Function( \
|
|
800
|
+
proto.Env(), proto, name, cb \
|
|
801
|
+
) \
|
|
802
|
+
); \
|
|
803
|
+
} \
|
|
804
|
+
inline static void accessorR( \
|
|
805
|
+
const char *name, \
|
|
806
|
+
Es5GetterCallback getter \
|
|
807
|
+
) { \
|
|
808
|
+
Napi::Object proto = ( \
|
|
809
|
+
_ctorEs5.Value().Get("prototype").As<Napi::Object>() \
|
|
810
|
+
); \
|
|
811
|
+
proto.DefineProperty( \
|
|
812
|
+
Napi::PropertyDescriptor::Accessor( \
|
|
813
|
+
proto.Env(), proto, name, getter \
|
|
814
|
+
) \
|
|
815
|
+
); \
|
|
816
|
+
} \
|
|
817
|
+
inline static void accessorRw( \
|
|
818
|
+
const char *name, \
|
|
819
|
+
Es5GetterCallback getter, \
|
|
820
|
+
Es5SetterCallback setter \
|
|
821
|
+
) { \
|
|
822
|
+
Napi::Object proto = ( \
|
|
823
|
+
_ctorEs5.Value().Get("prototype").As<Napi::Object>() \
|
|
824
|
+
); \
|
|
825
|
+
proto.DefineProperty( \
|
|
826
|
+
Napi::PropertyDescriptor::Accessor( \
|
|
827
|
+
proto.Env(), \
|
|
828
|
+
proto, \
|
|
829
|
+
name, \
|
|
830
|
+
getter, \
|
|
831
|
+
setter \
|
|
832
|
+
) \
|
|
833
|
+
); \
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
#define JS_DECLARE_METHOD(CLASS, NAME) \
|
|
838
|
+
inline static JS_METHOD(__st_##NAME) { \
|
|
839
|
+
CLASS *that = CLASS::unwrapChecked(info); \
|
|
840
|
+
if (that == nullptr) { \
|
|
841
|
+
return info.Env().Undefined(); \
|
|
842
|
+
} \
|
|
843
|
+
return that->__i_##NAME(info); \
|
|
844
|
+
}; \
|
|
845
|
+
JS_METHOD(__i_##NAME);
|
|
846
|
+
|
|
847
|
+
#define JS_DECLARE_GETTER(CLASS, NAME) JS_DECLARE_METHOD(CLASS, NAME##Getter)
|
|
848
|
+
|
|
849
|
+
#define JS_DECLARE_SETTER(CLASS, NAME) \
|
|
850
|
+
inline static void __st_##NAME##Setter( \
|
|
851
|
+
const Napi::CallbackInfo &info \
|
|
852
|
+
) { \
|
|
853
|
+
CLASS *that = CLASS::unwrapChecked(info); \
|
|
854
|
+
if (that == nullptr) { \
|
|
855
|
+
return; \
|
|
856
|
+
} \
|
|
857
|
+
that->__i_##NAME##Setter(info, info[0]); \
|
|
858
|
+
} \
|
|
859
|
+
Napi::Value __i_##NAME##Setter( \
|
|
860
|
+
const Napi::CallbackInfo &info, \
|
|
861
|
+
const Napi::Value &value \
|
|
862
|
+
);
|
|
863
|
+
|
|
864
|
+
#define JS_IMPLEMENT_METHOD(CLASS, NAME) \
|
|
865
|
+
JS_METHOD(CLASS::__i_##NAME)
|
|
866
|
+
|
|
867
|
+
#define JS_IMPLEMENT_GETTER(CLASS, NAME) \
|
|
868
|
+
JS_IMPLEMENT_METHOD(CLASS, NAME##Getter)
|
|
869
|
+
|
|
870
|
+
#define JS_IMPLEMENT_SETTER(CLASS, NAME) \
|
|
871
|
+
Napi::Value CLASS::__i_##NAME##Setter( \
|
|
872
|
+
const Napi::CallbackInfo &info, \
|
|
873
|
+
const Napi::Value &value \
|
|
874
|
+
)
|
|
875
|
+
|
|
876
|
+
#define JS_ASSIGN_METHOD(NAME) method(#NAME, __st_##NAME)
|
|
877
|
+
#define JS_ASSIGN_GETTER(NAME) accessorR(#NAME, __st_##NAME##Getter)
|
|
878
|
+
#define JS_ASSIGN_SETTER(NAME) \
|
|
879
|
+
accessorRw(#NAME, __st_##NAME##Getter, __st_##NAME##Setter)
|
|
880
|
+
|
|
881
|
+
#define IMPLEMENT_ES5_CLASS(CLASS) \
|
|
882
|
+
Napi::FunctionReference CLASS::_ctorEs5; \
|
|
883
|
+
const char *CLASS::_nameEs5 = #CLASS; \
|
|
884
|
+
void CLASS::_finalizeEs5(napi_env e, void *dest, void* hint) { \
|
|
885
|
+
CLASS *instance = reinterpret_cast<CLASS*>(dest); \
|
|
886
|
+
delete instance; \
|
|
887
|
+
} \
|
|
888
|
+
napi_value CLASS::_createEs5(napi_env env, napi_callback_info i) { \
|
|
889
|
+
Napi::CallbackInfo info(env, i); \
|
|
890
|
+
CLASS *instance = new CLASS(info); \
|
|
891
|
+
Napi::Object wrapObj = JS_OBJECT; \
|
|
892
|
+
info.This().As<Napi::Object>().Set(_nameEs5, wrapObj); \
|
|
893
|
+
napi_wrap(env, wrapObj, instance, _finalizeEs5, nullptr, nullptr); \
|
|
894
|
+
return info.Env().Undefined(); \
|
|
895
|
+
}
|