1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <js_native_api.h>
4 #include "../common.h"
5
6 typedef struct {
7 size_t value;
8 bool print;
9 napi_ref js_cb_ref;
10 } AddonData;
11
Increment(napi_env env,napi_callback_info info)12 static napi_value Increment(napi_env env, napi_callback_info info) {
13 AddonData* data;
14 napi_value result;
15
16 NAPI_CALL(env, napi_get_instance_data(env, (void**)&data));
17 NAPI_CALL(env, napi_create_uint32(env, ++data->value, &result));
18
19 return result;
20 }
21
DeleteAddonData(napi_env env,void * raw_data,void * hint)22 static void DeleteAddonData(napi_env env, void* raw_data, void* hint) {
23 AddonData* data = raw_data;
24 if (data->print) {
25 printf("deleting addon data\n");
26 }
27 if (data->js_cb_ref != NULL) {
28 NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref));
29 }
30 free(data);
31 }
32
SetPrintOnDelete(napi_env env,napi_callback_info info)33 static napi_value SetPrintOnDelete(napi_env env, napi_callback_info info) {
34 AddonData* data;
35
36 NAPI_CALL(env, napi_get_instance_data(env, (void**)&data));
37 data->print = true;
38
39 return NULL;
40 }
41
TestFinalizer(napi_env env,void * raw_data,void * hint)42 static void TestFinalizer(napi_env env, void* raw_data, void* hint) {
43 (void) raw_data;
44 (void) hint;
45
46 AddonData* data;
47 NAPI_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data));
48 napi_value js_cb, undefined;
49 NAPI_CALL_RETURN_VOID(env,
50 napi_get_reference_value(env, data->js_cb_ref, &js_cb));
51 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined));
52 NAPI_CALL_RETURN_VOID(env,
53 napi_call_function(env, undefined, js_cb, 0, NULL, NULL));
54 NAPI_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_cb_ref));
55 data->js_cb_ref = NULL;
56 }
57
ObjectWithFinalizer(napi_env env,napi_callback_info info)58 static napi_value ObjectWithFinalizer(napi_env env, napi_callback_info info) {
59 AddonData* data;
60 napi_value result, js_cb;
61 size_t argc = 1;
62
63 NAPI_CALL(env, napi_get_instance_data(env, (void**)&data));
64 NAPI_ASSERT(env, data->js_cb_ref == NULL, "reference must be NULL");
65 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &js_cb, NULL, NULL));
66 NAPI_CALL(env, napi_create_object(env, &result));
67 NAPI_CALL(env,
68 napi_add_finalizer(env, result, NULL, TestFinalizer, NULL, NULL));
69 NAPI_CALL(env, napi_create_reference(env, js_cb, 1, &data->js_cb_ref));
70
71 return result;
72 }
73
74 EXTERN_C_START
Init(napi_env env,napi_value exports)75 napi_value Init(napi_env env, napi_value exports) {
76 AddonData* data = malloc(sizeof(*data));
77 data->value = 41;
78 data->print = false;
79 data->js_cb_ref = NULL;
80
81 NAPI_CALL(env, napi_set_instance_data(env, data, DeleteAddonData, NULL));
82
83 napi_property_descriptor props[] = {
84 DECLARE_NAPI_PROPERTY("increment", Increment),
85 DECLARE_NAPI_PROPERTY("setPrintOnDelete", SetPrintOnDelete),
86 DECLARE_NAPI_PROPERTY("objectWithFinalizer", ObjectWithFinalizer),
87 };
88
89 NAPI_CALL(env, napi_define_properties(env,
90 exports,
91 sizeof(props) / sizeof(*props),
92 props));
93
94 return exports;
95 }
96 EXTERN_C_END
97