1 #define NAPI_EXPERIMENTAL
2 #include <js_native_api.h>
3 #include "../common.h"
4 #include <string.h>
5 #include "test_null.h"
6
7 static int test_value = 3;
8
Get(napi_env env,napi_callback_info info)9 static napi_value Get(napi_env env, napi_callback_info info) {
10 size_t argc = 2;
11 napi_value args[2];
12 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
13
14 NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
15
16 napi_valuetype valuetype0;
17 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
18
19 NAPI_ASSERT(env, valuetype0 == napi_object,
20 "Wrong type of arguments. Expects an object as first argument.");
21
22 napi_valuetype valuetype1;
23 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
24
25 NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
26 "Wrong type of arguments. Expects a string or symbol as second.");
27
28 napi_value object = args[0];
29 napi_value output;
30 NAPI_CALL(env, napi_get_property(env, object, args[1], &output));
31
32 return output;
33 }
34
GetNamed(napi_env env,napi_callback_info info)35 static napi_value GetNamed(napi_env env, napi_callback_info info) {
36 size_t argc = 2;
37 napi_value args[2];
38 char key[256] = "";
39 size_t key_length;
40 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
41
42 NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
43
44 napi_valuetype value_type0;
45 NAPI_CALL(env, napi_typeof(env, args[0], &value_type0));
46
47 NAPI_ASSERT(env, value_type0 == napi_object,
48 "Wrong type of arguments. Expects an object as first argument.");
49
50 napi_valuetype value_type1;
51 NAPI_CALL(env, napi_typeof(env, args[1], &value_type1));
52
53 NAPI_ASSERT(env, value_type1 == napi_string,
54 "Wrong type of arguments. Expects a string as second.");
55
56 napi_value object = args[0];
57 NAPI_CALL(env,
58 napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
59 key[255] = 0;
60 NAPI_ASSERT(env, key_length <= 255,
61 "Cannot accommodate keys longer than 255 bytes");
62 napi_value output;
63 NAPI_CALL(env, napi_get_named_property(env, object, key, &output));
64
65 return output;
66 }
67
GetPropertyNames(napi_env env,napi_callback_info info)68 static napi_value GetPropertyNames(napi_env env, napi_callback_info info) {
69 size_t argc = 1;
70 napi_value args[1];
71 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
72
73 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
74
75 napi_valuetype value_type0;
76 NAPI_CALL(env, napi_typeof(env, args[0], &value_type0));
77
78 NAPI_ASSERT(env, value_type0 == napi_object,
79 "Wrong type of arguments. Expects an object as first argument.");
80
81 napi_value output;
82 NAPI_CALL(env, napi_get_property_names(env, args[0], &output));
83
84 return output;
85 }
86
GetSymbolNames(napi_env env,napi_callback_info info)87 static napi_value GetSymbolNames(napi_env env, napi_callback_info info) {
88 size_t argc = 1;
89 napi_value args[1];
90 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
91
92 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
93
94 napi_valuetype value_type0;
95 NAPI_CALL(env, napi_typeof(env, args[0], &value_type0));
96
97 NAPI_ASSERT(env,
98 value_type0 == napi_object,
99 "Wrong type of arguments. Expects an object as first argument.");
100
101 napi_value output;
102 NAPI_CALL(env,
103 napi_get_all_property_names(
104 env,
105 args[0],
106 napi_key_include_prototypes,
107 napi_key_skip_strings,
108 napi_key_numbers_to_strings,
109 &output));
110
111 return output;
112 }
113
Set(napi_env env,napi_callback_info info)114 static napi_value Set(napi_env env, napi_callback_info info) {
115 size_t argc = 3;
116 napi_value args[3];
117 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
118
119 NAPI_ASSERT(env, argc >= 3, "Wrong number of arguments");
120
121 napi_valuetype valuetype0;
122 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
123
124 NAPI_ASSERT(env, valuetype0 == napi_object,
125 "Wrong type of arguments. Expects an object as first argument.");
126
127 napi_valuetype valuetype1;
128 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
129
130 NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
131 "Wrong type of arguments. Expects a string or symbol as second.");
132
133 NAPI_CALL(env, napi_set_property(env, args[0], args[1], args[2]));
134
135 napi_value valuetrue;
136 NAPI_CALL(env, napi_get_boolean(env, true, &valuetrue));
137
138 return valuetrue;
139 }
140
SetNamed(napi_env env,napi_callback_info info)141 static napi_value SetNamed(napi_env env, napi_callback_info info) {
142 size_t argc = 3;
143 napi_value args[3];
144 char key[256] = "";
145 size_t key_length;
146 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
147
148 NAPI_ASSERT(env, argc >= 3, "Wrong number of arguments");
149
150 napi_valuetype value_type0;
151 NAPI_CALL(env, napi_typeof(env, args[0], &value_type0));
152
153 NAPI_ASSERT(env, value_type0 == napi_object,
154 "Wrong type of arguments. Expects an object as first argument.");
155
156 napi_valuetype value_type1;
157 NAPI_CALL(env, napi_typeof(env, args[1], &value_type1));
158
159 NAPI_ASSERT(env, value_type1 == napi_string,
160 "Wrong type of arguments. Expects a string as second.");
161
162 NAPI_CALL(env,
163 napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
164 key[255] = 0;
165 NAPI_ASSERT(env, key_length <= 255,
166 "Cannot accommodate keys longer than 255 bytes");
167
168 NAPI_CALL(env, napi_set_named_property(env, args[0], key, args[2]));
169
170 napi_value value_true;
171 NAPI_CALL(env, napi_get_boolean(env, true, &value_true));
172
173 return value_true;
174 }
175
Has(napi_env env,napi_callback_info info)176 static napi_value Has(napi_env env, napi_callback_info info) {
177 size_t argc = 2;
178 napi_value args[2];
179 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
180
181 NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
182
183 napi_valuetype valuetype0;
184 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
185
186 NAPI_ASSERT(env, valuetype0 == napi_object,
187 "Wrong type of arguments. Expects an object as first argument.");
188
189 napi_valuetype valuetype1;
190 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
191
192 NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
193 "Wrong type of arguments. Expects a string or symbol as second.");
194
195 bool has_property;
196 NAPI_CALL(env, napi_has_property(env, args[0], args[1], &has_property));
197
198 napi_value ret;
199 NAPI_CALL(env, napi_get_boolean(env, has_property, &ret));
200
201 return ret;
202 }
203
HasNamed(napi_env env,napi_callback_info info)204 static napi_value HasNamed(napi_env env, napi_callback_info info) {
205 size_t argc = 2;
206 napi_value args[2];
207 char key[256] = "";
208 size_t key_length;
209 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
210
211 NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
212
213 napi_valuetype value_type0;
214 NAPI_CALL(env, napi_typeof(env, args[0], &value_type0));
215
216 NAPI_ASSERT(env, value_type0 == napi_object,
217 "Wrong type of arguments. Expects an object as first argument.");
218
219 napi_valuetype value_type1;
220 NAPI_CALL(env, napi_typeof(env, args[1], &value_type1));
221
222 NAPI_ASSERT(env, value_type1 == napi_string || value_type1 == napi_symbol,
223 "Wrong type of arguments. Expects a string as second.");
224
225 NAPI_CALL(env,
226 napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
227 key[255] = 0;
228 NAPI_ASSERT(env, key_length <= 255,
229 "Cannot accommodate keys longer than 255 bytes");
230
231 bool has_property;
232 NAPI_CALL(env, napi_has_named_property(env, args[0], key, &has_property));
233
234 napi_value ret;
235 NAPI_CALL(env, napi_get_boolean(env, has_property, &ret));
236
237 return ret;
238 }
239
HasOwn(napi_env env,napi_callback_info info)240 static napi_value HasOwn(napi_env env, napi_callback_info info) {
241 size_t argc = 2;
242 napi_value args[2];
243 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
244
245 NAPI_ASSERT(env, argc == 2, "Wrong number of arguments");
246
247 napi_valuetype valuetype0;
248 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
249
250 NAPI_ASSERT(env, valuetype0 == napi_object,
251 "Wrong type of arguments. Expects an object as first argument.");
252
253 // napi_valuetype valuetype1;
254 // NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
255 //
256 // NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
257 // "Wrong type of arguments. Expects a string or symbol as second.");
258
259 bool has_property;
260 NAPI_CALL(env, napi_has_own_property(env, args[0], args[1], &has_property));
261
262 napi_value ret;
263 NAPI_CALL(env, napi_get_boolean(env, has_property, &ret));
264
265 return ret;
266 }
267
Delete(napi_env env,napi_callback_info info)268 static napi_value Delete(napi_env env, napi_callback_info info) {
269 size_t argc = 2;
270 napi_value args[2];
271
272 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
273 NAPI_ASSERT(env, argc == 2, "Wrong number of arguments");
274
275 napi_valuetype valuetype0;
276 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
277 NAPI_ASSERT(env, valuetype0 == napi_object,
278 "Wrong type of arguments. Expects an object as first argument.");
279
280 napi_valuetype valuetype1;
281 NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
282 NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
283 "Wrong type of arguments. Expects a string or symbol as second.");
284
285 bool result;
286 napi_value ret;
287 NAPI_CALL(env, napi_delete_property(env, args[0], args[1], &result));
288 NAPI_CALL(env, napi_get_boolean(env, result, &ret));
289
290 return ret;
291 }
292
New(napi_env env,napi_callback_info info)293 static napi_value New(napi_env env, napi_callback_info info) {
294 napi_value ret;
295 NAPI_CALL(env, napi_create_object(env, &ret));
296
297 napi_value num;
298 NAPI_CALL(env, napi_create_int32(env, 987654321, &num));
299
300 NAPI_CALL(env, napi_set_named_property(env, ret, "test_number", num));
301
302 napi_value str;
303 const char* str_val = "test string";
304 size_t str_len = strlen(str_val);
305 NAPI_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str));
306
307 NAPI_CALL(env, napi_set_named_property(env, ret, "test_string", str));
308
309 return ret;
310 }
311
Inflate(napi_env env,napi_callback_info info)312 static napi_value Inflate(napi_env env, napi_callback_info info) {
313 size_t argc = 1;
314 napi_value args[1];
315 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
316
317 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
318
319 napi_valuetype valuetype0;
320 NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
321
322 NAPI_ASSERT(env, valuetype0 == napi_object,
323 "Wrong type of arguments. Expects an object as first argument.");
324
325 napi_value obj = args[0];
326 napi_value propertynames;
327 NAPI_CALL(env, napi_get_property_names(env, obj, &propertynames));
328
329 uint32_t i, length;
330 NAPI_CALL(env, napi_get_array_length(env, propertynames, &length));
331
332 for (i = 0; i < length; i++) {
333 napi_value property_str;
334 NAPI_CALL(env, napi_get_element(env, propertynames, i, &property_str));
335
336 napi_value value;
337 NAPI_CALL(env, napi_get_property(env, obj, property_str, &value));
338
339 double double_val;
340 NAPI_CALL(env, napi_get_value_double(env, value, &double_val));
341 NAPI_CALL(env, napi_create_double(env, double_val + 1, &value));
342 NAPI_CALL(env, napi_set_property(env, obj, property_str, value));
343 }
344
345 return obj;
346 }
347
Wrap(napi_env env,napi_callback_info info)348 static napi_value Wrap(napi_env env, napi_callback_info info) {
349 size_t argc = 1;
350 napi_value arg;
351 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
352
353 NAPI_CALL(env, napi_wrap(env, arg, &test_value, NULL, NULL, NULL));
354 return NULL;
355 }
356
Unwrap(napi_env env,napi_callback_info info)357 static napi_value Unwrap(napi_env env, napi_callback_info info) {
358 size_t argc = 1;
359 napi_value arg;
360 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
361
362 void* data;
363 NAPI_CALL(env, napi_unwrap(env, arg, &data));
364
365 bool is_expected = (data != NULL && *(int*)data == 3);
366 napi_value result;
367 NAPI_CALL(env, napi_get_boolean(env, is_expected, &result));
368 return result;
369 }
370
TestSetProperty(napi_env env,napi_callback_info info)371 static napi_value TestSetProperty(napi_env env,
372 napi_callback_info info) {
373 napi_status status;
374 napi_value object, key, value;
375
376 NAPI_CALL(env, napi_create_object(env, &object));
377
378 NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
379
380 NAPI_CALL(env, napi_create_object(env, &value));
381
382 status = napi_set_property(NULL, object, key, value);
383
384 add_returned_status(env,
385 "envIsNull",
386 object,
387 "Invalid argument",
388 napi_invalid_arg,
389 status);
390
391 napi_set_property(env, NULL, key, value);
392
393 add_last_status(env, "objectIsNull", object);
394
395 napi_set_property(env, object, NULL, value);
396
397 add_last_status(env, "keyIsNull", object);
398
399 napi_set_property(env, object, key, NULL);
400
401 add_last_status(env, "valueIsNull", object);
402
403 return object;
404 }
405
TestHasProperty(napi_env env,napi_callback_info info)406 static napi_value TestHasProperty(napi_env env,
407 napi_callback_info info) {
408 napi_status status;
409 napi_value object, key;
410 bool result;
411
412 NAPI_CALL(env, napi_create_object(env, &object));
413
414 NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
415
416 status = napi_has_property(NULL, object, key, &result);
417
418 add_returned_status(env,
419 "envIsNull",
420 object,
421 "Invalid argument",
422 napi_invalid_arg,
423 status);
424
425 napi_has_property(env, NULL, key, &result);
426
427 add_last_status(env, "objectIsNull", object);
428
429 napi_has_property(env, object, NULL, &result);
430
431 add_last_status(env, "keyIsNull", object);
432
433 napi_has_property(env, object, key, NULL);
434
435 add_last_status(env, "resultIsNull", object);
436
437 return object;
438 }
439
TestGetProperty(napi_env env,napi_callback_info info)440 static napi_value TestGetProperty(napi_env env,
441 napi_callback_info info) {
442 napi_status status;
443 napi_value object, key, result;
444
445 NAPI_CALL(env, napi_create_object(env, &object));
446
447 NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
448
449 NAPI_CALL(env, napi_create_object(env, &result));
450
451 status = napi_get_property(NULL, object, key, &result);
452
453 add_returned_status(env,
454 "envIsNull",
455 object,
456 "Invalid argument",
457 napi_invalid_arg,
458 status);
459
460 napi_get_property(env, NULL, key, &result);
461
462 add_last_status(env, "objectIsNull", object);
463
464 napi_get_property(env, object, NULL, &result);
465
466 add_last_status(env, "keyIsNull", object);
467
468 napi_get_property(env, object, key, NULL);
469
470 add_last_status(env, "resultIsNull", object);
471
472 return object;
473 }
474
TestFreeze(napi_env env,napi_callback_info info)475 static napi_value TestFreeze(napi_env env,
476 napi_callback_info info) {
477 size_t argc = 1;
478 napi_value args[1];
479 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
480
481 napi_value object = args[0];
482 NAPI_CALL(env, napi_object_freeze(env, object));
483
484 return object;
485 }
486
TestSeal(napi_env env,napi_callback_info info)487 static napi_value TestSeal(napi_env env,
488 napi_callback_info info) {
489 size_t argc = 1;
490 napi_value args[1];
491 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
492
493 napi_value object = args[0];
494 NAPI_CALL(env, napi_object_seal(env, object));
495
496 return object;
497 }
498
499 // We create two type tags. They are basically 128-bit UUIDs.
500 static const napi_type_tag type_tags[2] = {
501 { 0xdaf987b3cc62481a, 0xb745b0497f299531 },
502 { 0xbb7936c374084d9b, 0xa9548d0762eeedb9 }
503 };
504
505 static napi_value
TypeTaggedInstance(napi_env env,napi_callback_info info)506 TypeTaggedInstance(napi_env env, napi_callback_info info) {
507 size_t argc = 1;
508 uint32_t type_index;
509 napi_value instance, which_type;
510
511 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL));
512 NAPI_CALL(env, napi_get_value_uint32(env, which_type, &type_index));
513 NAPI_CALL(env, napi_create_object(env, &instance));
514 NAPI_CALL(env, napi_type_tag_object(env, instance, &type_tags[type_index]));
515
516 return instance;
517 }
518
519 static napi_value
CheckTypeTag(napi_env env,napi_callback_info info)520 CheckTypeTag(napi_env env, napi_callback_info info) {
521 size_t argc = 2;
522 bool result;
523 napi_value argv[2], js_result;
524 uint32_t type_index;
525
526 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
527 NAPI_CALL(env, napi_get_value_uint32(env, argv[0], &type_index));
528 NAPI_CALL(env, napi_check_object_type_tag(env,
529 argv[1],
530 &type_tags[type_index],
531 &result));
532 NAPI_CALL(env, napi_get_boolean(env, result, &js_result));
533
534 return js_result;
535 }
536
537 EXTERN_C_START
Init(napi_env env,napi_value exports)538 napi_value Init(napi_env env, napi_value exports) {
539 napi_property_descriptor descriptors[] = {
540 DECLARE_NAPI_PROPERTY("Get", Get),
541 DECLARE_NAPI_PROPERTY("GetNamed", GetNamed),
542 DECLARE_NAPI_PROPERTY("GetPropertyNames", GetPropertyNames),
543 DECLARE_NAPI_PROPERTY("GetSymbolNames", GetSymbolNames),
544 DECLARE_NAPI_PROPERTY("Set", Set),
545 DECLARE_NAPI_PROPERTY("SetNamed", SetNamed),
546 DECLARE_NAPI_PROPERTY("Has", Has),
547 DECLARE_NAPI_PROPERTY("HasNamed", HasNamed),
548 DECLARE_NAPI_PROPERTY("HasOwn", HasOwn),
549 DECLARE_NAPI_PROPERTY("Delete", Delete),
550 DECLARE_NAPI_PROPERTY("New", New),
551 DECLARE_NAPI_PROPERTY("Inflate", Inflate),
552 DECLARE_NAPI_PROPERTY("Wrap", Wrap),
553 DECLARE_NAPI_PROPERTY("Unwrap", Unwrap),
554 DECLARE_NAPI_PROPERTY("TestSetProperty", TestSetProperty),
555 DECLARE_NAPI_PROPERTY("TestHasProperty", TestHasProperty),
556 DECLARE_NAPI_PROPERTY("TypeTaggedInstance", TypeTaggedInstance),
557 DECLARE_NAPI_PROPERTY("CheckTypeTag", CheckTypeTag),
558 DECLARE_NAPI_PROPERTY("TestGetProperty", TestGetProperty),
559 DECLARE_NAPI_PROPERTY("TestFreeze", TestFreeze),
560 DECLARE_NAPI_PROPERTY("TestSeal", TestSeal),
561 };
562
563 init_test_null(env, exports);
564
565 NAPI_CALL(env, napi_define_properties(
566 env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
567
568 return exports;
569 }
570 EXTERN_C_END
571