frida 16.7.14 → 16.7.15

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.
Files changed (172) hide show
  1. package/README.md +1 -10
  2. package/build/BSDmakefile +6 -0
  3. package/build/Makefile +10 -0
  4. package/build/src/frida.d.ts +364 -0
  5. package/build/src/frida.js +962 -0
  6. package/build/src/frida_binding.d.ts +938 -0
  7. package/meson.build +34 -67
  8. package/package.json +30 -20
  9. package/scripts/fetch-abi-bits.py +15 -65
  10. package/scripts/install.js +5 -4
  11. package/src/addon.def +3 -0
  12. package/src/addon.symbols +2 -1
  13. package/src/addon.version +4 -0
  14. package/src/frida_bindgen/__init__.py +0 -0
  15. package/src/frida_bindgen/__main__.py +4 -0
  16. package/src/frida_bindgen/__pycache__/__init__.cpython-312.pyc +0 -0
  17. package/src/frida_bindgen/__pycache__/__main__.cpython-312.pyc +0 -0
  18. package/src/frida_bindgen/__pycache__/cli.cpython-312.pyc +0 -0
  19. package/src/frida_bindgen/__pycache__/codegen.cpython-312.pyc +0 -0
  20. package/src/frida_bindgen/__pycache__/customization.cpython-312.pyc +0 -0
  21. package/src/frida_bindgen/__pycache__/loader.cpython-312.pyc +0 -0
  22. package/src/frida_bindgen/__pycache__/model.cpython-312.pyc +0 -0
  23. package/src/frida_bindgen/assets/codegen_helpers.c +1970 -0
  24. package/src/frida_bindgen/assets/codegen_helpers.ts +100 -0
  25. package/src/frida_bindgen/assets/codegen_prototypes.h +78 -0
  26. package/src/frida_bindgen/assets/codegen_types.h +57 -0
  27. package/src/frida_bindgen/assets/customization_facade.exports +13 -0
  28. package/src/frida_bindgen/assets/customization_facade.ts +157 -0
  29. package/src/frida_bindgen/assets/customization_helpers.imports +2 -0
  30. package/src/frida_bindgen/assets/customization_helpers.ts +396 -0
  31. package/src/frida_bindgen/cli.py +96 -0
  32. package/src/frida_bindgen/codegen.py +2233 -0
  33. package/src/frida_bindgen/customization.py +924 -0
  34. package/src/frida_bindgen/loader.py +60 -0
  35. package/src/frida_bindgen/model.py +1357 -0
  36. package/src/meson.build +92 -27
  37. package/{lib/build.py → src/tsc.py} +12 -12
  38. package/src/win_delay_load_hook.c +56 -0
  39. package/subprojects/frida-core.wrap +1 -1
  40. package/test/data/index.ts +2 -2
  41. package/test/device.ts +1 -2
  42. package/test/device_manager.ts +1 -2
  43. package/test/labrat.ts +2 -2
  44. package/test/script.ts +12 -12
  45. package/test/session.ts +3 -3
  46. package/tsconfig.json +6 -11
  47. package/dist/application.d.ts +0 -81
  48. package/dist/application.js +0 -2
  49. package/dist/authentication.d.ts +0 -3
  50. package/dist/authentication.js +0 -2
  51. package/dist/bus.d.ts +0 -16
  52. package/dist/bus.js +0 -23
  53. package/dist/cancellable.d.ts +0 -15
  54. package/dist/cancellable.js +0 -41
  55. package/dist/child.d.ts +0 -16
  56. package/dist/child.js +0 -9
  57. package/dist/crash.d.ts +0 -10
  58. package/dist/crash.js +0 -2
  59. package/dist/device.d.ts +0 -156
  60. package/dist/device.js +0 -188
  61. package/dist/device_manager.d.ts +0 -25
  62. package/dist/device_manager.js +0 -42
  63. package/dist/endpoint_parameters.d.ts +0 -26
  64. package/dist/endpoint_parameters.js +0 -24
  65. package/dist/icon.d.ts +0 -14
  66. package/dist/icon.js +0 -2
  67. package/dist/index.d.ts +0 -161
  68. package/dist/index.js +0 -170
  69. package/dist/iostream.d.ts +0 -13
  70. package/dist/iostream.js +0 -73
  71. package/dist/native.d.ts +0 -1
  72. package/dist/native.js +0 -11
  73. package/dist/portal_membership.d.ts +0 -6
  74. package/dist/portal_membership.js +0 -12
  75. package/dist/portal_service.d.ts +0 -48
  76. package/dist/portal_service.js +0 -52
  77. package/dist/process.d.ts +0 -47
  78. package/dist/process.js +0 -2
  79. package/dist/relay.d.ts +0 -22
  80. package/dist/relay.js +0 -32
  81. package/dist/script.d.ts +0 -70
  82. package/dist/script.js +0 -266
  83. package/dist/service.d.ts +0 -16
  84. package/dist/service.js +0 -26
  85. package/dist/session.d.ts +0 -45
  86. package/dist/session.js +0 -73
  87. package/dist/signals.d.ts +0 -20
  88. package/dist/signals.js +0 -40
  89. package/dist/socket_address.d.ts +0 -25
  90. package/dist/socket_address.js +0 -2
  91. package/dist/spawn.d.ts +0 -4
  92. package/dist/spawn.js +0 -2
  93. package/dist/system_parameters.d.ts +0 -84
  94. package/dist/system_parameters.js +0 -2
  95. package/lib/application.ts +0 -98
  96. package/lib/authentication.ts +0 -3
  97. package/lib/bus.ts +0 -30
  98. package/lib/cancellable.ts +0 -48
  99. package/lib/child.ts +0 -15
  100. package/lib/crash.ts +0 -11
  101. package/lib/device.ts +0 -331
  102. package/lib/device_manager.ts +0 -69
  103. package/lib/endpoint_parameters.ts +0 -56
  104. package/lib/icon.ts +0 -15
  105. package/lib/index.ts +0 -316
  106. package/lib/iostream.ts +0 -78
  107. package/lib/meson.build +0 -53
  108. package/lib/native.ts +0 -9
  109. package/lib/portal_membership.ts +0 -10
  110. package/lib/portal_service.ts +0 -105
  111. package/lib/process.ts +0 -57
  112. package/lib/relay.ts +0 -44
  113. package/lib/script.ts +0 -361
  114. package/lib/service.ts +0 -34
  115. package/lib/session.ts +0 -113
  116. package/lib/signals.ts +0 -45
  117. package/lib/socket_address.ts +0 -35
  118. package/lib/spawn.ts +0 -4
  119. package/lib/system_parameters.ts +0 -103
  120. package/meson.options +0 -11
  121. package/src/addon.cc +0 -78
  122. package/src/application.cc +0 -148
  123. package/src/application.h +0 -31
  124. package/src/authentication.cc +0 -174
  125. package/src/authentication.h +0 -24
  126. package/src/bus.cc +0 -167
  127. package/src/bus.h +0 -33
  128. package/src/cancellable.cc +0 -117
  129. package/src/cancellable.h +0 -31
  130. package/src/child.cc +0 -150
  131. package/src/child.h +0 -32
  132. package/src/crash.cc +0 -122
  133. package/src/crash.h +0 -30
  134. package/src/device.cc +0 -1350
  135. package/src/device.h +0 -56
  136. package/src/device_manager.cc +0 -362
  137. package/src/device_manager.h +0 -35
  138. package/src/endpoint_parameters.cc +0 -171
  139. package/src/endpoint_parameters.h +0 -28
  140. package/src/glib_context.cc +0 -62
  141. package/src/glib_context.h +0 -29
  142. package/src/glib_object.cc +0 -25
  143. package/src/glib_object.h +0 -37
  144. package/src/iostream.cc +0 -243
  145. package/src/iostream.h +0 -30
  146. package/src/operation.h +0 -94
  147. package/src/portal_membership.cc +0 -100
  148. package/src/portal_membership.h +0 -26
  149. package/src/portal_service.cc +0 -401
  150. package/src/portal_service.h +0 -40
  151. package/src/process.cc +0 -135
  152. package/src/process.h +0 -30
  153. package/src/relay.cc +0 -139
  154. package/src/relay.h +0 -31
  155. package/src/runtime.cc +0 -568
  156. package/src/runtime.h +0 -69
  157. package/src/script.cc +0 -301
  158. package/src/script.h +0 -36
  159. package/src/service.cc +0 -224
  160. package/src/service.h +0 -36
  161. package/src/session.cc +0 -860
  162. package/src/session.h +0 -42
  163. package/src/signals.cc +0 -334
  164. package/src/signals.h +0 -47
  165. package/src/spawn.cc +0 -95
  166. package/src/spawn.h +0 -27
  167. package/src/usage_monitor.h +0 -117
  168. package/src/uv_context.cc +0 -118
  169. package/src/uv_context.h +0 -40
  170. package/src/win_delay_load_hook.cc +0 -63
  171. package/subprojects/nan.wrap +0 -9
  172. package/subprojects/packagefiles/nan.patch +0 -13
@@ -0,0 +1,1970 @@
1
+ static gboolean
2
+ fdn_is_null (napi_env env,
3
+ napi_value value)
4
+ {
5
+ napi_valuetype type;
6
+
7
+ napi_typeof (env, value, &type);
8
+
9
+ return type == napi_null;
10
+ }
11
+
12
+ static gboolean
13
+ fdn_is_undefined_or_null (napi_env env,
14
+ napi_value value)
15
+ {
16
+ napi_valuetype type;
17
+
18
+ napi_typeof (env, value, &type);
19
+
20
+ return type == napi_undefined || type == napi_null;
21
+ }
22
+
23
+ static gboolean
24
+ fdn_is_function (napi_env env,
25
+ napi_value value)
26
+ {
27
+ napi_valuetype type;
28
+
29
+ napi_typeof (env, value, &type);
30
+
31
+ return type == napi_function;
32
+ }
33
+
34
+ static gboolean
35
+ fdn_boolean_from_value (napi_env env,
36
+ napi_value value,
37
+ gboolean * b)
38
+ {
39
+ bool napi_b;
40
+
41
+ if (napi_get_value_bool (env, value, &napi_b) != napi_ok)
42
+ goto invalid_argument;
43
+
44
+ *b = napi_b;
45
+ return TRUE;
46
+
47
+ invalid_argument:
48
+ {
49
+ napi_throw_error (env, NULL, "expected a boolean");
50
+ return FALSE;
51
+ }
52
+ }
53
+
54
+ static napi_value
55
+ fdn_boolean_to_value (napi_env env,
56
+ gboolean b)
57
+ {
58
+ napi_value result;
59
+ napi_get_boolean (env, b, &result);
60
+ return result;
61
+ }
62
+
63
+ static gboolean
64
+ fdn_size_from_value (napi_env env,
65
+ napi_value value,
66
+ gsize * s)
67
+ {
68
+ double d;
69
+
70
+ if (napi_get_value_double (env, value, &d) != napi_ok)
71
+ goto invalid_argument;
72
+
73
+ if (d < 0 || d > G_MAXSIZE)
74
+ goto invalid_argument;
75
+
76
+ *s = d;
77
+ return TRUE;
78
+
79
+ invalid_argument:
80
+ {
81
+ napi_throw_error (env, NULL, "expected an unsigned integer");
82
+ return FALSE;
83
+ }
84
+ }
85
+
86
+ static napi_value
87
+ fdn_size_to_value (napi_env env,
88
+ gsize s)
89
+ {
90
+ return fdn_ssize_to_value (env, s);
91
+ }
92
+
93
+ static napi_value
94
+ fdn_ssize_to_value (napi_env env,
95
+ gssize s)
96
+ {
97
+ napi_value result;
98
+ napi_create_int64 (env, s, &result);
99
+ return result;
100
+ }
101
+
102
+ static gboolean
103
+ fdn_int_from_value (napi_env env,
104
+ napi_value value,
105
+ gint * i)
106
+ {
107
+ int32_t napi_i;
108
+
109
+ if (napi_get_value_int32 (env, value, &napi_i) != napi_ok)
110
+ goto invalid_argument;
111
+
112
+ *i = napi_i;
113
+ return TRUE;
114
+
115
+ invalid_argument:
116
+ {
117
+ napi_throw_error (env, NULL, "expected an integer");
118
+ return FALSE;
119
+ }
120
+ }
121
+
122
+ static napi_value
123
+ fdn_int_to_value (napi_env env,
124
+ gint i)
125
+ {
126
+ napi_value result;
127
+ napi_create_int32 (env, i, &result);
128
+ return result;
129
+ }
130
+
131
+ static gboolean
132
+ fdn_uint_from_value (napi_env env,
133
+ napi_value value,
134
+ guint * u)
135
+ {
136
+ uint32_t napi_u;
137
+
138
+ if (napi_get_value_uint32 (env, value, &napi_u) != napi_ok)
139
+ goto invalid_argument;
140
+
141
+ *u = napi_u;
142
+ return TRUE;
143
+
144
+ invalid_argument:
145
+ {
146
+ napi_throw_error (env, NULL, "expected an unsigned integer");
147
+ return FALSE;
148
+ }
149
+ }
150
+
151
+ static napi_value
152
+ fdn_uint_to_value (napi_env env,
153
+ guint u)
154
+ {
155
+ napi_value result;
156
+ napi_create_uint32 (env, u, &result);
157
+ return result;
158
+ }
159
+
160
+ static gboolean
161
+ fdn_uint16_from_value (napi_env env,
162
+ napi_value value,
163
+ guint16 * u)
164
+ {
165
+ uint32_t napi_u;
166
+
167
+ if (napi_get_value_uint32 (env, value, &napi_u) != napi_ok)
168
+ goto invalid_argument;
169
+
170
+ if (napi_u > G_MAXUINT16)
171
+ goto invalid_argument;
172
+
173
+ *u = napi_u;
174
+ return TRUE;
175
+
176
+ invalid_argument:
177
+ {
178
+ napi_throw_error (env, NULL, "expected an unsigned 16-bit integer");
179
+ return FALSE;
180
+ }
181
+ }
182
+
183
+ static napi_value
184
+ fdn_uint16_to_value (napi_env env,
185
+ guint16 u)
186
+ {
187
+ return fdn_uint32_to_value (env, u);
188
+ }
189
+
190
+ static napi_value
191
+ fdn_uint32_to_value (napi_env env,
192
+ guint32 u)
193
+ {
194
+ napi_value result;
195
+ napi_create_uint32 (env, u, &result);
196
+ return result;
197
+ }
198
+
199
+ static gboolean
200
+ fdn_int64_from_value (napi_env env,
201
+ napi_value value,
202
+ gint64 * i)
203
+ {
204
+ int64_t napi_i;
205
+
206
+ if (napi_get_value_int64 (env, value, &napi_i) != napi_ok)
207
+ goto invalid_argument;
208
+
209
+ *i = napi_i;
210
+ return TRUE;
211
+
212
+ invalid_argument:
213
+ {
214
+ napi_throw_error (env, NULL, "expected an integer");
215
+ return FALSE;
216
+ }
217
+ }
218
+
219
+ static napi_value
220
+ fdn_int64_to_value (napi_env env,
221
+ gint64 i)
222
+ {
223
+ napi_value result;
224
+ napi_create_int64 (env, i, &result);
225
+ return result;
226
+ }
227
+
228
+ static napi_value
229
+ fdn_uint64_to_value (napi_env env,
230
+ guint64 u)
231
+ {
232
+ napi_value result;
233
+ napi_create_double (env, u, &result);
234
+ return result;
235
+ }
236
+
237
+ static gboolean
238
+ fdn_ulong_from_value (napi_env env,
239
+ napi_value value,
240
+ gulong * u)
241
+ {
242
+ double d;
243
+
244
+ if (napi_get_value_double (env, value, &d) != napi_ok)
245
+ goto invalid_argument;
246
+
247
+ if (d < 0 || d > G_MAXULONG)
248
+ goto invalid_argument;
249
+
250
+ *u = d;
251
+ return TRUE;
252
+
253
+ invalid_argument:
254
+ {
255
+ napi_throw_error (env, NULL, "expected an unsigned integer");
256
+ return FALSE;
257
+ }
258
+ }
259
+
260
+ static gboolean
261
+ fdn_double_from_value (napi_env env,
262
+ napi_value value,
263
+ gdouble * d)
264
+ {
265
+ if (napi_get_value_double (env, value, d) != napi_ok)
266
+ goto invalid_argument;
267
+
268
+ return TRUE;
269
+
270
+ invalid_argument:
271
+ {
272
+ napi_throw_error (env, NULL, "expected a number");
273
+ return FALSE;
274
+ }
275
+ }
276
+
277
+ static napi_value
278
+ fdn_double_to_value (napi_env env,
279
+ gdouble d)
280
+ {
281
+ napi_value result;
282
+ napi_create_double (env, d, &result);
283
+ return result;
284
+ }
285
+
286
+ static gboolean
287
+ fdn_enum_from_value (napi_env env,
288
+ GType enum_type,
289
+ napi_value value,
290
+ gint * e)
291
+ {
292
+ gboolean success = FALSE;
293
+ gchar * nick;
294
+ GEnumClass * enum_class;
295
+ guint i;
296
+
297
+ if (!fdn_utf8_from_value (env, value, &nick))
298
+ return FALSE;
299
+
300
+ enum_class = G_ENUM_CLASS (g_type_class_ref (enum_type));
301
+
302
+ for (i = 0; i != enum_class->n_values; i++)
303
+ {
304
+ GEnumValue * enum_value = &enum_class->values[i];
305
+ if (strcmp (enum_value->value_nick, nick) == 0)
306
+ {
307
+ *e = enum_value->value;
308
+ success = TRUE;
309
+ break;
310
+ }
311
+ }
312
+
313
+ g_type_class_unref (enum_class);
314
+
315
+ g_free (nick);
316
+
317
+ if (!success)
318
+ napi_throw_error (env, NULL, "invalid enumeration value");
319
+
320
+ return success;
321
+ }
322
+
323
+ static napi_value
324
+ fdn_enum_to_value (napi_env env,
325
+ GType enum_type,
326
+ gint e)
327
+ {
328
+ napi_value result;
329
+ GEnumClass * enum_class;
330
+ GEnumValue * enum_value;
331
+
332
+ enum_class = G_ENUM_CLASS (g_type_class_ref (enum_type));
333
+
334
+ enum_value = g_enum_get_value (enum_class, e);
335
+ g_assert (enum_value != NULL);
336
+
337
+ result = fdn_utf8_to_value (env, enum_value->value_nick);
338
+
339
+ g_type_class_unref (enum_class);
340
+
341
+ return result;
342
+ }
343
+
344
+ static gboolean
345
+ fdn_utf8_from_value (napi_env env,
346
+ napi_value value,
347
+ gchar ** str)
348
+ {
349
+ gchar * result = NULL;
350
+ size_t length;
351
+
352
+ if (napi_get_value_string_utf8 (env, value, NULL, 0, &length) != napi_ok)
353
+ goto invalid_argument;
354
+
355
+ result = g_malloc (length + 1);
356
+ if (napi_get_value_string_utf8 (env, value, result, length + 1, &length) != napi_ok)
357
+ goto invalid_argument;
358
+
359
+ *str = result;
360
+ return TRUE;
361
+
362
+ invalid_argument:
363
+ {
364
+ napi_throw_error (env, NULL, "expected a string");
365
+ g_free (result);
366
+ return FALSE;
367
+ }
368
+ }
369
+
370
+ static napi_value
371
+ fdn_utf8_to_value (napi_env env,
372
+ const gchar * str)
373
+ {
374
+ napi_value result;
375
+ napi_create_string_utf8 (env, str, NAPI_AUTO_LENGTH, &result);
376
+ return result;
377
+ }
378
+
379
+ static gboolean
380
+ fdn_strv_from_value (napi_env env,
381
+ napi_value value,
382
+ gchar *** strv)
383
+ {
384
+ uint32_t length, i;
385
+ gchar ** vector = NULL;
386
+
387
+ if (napi_get_array_length (env, value, &length) != napi_ok)
388
+ goto invalid_argument;
389
+
390
+ vector = g_new0 (gchar *, length + 1);
391
+
392
+ for (i = 0; i != length; i++)
393
+ {
394
+ napi_value js_str;
395
+
396
+ if (napi_get_element (env, value, i, &js_str) != napi_ok)
397
+ goto invalid_argument;
398
+
399
+ if (!fdn_utf8_from_value (env, js_str, &vector[i]))
400
+ goto invalid_argument;
401
+ }
402
+
403
+ *strv = vector;
404
+ return TRUE;
405
+
406
+ invalid_argument:
407
+ {
408
+ napi_throw_error (env, NULL, "expected an array of strings");
409
+ g_strfreev (vector);
410
+ return FALSE;
411
+ }
412
+ }
413
+
414
+ static napi_value
415
+ fdn_strv_to_value (napi_env env,
416
+ gchar ** strv)
417
+ {
418
+ napi_value result;
419
+ uint32_t length, i;
420
+
421
+ length = g_strv_length (strv);
422
+
423
+ napi_create_array_with_length (env, length, &result);
424
+
425
+ for (i = 0; i != length; i++)
426
+ napi_set_element (env, result, i, fdn_utf8_to_value (env, strv[i]));
427
+
428
+ return result;
429
+ }
430
+
431
+ static napi_value
432
+ fdn_buffer_to_value (napi_env env,
433
+ const guint8 * data,
434
+ gsize size)
435
+ {
436
+ napi_value result;
437
+ napi_create_buffer_copy (env, size, data, NULL, &result);
438
+ return result;
439
+ }
440
+
441
+ static gboolean
442
+ fdn_bytes_from_value (napi_env env,
443
+ napi_value value,
444
+ GBytes ** bytes)
445
+ {
446
+ void * data;
447
+ size_t size;
448
+
449
+ if (napi_get_buffer_info (env, value, &data, &size) != napi_ok)
450
+ goto invalid_argument;
451
+
452
+ *bytes = g_bytes_new (data, size);
453
+ return TRUE;
454
+
455
+ invalid_argument:
456
+ {
457
+ napi_throw_error (env, NULL, "expected a buffer");
458
+ return FALSE;
459
+ }
460
+ }
461
+
462
+ static napi_value
463
+ fdn_bytes_to_value (napi_env env,
464
+ GBytes * bytes)
465
+ {
466
+ const guint8 * data;
467
+ gsize size;
468
+
469
+ data = g_bytes_get_data (bytes, &size);
470
+
471
+ return fdn_buffer_to_value (env, data, size);
472
+ }
473
+
474
+ static gboolean
475
+ fdn_vardict_from_value (napi_env env,
476
+ napi_value value,
477
+ GHashTable ** vardict)
478
+ {
479
+ napi_value keys;
480
+ uint32_t length, i;
481
+ GHashTable * dict = NULL;
482
+ gchar * key = NULL;
483
+
484
+ if (napi_get_property_names (env, value, &keys) != napi_ok)
485
+ goto invalid_argument;
486
+ if (napi_get_array_length (env, keys, &length) != napi_ok)
487
+ goto propagate_error;
488
+
489
+ dict = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
490
+
491
+ for (i = 0; i != length; i++)
492
+ {
493
+ napi_value js_key, js_val;
494
+ GVariant * val;
495
+
496
+ if (napi_get_element (env, keys, i, &js_key) != napi_ok)
497
+ goto propagate_error;
498
+ if (!fdn_utf8_from_value (env, js_key, &key))
499
+ goto invalid_argument;
500
+
501
+ if (napi_get_property (env, value, js_key, &js_val) != napi_ok)
502
+ goto propagate_error;
503
+ if (!fdn_variant_from_value (env, js_val, &val))
504
+ goto propagate_error;
505
+
506
+ g_hash_table_insert (dict, g_steal_pointer (&key), g_variant_ref_sink (val));
507
+ }
508
+
509
+ *vardict = dict;
510
+ return TRUE;
511
+
512
+ invalid_argument:
513
+ {
514
+ napi_throw_error (env, NULL, "expected a vardict");
515
+ goto propagate_error;
516
+ }
517
+ propagate_error:
518
+ {
519
+ g_free (key);
520
+ g_clear_pointer (&dict, g_hash_table_unref);
521
+ return FALSE;
522
+ }
523
+ }
524
+
525
+ static napi_value
526
+ fdn_vardict_to_value (napi_env env,
527
+ GHashTable * vardict)
528
+ {
529
+ napi_value result;
530
+ GHashTableIter iter;
531
+ gpointer key, value;
532
+
533
+ napi_create_object (env, &result);
534
+
535
+ g_hash_table_iter_init (&iter, vardict);
536
+ while (g_hash_table_iter_next (&iter, &key, &value))
537
+ {
538
+ napi_value js_key, js_value;
539
+
540
+ js_key = fdn_utf8_to_value (env, key);
541
+ js_value = fdn_variant_to_value (env, value);
542
+
543
+ napi_set_property (env, result, js_key, js_value);
544
+ }
545
+
546
+ return result;
547
+ }
548
+
549
+ static gboolean
550
+ fdn_variant_from_value (napi_env env,
551
+ napi_value value,
552
+ GVariant ** variant)
553
+ {
554
+ napi_valuetype type;
555
+
556
+ napi_typeof (env, value, &type);
557
+
558
+ switch (type)
559
+ {
560
+ case napi_boolean:
561
+ {
562
+ gboolean b;
563
+
564
+ if (!fdn_boolean_from_value (env, value, &b))
565
+ return FALSE;
566
+
567
+ *variant = g_variant_new_boolean (b);
568
+ return TRUE;
569
+ }
570
+ case napi_number:
571
+ {
572
+ gint64 i;
573
+
574
+ if (!fdn_int64_from_value (env, value, &i))
575
+ return FALSE;
576
+
577
+ *variant = g_variant_new_int64 (i);
578
+ return TRUE;
579
+ }
580
+ case napi_string:
581
+ {
582
+ gchar * str;
583
+
584
+ if (!fdn_utf8_from_value (env, value, &str))
585
+ return FALSE;
586
+
587
+ *variant = g_variant_new_take_string (str);
588
+ return TRUE;
589
+ }
590
+ case napi_object:
591
+ {
592
+ bool is_buffer, is_array;
593
+ GVariantBuilder builder;
594
+ napi_value keys;
595
+ uint32_t length, i;
596
+
597
+ if (napi_is_buffer (env, value, &is_buffer) != napi_ok)
598
+ return FALSE;
599
+ if (is_buffer)
600
+ {
601
+ void * data;
602
+ size_t size;
603
+ gpointer copy;
604
+
605
+ if (napi_get_buffer_info (env, value, &data, &size) != napi_ok)
606
+ return FALSE;
607
+
608
+ copy = g_memdup2 (data, size);
609
+ *variant = g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, copy, size, TRUE, g_free, copy);
610
+ return TRUE;
611
+ }
612
+
613
+ if (napi_is_array (env, value, &is_array) != napi_ok)
614
+ return FALSE;
615
+ if (is_array)
616
+ {
617
+ uint32_t length;
618
+
619
+ if (napi_get_array_length (env, value, &length) != napi_ok)
620
+ return FALSE;
621
+
622
+ if (length == 2)
623
+ {
624
+ napi_value first;
625
+ napi_valuetype first_type;
626
+
627
+ if (napi_get_element (env, value, 0, &first) != napi_ok)
628
+ return FALSE;
629
+
630
+ napi_typeof (env, first, &first_type);
631
+
632
+ if (first_type == napi_symbol)
633
+ {
634
+ napi_value second;
635
+ GVariant * val;
636
+ napi_value desc;
637
+ gchar * type;
638
+ GVariant * t[2];
639
+
640
+ if (napi_get_element (env, value, 1, &second) != napi_ok)
641
+ return FALSE;
642
+
643
+ if (!fdn_variant_from_value (env, second, &val))
644
+ return FALSE;
645
+
646
+ napi_coerce_to_string (env, first, &desc);
647
+ fdn_utf8_from_value (env, desc, &type);
648
+
649
+ t[0] = g_variant_new_take_string (type);
650
+ t[1] = val;
651
+
652
+ *variant = g_variant_new_tuple (t, G_N_ELEMENTS (t));
653
+ return TRUE;
654
+ }
655
+ }
656
+
657
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
658
+
659
+ for (i = 0; i != length; i++)
660
+ {
661
+ napi_value element;
662
+ GVariant * v;
663
+
664
+ if (napi_get_element (env, value, i, &element) != napi_ok)
665
+ {
666
+ g_variant_builder_clear (&builder);
667
+ return FALSE;
668
+ }
669
+
670
+ if (!fdn_variant_from_value (env, element, &v))
671
+ {
672
+ g_variant_builder_clear (&builder);
673
+ return FALSE;
674
+ }
675
+
676
+ g_variant_builder_add (&builder, "v", v);
677
+ }
678
+
679
+ *variant = g_variant_builder_end (&builder);
680
+ return TRUE;
681
+ }
682
+
683
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
684
+
685
+ if (napi_get_property_names (env, value, &keys) != napi_ok)
686
+ return FALSE;
687
+
688
+ if (napi_get_array_length (env, keys, &length) != napi_ok)
689
+ return FALSE;
690
+
691
+ for (i = 0; i != length; i++)
692
+ {
693
+ napi_value key;
694
+ gchar * key_str;
695
+ napi_value val;
696
+ GVariant * v;
697
+
698
+ if (napi_get_element (env, keys, i, &key) != napi_ok)
699
+ return FALSE;
700
+
701
+ if (!fdn_utf8_from_value (env, key, &key_str))
702
+ return FALSE;
703
+
704
+ if (napi_get_property (env, value, key, &val) != napi_ok)
705
+ {
706
+ g_free (key_str);
707
+ return FALSE;
708
+ }
709
+
710
+ if (!fdn_variant_from_value (env, val, &v))
711
+ {
712
+ g_free (key_str);
713
+ return FALSE;
714
+ }
715
+
716
+ g_variant_builder_add (&builder, "{sv}", key_str, v);
717
+ g_free (key_str);
718
+ }
719
+
720
+ *variant = g_variant_builder_end (&builder);
721
+ return TRUE;
722
+ }
723
+ default:
724
+ break;
725
+ }
726
+
727
+ napi_throw_type_error (env, NULL, "expected value serializable to GVariant");
728
+ return FALSE;
729
+ }
730
+
731
+ static napi_value
732
+ fdn_variant_to_value (napi_env env,
733
+ GVariant * variant)
734
+ {
735
+ napi_value result;
736
+
737
+ switch (g_variant_classify (variant))
738
+ {
739
+ case G_VARIANT_CLASS_STRING:
740
+ {
741
+ const gchar * str = g_variant_get_string (variant, NULL);
742
+ return fdn_utf8_to_value (env, str);
743
+ }
744
+ case G_VARIANT_CLASS_INT64:
745
+ return fdn_int64_to_value (env, g_variant_get_int64 (variant));
746
+ case G_VARIANT_CLASS_UINT64:
747
+ return fdn_uint64_to_value (env, g_variant_get_uint64 (variant));
748
+ case G_VARIANT_CLASS_DOUBLE:
749
+ return fdn_double_to_value (env, g_variant_get_double (variant));
750
+ case G_VARIANT_CLASS_BOOLEAN:
751
+ return fdn_boolean_to_value (env, g_variant_get_boolean (variant));
752
+ case G_VARIANT_CLASS_ARRAY:
753
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE ("ay")))
754
+ {
755
+ gsize size;
756
+ g_variant_get_fixed_array (variant, &size, sizeof (guint8));
757
+ return fdn_buffer_to_value (env, g_variant_get_data (variant), size);
758
+ }
759
+
760
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_VARDICT))
761
+ {
762
+ napi_value dict;
763
+ GVariantIter iter;
764
+ gchar * key;
765
+ GVariant * value;
766
+
767
+ napi_create_object (env, &dict);
768
+
769
+ g_variant_iter_init (&iter, variant);
770
+ while (g_variant_iter_next (&iter, "{sv}", &key, &value))
771
+ {
772
+ napi_value js_key, js_value;
773
+
774
+ js_key = fdn_utf8_to_value (env, key);
775
+ js_value = fdn_variant_to_value (env, value);
776
+
777
+ napi_set_property (env, dict, js_key, js_value);
778
+
779
+ g_variant_unref (value);
780
+ g_free (key);
781
+ }
782
+
783
+ return dict;
784
+ }
785
+
786
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY))
787
+ {
788
+ napi_value array;
789
+ GVariantIter iter;
790
+ uint32_t i;
791
+ GVariant * child;
792
+
793
+ napi_create_array (env, &array);
794
+
795
+ g_variant_iter_init (&iter, variant);
796
+ i = 0;
797
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
798
+ {
799
+ napi_value element = fdn_variant_to_value (env, child);
800
+ napi_set_element (env, array, i++, element);
801
+ g_variant_unref (child);
802
+ }
803
+
804
+ return array;
805
+ }
806
+
807
+ break;
808
+ case G_VARIANT_CLASS_TUPLE:
809
+ napi_get_undefined (env, &result);
810
+ return result;
811
+ default:
812
+ break;
813
+ }
814
+
815
+ napi_get_null (env, &result);
816
+ return result;
817
+ }
818
+
819
+ static gboolean
820
+ fdn_gvalue_from_value (napi_env env,
821
+ GType type,
822
+ napi_value js_value,
823
+ GValue * value)
824
+ {
825
+ g_value_init (value, type);
826
+
827
+ switch (type)
828
+ {
829
+ case G_TYPE_BOOLEAN:
830
+ {
831
+ gboolean b;
832
+
833
+ if (!fdn_boolean_from_value (env, js_value, &b))
834
+ return FALSE;
835
+ g_value_set_boolean (value, b);
836
+
837
+ break;
838
+ }
839
+ case G_TYPE_INT:
840
+ {
841
+ gint i;
842
+
843
+ if (!fdn_int_from_value (env, js_value, &i))
844
+ return FALSE;
845
+ g_value_set_int (value, i);
846
+
847
+ break;
848
+ }
849
+ case G_TYPE_UINT:
850
+ {
851
+ guint u;
852
+
853
+ if (!fdn_uint_from_value (env, js_value, &u))
854
+ return FALSE;
855
+ g_value_set_uint (value, u);
856
+
857
+ break;
858
+ }
859
+ case G_TYPE_FLOAT:
860
+ {
861
+ gdouble d;
862
+
863
+ if (!fdn_double_from_value (env, js_value, &d))
864
+ return FALSE;
865
+ g_value_set_float (value, d);
866
+
867
+ break;
868
+ }
869
+ case G_TYPE_DOUBLE:
870
+ {
871
+ gdouble d;
872
+
873
+ if (!fdn_double_from_value (env, js_value, &d))
874
+ return FALSE;
875
+ g_value_set_double (value, d);
876
+
877
+ break;
878
+ }
879
+ case G_TYPE_STRING:
880
+ {
881
+ gchar * str;
882
+
883
+ if (!fdn_utf8_from_value (env, js_value, &str))
884
+ return FALSE;
885
+ g_value_take_string (value, str);
886
+
887
+ break;
888
+ }
889
+ default:
890
+ {
891
+ gchar * msg;
892
+
893
+ if (G_TYPE_IS_ENUM (type))
894
+ {
895
+ gint e;
896
+
897
+ if (!fdn_enum_from_value (env, type, js_value, &e))
898
+ return FALSE;
899
+ g_value_set_enum (value, e);
900
+
901
+ return TRUE;
902
+ }
903
+
904
+ if (type == G_TYPE_STRV)
905
+ {
906
+ gchar ** strv;
907
+
908
+ if (!fdn_strv_from_value (env, js_value, &strv))
909
+ return FALSE;
910
+ g_value_take_boxed (value, strv);
911
+
912
+ return TRUE;
913
+ }
914
+
915
+ if (type == G_TYPE_BYTES)
916
+ {
917
+ GBytes * bytes;
918
+
919
+ if (!fdn_bytes_from_value (env, js_value, &bytes))
920
+ return FALSE;
921
+ g_value_take_boxed (value, bytes);
922
+
923
+ return TRUE;
924
+ }
925
+
926
+ if (type == G_TYPE_HASH_TABLE)
927
+ {
928
+ GHashTable * vardict;
929
+
930
+ if (!fdn_vardict_from_value (env, js_value, &vardict))
931
+ return FALSE;
932
+ g_value_take_boxed (value, vardict);
933
+
934
+ return TRUE;
935
+ }
936
+
937
+ if (type == G_TYPE_TLS_CERTIFICATE)
938
+ {
939
+ GTlsCertificate * certificate;
940
+
941
+ if (!fdn_tls_certificate_from_value (env, js_value, &certificate))
942
+ return FALSE;
943
+ g_value_take_object (value, certificate);
944
+
945
+ return TRUE;
946
+ }
947
+
948
+ msg = g_strdup_printf ("unsupported property type: %s", g_type_name (type));
949
+ napi_throw_type_error (env, NULL, msg);
950
+ g_free (msg);
951
+
952
+ return FALSE;
953
+ }
954
+ }
955
+
956
+ return TRUE;
957
+ }
958
+
959
+ static napi_value
960
+ fdn_gvalue_to_value (napi_env env,
961
+ GValue * value)
962
+ {
963
+ GType gtype;
964
+
965
+ gtype = G_VALUE_TYPE (value);
966
+
967
+ switch (gtype)
968
+ {
969
+ case G_TYPE_BOOLEAN:
970
+ return fdn_boolean_to_value (env, g_value_get_boolean (value));
971
+ case G_TYPE_INT:
972
+ return fdn_int_to_value (env, g_value_get_int (value));
973
+ case G_TYPE_UINT:
974
+ return fdn_uint_to_value (env, g_value_get_uint (value));
975
+ case G_TYPE_FLOAT:
976
+ return fdn_double_to_value (env, g_value_get_float (value));
977
+ case G_TYPE_DOUBLE:
978
+ return fdn_double_to_value (env, g_value_get_double (value));
979
+ case G_TYPE_STRING:
980
+ {
981
+ const gchar * str;
982
+
983
+ str = g_value_get_string (value);
984
+ if (str == NULL)
985
+ {
986
+ napi_value result;
987
+ napi_get_null (env, &result);
988
+ return result;
989
+ }
990
+
991
+ return fdn_utf8_to_value (env, str);
992
+ }
993
+ default:
994
+ {
995
+ napi_value result;
996
+
997
+ if (G_TYPE_IS_ENUM (gtype))
998
+ return fdn_enum_to_value (env, gtype, g_value_get_enum (value));
999
+
1000
+ if (gtype == G_TYPE_BYTES)
1001
+ {
1002
+ GBytes * bytes = g_value_get_boxed (value);
1003
+ if (bytes != NULL)
1004
+ {
1005
+ return fdn_bytes_to_value (env, bytes);
1006
+ }
1007
+ else
1008
+ {
1009
+ napi_get_null (env, &result);
1010
+ return result;
1011
+ }
1012
+ }
1013
+
1014
+ if (G_TYPE_IS_OBJECT (gtype))
1015
+ result = fdn_object_subclass_to_value (env, g_value_get_object (value));
1016
+ else
1017
+ napi_get_null (env, &result);
1018
+
1019
+ return result;
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ static gboolean
1025
+ fdn_error_from_value (napi_env env,
1026
+ napi_value value,
1027
+ GError ** error)
1028
+ {
1029
+ napi_value js_message;
1030
+ gchar * raw_message;
1031
+ GString * message;
1032
+
1033
+ if (napi_get_named_property (env, value, "message", &js_message) != napi_ok)
1034
+ return FALSE;
1035
+
1036
+ if (!fdn_utf8_from_value (env, js_message, &raw_message))
1037
+ return FALSE;
1038
+
1039
+ message = g_string_new ("");
1040
+ g_string_append_unichar (message, g_unichar_toupper (g_utf8_get_char (raw_message)));
1041
+ g_string_append (message, g_utf8_offset_to_pointer (raw_message, 1));
1042
+
1043
+ *error = g_error_new_literal (FRIDA_ERROR, FRIDA_ERROR_INVALID_ARGUMENT, message->str);
1044
+
1045
+ g_free (raw_message);
1046
+ g_string_free (message, TRUE);
1047
+
1048
+ return TRUE;
1049
+ }
1050
+
1051
+ static napi_value
1052
+ fdn_error_to_value (napi_env env,
1053
+ GError * error)
1054
+ {
1055
+ napi_value result;
1056
+ napi_create_error (env, NULL, fdn_utf8_to_value (env, error->message), &result);
1057
+ return result;
1058
+ }
1059
+
1060
+ static gboolean
1061
+ fdn_file_from_value (napi_env env,
1062
+ napi_value value,
1063
+ GFile ** file)
1064
+ {
1065
+ gchar * path;
1066
+
1067
+ if (!fdn_utf8_from_value (env, value, &path))
1068
+ return FALSE;
1069
+ *file = g_file_new_for_path (path);
1070
+ g_free (path);
1071
+
1072
+ return TRUE;
1073
+ }
1074
+
1075
+ static napi_value
1076
+ fdn_file_to_value (napi_env env,
1077
+ GFile * file)
1078
+ {
1079
+ napi_value result;
1080
+ gchar * path;
1081
+
1082
+ path = g_file_get_path (file);
1083
+ result = fdn_utf8_to_value (env, path);
1084
+ g_free (path);
1085
+
1086
+ return result;
1087
+ }
1088
+
1089
+ static gboolean
1090
+ fdn_tls_certificate_from_value (napi_env env,
1091
+ napi_value value,
1092
+ GTlsCertificate ** certificate)
1093
+ {
1094
+ gchar * str;
1095
+ GError * error = NULL;
1096
+
1097
+ if (!fdn_utf8_from_value (env, value, &str))
1098
+ return FALSE;
1099
+
1100
+ if (strchr (str, '\n') != NULL)
1101
+ *certificate = g_tls_certificate_new_from_pem (str, -1, &error);
1102
+ else
1103
+ *certificate = g_tls_certificate_new_from_file (str, &error);
1104
+
1105
+ g_free (str);
1106
+
1107
+ if (error != NULL)
1108
+ goto invalid_argument;
1109
+ return TRUE;
1110
+
1111
+ invalid_argument:
1112
+ {
1113
+ napi_throw (env, fdn_error_to_value (env, error));
1114
+ g_error_free (error);
1115
+ return FALSE;
1116
+ }
1117
+ }
1118
+
1119
+ static napi_value
1120
+ fdn_tls_certificate_to_value (napi_env env,
1121
+ GTlsCertificate * certificate)
1122
+ {
1123
+ napi_value result;
1124
+ gchar * pem;
1125
+
1126
+ g_object_get (certificate, "certificate-pem", &pem, NULL);
1127
+ result = fdn_utf8_to_value (env, pem);
1128
+ g_free (pem);
1129
+
1130
+ return result;
1131
+ }
1132
+
1133
+ static gboolean
1134
+ fdn_options_from_value (napi_env env,
1135
+ GType object_type,
1136
+ napi_value value,
1137
+ gpointer * options)
1138
+ {
1139
+ gboolean success = FALSE;
1140
+ napi_valuetype value_type;
1141
+ napi_value keys;
1142
+ uint32_t n_keys;
1143
+ guint n_properties = 0;
1144
+ const char ** property_names = NULL;
1145
+ GValue * property_values = NULL;
1146
+ GObjectClass * object_class = NULL;
1147
+ uint32_t i;
1148
+ gchar * gobject_property_name = NULL;
1149
+
1150
+ if (napi_typeof (env, value, &value_type) != napi_ok || value_type != napi_object)
1151
+ goto expected_an_object;
1152
+
1153
+ if (napi_get_property_names (env, value, &keys) != napi_ok)
1154
+ goto beach;
1155
+
1156
+ if (napi_get_array_length (env, keys, &n_keys) != napi_ok)
1157
+ goto beach;
1158
+
1159
+ property_names = g_newa (const char *, n_keys);
1160
+ property_values = g_newa (GValue, n_keys);
1161
+
1162
+ object_class = G_OBJECT_CLASS (g_type_class_ref (object_type));
1163
+
1164
+ for (i = 0; i != n_keys; i++)
1165
+ {
1166
+ napi_value js_key, js_value;
1167
+ gchar * property_name;
1168
+ GParamSpec * pspec;
1169
+
1170
+ if (napi_get_element (env, keys, i, &js_key) != napi_ok)
1171
+ goto beach;
1172
+
1173
+ if (!fdn_utf8_from_value (env, js_key, &property_name))
1174
+ goto beach;
1175
+
1176
+ gobject_property_name = fdn_camel_case_to_kebab_case (property_name);
1177
+ g_free (property_name);
1178
+
1179
+ pspec = g_object_class_find_property (object_class, gobject_property_name);
1180
+ if (pspec == NULL)
1181
+ {
1182
+ g_free (gobject_property_name);
1183
+ gobject_property_name = NULL;
1184
+ continue;
1185
+ }
1186
+
1187
+ if (napi_get_property (env, value, js_key, &js_value) != napi_ok)
1188
+ goto beach;
1189
+
1190
+ if (!fdn_gvalue_from_value (env, pspec->value_type, js_value, &property_values[n_properties]))
1191
+ goto beach;
1192
+
1193
+ property_names[n_properties] = g_steal_pointer (&gobject_property_name);
1194
+ n_properties++;
1195
+ }
1196
+
1197
+ *options = g_object_new_with_properties (object_type, n_properties, property_names, property_values);
1198
+
1199
+ success = TRUE;
1200
+ goto beach;
1201
+
1202
+ expected_an_object:
1203
+ {
1204
+ napi_throw_type_error (env, NULL, "expected an object");
1205
+ goto beach;
1206
+ }
1207
+ beach:
1208
+ {
1209
+ g_free (gobject_property_name);
1210
+
1211
+ for (i = 0; i != n_properties; i++)
1212
+ {
1213
+ g_free ((gchar *) property_names[i]);
1214
+ g_value_unset (&property_values[i]);
1215
+ }
1216
+
1217
+ g_clear_pointer (&object_class, g_type_class_unref);
1218
+
1219
+ return success;
1220
+ }
1221
+ }
1222
+
1223
+ static napi_value
1224
+ fdn_object_subclass_to_value (napi_env env,
1225
+ GObject * object)
1226
+ {
1227
+ napi_value result;
1228
+ napi_ref ctor;
1229
+
1230
+ if (object == NULL)
1231
+ {
1232
+ napi_get_null (env, &result);
1233
+ return result;
1234
+ }
1235
+
1236
+ ctor = g_hash_table_lookup (fdn_constructors, GSIZE_TO_POINTER (G_OBJECT_TYPE (object)));
1237
+ if (ctor == NULL)
1238
+ goto unsupported_type;
1239
+
1240
+ return fdn_object_new (env, object, ctor);
1241
+
1242
+ unsupported_type:
1243
+ {
1244
+ napi_get_null (env, &result);
1245
+ return result;
1246
+ }
1247
+ }
1248
+
1249
+ static napi_value
1250
+ fdn_object_new (napi_env env,
1251
+ GObject * handle,
1252
+ napi_ref constructor)
1253
+ {
1254
+ napi_value result, ctor, handle_wrapper;
1255
+ napi_ref wrapper_ref;
1256
+
1257
+ wrapper_ref = g_object_get_data (handle, "fdn-wrapper");
1258
+ if (wrapper_ref != NULL)
1259
+ {
1260
+ if (napi_get_reference_value (env, wrapper_ref, &result) == napi_ok && result != NULL)
1261
+ return result;
1262
+ }
1263
+
1264
+ napi_get_reference_value (env, constructor, &ctor);
1265
+
1266
+ napi_create_external (env, handle, NULL, NULL, &handle_wrapper);
1267
+ napi_type_tag_object (env, handle_wrapper, &fdn_handle_wrapper_type_tag);
1268
+
1269
+ napi_new_instance (env, ctor, 1, &handle_wrapper, &result);
1270
+
1271
+ return result;
1272
+ }
1273
+
1274
+ static gboolean
1275
+ fdn_object_wrap (napi_env env,
1276
+ napi_value wrapper,
1277
+ GObject * handle,
1278
+ napi_finalize finalizer)
1279
+ {
1280
+ napi_ref ref;
1281
+
1282
+ if (napi_type_tag_object (env, wrapper, &fdn_object_type_tag) != napi_ok)
1283
+ return FALSE;
1284
+
1285
+ if (napi_wrap (env, wrapper, handle, NULL, NULL, NULL) != napi_ok)
1286
+ return FALSE;
1287
+
1288
+ if (napi_add_finalizer (env, wrapper, handle, finalizer, NULL, NULL) != napi_ok)
1289
+ return FALSE;
1290
+
1291
+ napi_create_reference (env, wrapper, 0, &ref);
1292
+ g_object_set_data (handle, "fdn-wrapper", ref);
1293
+
1294
+ return TRUE;
1295
+ }
1296
+
1297
+ static gboolean
1298
+ fdn_object_unwrap (napi_env env,
1299
+ napi_value wrapper,
1300
+ GType expected_type,
1301
+ GObject ** handle)
1302
+ {
1303
+ bool is_instance;
1304
+ GObject * obj;
1305
+
1306
+ if (napi_check_object_type_tag (env, wrapper, &fdn_object_type_tag, &is_instance) != napi_ok || !is_instance)
1307
+ goto invalid_tag;
1308
+
1309
+ if (napi_unwrap (env, wrapper, (void **) &obj) != napi_ok)
1310
+ goto invalid_tag;
1311
+
1312
+ if (!g_type_is_a (G_OBJECT_TYPE (obj), expected_type))
1313
+ goto invalid_type;
1314
+
1315
+ *handle = g_object_ref (obj);
1316
+ return TRUE;
1317
+
1318
+ invalid_tag:
1319
+ {
1320
+ gchar * msg;
1321
+
1322
+ msg = g_strdup_printf ("expected an instance of %s", g_type_name (expected_type));
1323
+ napi_throw_type_error (env, NULL, msg);
1324
+ g_free (msg);
1325
+
1326
+ return FALSE;
1327
+ }
1328
+ invalid_type:
1329
+ {
1330
+ gchar * msg;
1331
+
1332
+ msg = g_strdup_printf ("expected an instance of %s, got a %s",
1333
+ g_type_name (expected_type),
1334
+ g_type_name (G_OBJECT_TYPE (obj)));
1335
+ napi_throw_type_error (env, NULL, msg);
1336
+ g_free (msg);
1337
+
1338
+ return FALSE;
1339
+ }
1340
+ }
1341
+
1342
+ static void
1343
+ fdn_object_finalize (napi_env env,
1344
+ void * finalize_data,
1345
+ void * finalize_hint)
1346
+ {
1347
+ GObject * handle = G_OBJECT (finalize_data);
1348
+
1349
+ napi_delete_reference (env, g_object_steal_data (handle, "fdn-wrapper"));
1350
+
1351
+ g_object_unref (handle);
1352
+ }
1353
+
1354
+ static napi_value
1355
+ fdn_object_get_signal (napi_env env,
1356
+ napi_callback_info info,
1357
+ const gchar * name,
1358
+ const gchar * js_storage_name,
1359
+ FdnSignalBehavior behavior)
1360
+ {
1361
+ napi_value result, jsthis, js_storage_name_value;
1362
+ napi_valuetype type;
1363
+
1364
+ if (napi_get_cb_info (env, info, NULL, NULL, &jsthis, NULL) != napi_ok)
1365
+ return NULL;
1366
+
1367
+ js_storage_name_value = fdn_utf8_to_value (env, js_storage_name);
1368
+
1369
+ if (napi_get_property (env, jsthis, js_storage_name_value, &result) != napi_ok)
1370
+ return NULL;
1371
+
1372
+ if (napi_typeof (env, result, &type) != napi_ok)
1373
+ return NULL;
1374
+
1375
+ if (type == napi_undefined)
1376
+ {{
1377
+ GObject * handle;
1378
+
1379
+ if (napi_unwrap (env, jsthis, (void **) &handle) != napi_ok)
1380
+ return NULL;
1381
+
1382
+ result = fdn_signal_new (env, handle, name, behavior);
1383
+ napi_set_property (env, jsthis, js_storage_name_value, result);
1384
+ }}
1385
+
1386
+ return result;
1387
+ }
1388
+
1389
+ static napi_value
1390
+ fdn_signal_new (napi_env env,
1391
+ GObject * handle,
1392
+ const gchar * name,
1393
+ FdnSignalBehavior behavior)
1394
+ {
1395
+ napi_value result, constructor, handle_wrapper;
1396
+ napi_value args[3];
1397
+
1398
+ napi_get_reference_value (env, fdn_signal_constructor, &constructor);
1399
+
1400
+ napi_create_external (env, handle, NULL, NULL, &handle_wrapper);
1401
+ napi_type_tag_object (env, handle_wrapper, &fdn_handle_wrapper_type_tag);
1402
+
1403
+ args[0] = handle_wrapper;
1404
+ args[1] = fdn_utf8_to_value (env, name);
1405
+ args[2] = fdn_int_to_value (env, behavior);
1406
+
1407
+ napi_new_instance (env, constructor, G_N_ELEMENTS (args), args, &result);
1408
+
1409
+ return result;
1410
+ }
1411
+
1412
+ static void
1413
+ fdn_signal_register (napi_env env,
1414
+ napi_value exports)
1415
+ {
1416
+ napi_property_descriptor properties[] =
1417
+ {
1418
+ { "connect", NULL, fdn_signal_connect, NULL, NULL, NULL, napi_default, NULL },
1419
+ { "disconnect", NULL, fdn_signal_disconnect, NULL, NULL, NULL, napi_default, NULL },
1420
+ };
1421
+ napi_value constructor;
1422
+
1423
+ napi_define_class (env, "Signal", NAPI_AUTO_LENGTH, fdn_signal_construct, NULL, G_N_ELEMENTS (properties), properties, &constructor);
1424
+ napi_create_reference (env, constructor, 1, &fdn_signal_constructor);
1425
+
1426
+ napi_set_named_property (env, exports, "Signal", constructor);
1427
+ }
1428
+
1429
+ static napi_value
1430
+ fdn_signal_construct (napi_env env,
1431
+ napi_callback_info info)
1432
+ {
1433
+ size_t argc = 3;
1434
+ napi_value args[3];
1435
+ napi_value jsthis;
1436
+ GObject * handle;
1437
+ bool is_instance;
1438
+ gchar * name = NULL;
1439
+ FdnSignalBehavior behavior;
1440
+ FdnSignal * sig = NULL;
1441
+
1442
+ if (napi_get_cb_info (env, info, &argc, args, &jsthis, NULL) != napi_ok)
1443
+ goto propagate_error;
1444
+
1445
+ if (argc != 3)
1446
+ goto missing_argument;
1447
+
1448
+ if (napi_check_object_type_tag (env, args[0], &fdn_handle_wrapper_type_tag, &is_instance) != napi_ok || !is_instance)
1449
+ goto invalid_handle;
1450
+
1451
+ if (napi_get_value_external (env, args[0], (void **) &handle) != napi_ok)
1452
+ goto propagate_error;
1453
+
1454
+ if (!fdn_utf8_from_value (env, args[1], &name))
1455
+ goto propagate_error;
1456
+
1457
+ if (!fdn_int_from_value (env, args[2], (gint *) &behavior))
1458
+ goto propagate_error;
1459
+ if (behavior != FDN_SIGNAL_ALLOW_EXIT && behavior != FDN_SIGNAL_KEEP_ALIVE)
1460
+ goto invalid_behavior;
1461
+
1462
+ sig = g_slice_new (FdnSignal);
1463
+ sig->handle = g_object_ref (handle);
1464
+ sig->id = g_signal_lookup (name, G_OBJECT_TYPE (sig->handle));
1465
+ sig->behavior = behavior;
1466
+ sig->closures = NULL;
1467
+ if (sig->id == 0)
1468
+ goto invalid_signal_name;
1469
+
1470
+ if (napi_wrap (env, jsthis, sig, NULL, NULL, NULL) != napi_ok)
1471
+ goto propagate_error;
1472
+
1473
+ if (napi_add_finalizer (env, jsthis, sig, fdn_signal_finalize, NULL, NULL) != napi_ok)
1474
+ goto propagate_error;
1475
+
1476
+ g_free (name);
1477
+
1478
+ return jsthis;
1479
+
1480
+ missing_argument:
1481
+ {
1482
+ napi_throw_error (env, NULL, "missing argument");
1483
+ goto propagate_error;
1484
+ }
1485
+ invalid_handle:
1486
+ {
1487
+ napi_throw_type_error (env, NULL, "expected an object handle");
1488
+ goto propagate_error;
1489
+ }
1490
+ invalid_behavior:
1491
+ {
1492
+ napi_throw_error (env, NULL, "invalid behavior");
1493
+ goto propagate_error;
1494
+ }
1495
+ invalid_signal_name:
1496
+ {
1497
+ napi_throw_type_error (env, NULL, "bad signal name");
1498
+ goto propagate_error;
1499
+ }
1500
+ propagate_error:
1501
+ {
1502
+ if (sig != NULL)
1503
+ fdn_signal_finalize (env, sig, NULL);
1504
+
1505
+ g_free (name);
1506
+
1507
+ return NULL;
1508
+ }
1509
+ }
1510
+
1511
+ static void
1512
+ fdn_signal_finalize (napi_env env,
1513
+ void * finalize_data,
1514
+ void * finalize_hint)
1515
+ {
1516
+ FdnSignal * sig = finalize_data;
1517
+ GSList * cur;
1518
+
1519
+ for (cur = sig->closures; cur != NULL; cur = cur->next)
1520
+ fdn_signal_disconnect_closure (sig, cur->data);
1521
+ g_slist_free (sig->closures);
1522
+
1523
+ g_object_unref (sig->handle);
1524
+
1525
+ g_slice_free (FdnSignal, sig);
1526
+ }
1527
+
1528
+ static napi_value
1529
+ fdn_signal_connect (napi_env env,
1530
+ napi_callback_info info)
1531
+ {
1532
+ napi_value js_retval;
1533
+ FdnSignal * self;
1534
+ napi_value js_self, handler;
1535
+ FdnSignalClosure * sc;
1536
+ GClosure * closure;
1537
+
1538
+ if (!fdn_signal_parse_arguments (env, info, &self, &js_self, &handler))
1539
+ return NULL;
1540
+
1541
+ sc = fdn_signal_closure_new (env, self, js_self, handler);
1542
+
1543
+ closure = (GClosure *) sc;
1544
+ g_closure_ref (closure);
1545
+ g_closure_sink (closure);
1546
+ self->closures = g_slist_prepend (self->closures, sc);
1547
+
1548
+ sc->handler_id = g_signal_connect_closure_by_id (self->handle, self->id, 0, closure, TRUE);
1549
+
1550
+ napi_get_undefined (env, &js_retval);
1551
+
1552
+ return js_retval;
1553
+ }
1554
+
1555
+ static napi_value
1556
+ fdn_signal_disconnect (napi_env env,
1557
+ napi_callback_info info)
1558
+ {
1559
+ napi_value js_retval;
1560
+ FdnSignal * self;
1561
+ napi_value handler;
1562
+ GSList * cur;
1563
+
1564
+ if (!fdn_signal_parse_arguments (env, info, &self, NULL, &handler))
1565
+ return NULL;
1566
+
1567
+ for (cur = self->closures; cur != NULL; cur = cur->next)
1568
+ {
1569
+ FdnSignalClosure * closure = cur->data;
1570
+ napi_value candidate_handler;
1571
+ bool same_handler;
1572
+
1573
+ napi_get_reference_value (env, closure->handler, &candidate_handler);
1574
+
1575
+ napi_strict_equals (env, candidate_handler, handler, &same_handler);
1576
+
1577
+ if (same_handler)
1578
+ {
1579
+ fdn_signal_disconnect_closure (self, closure);
1580
+ self->closures = g_slist_delete_link (self->closures, cur);
1581
+ break;
1582
+ }
1583
+ }
1584
+
1585
+ napi_get_undefined (env, &js_retval);
1586
+
1587
+ return js_retval;
1588
+ }
1589
+
1590
+ static void
1591
+ fdn_signal_disconnect_closure (FdnSignal * self,
1592
+ FdnSignalClosure * closure)
1593
+ {
1594
+ g_signal_handler_disconnect (self->handle, closure->handler_id);
1595
+ closure->handler_id = 0;
1596
+
1597
+ closure->state = FDN_SIGNAL_CLOSURE_CLOSED;
1598
+
1599
+ g_closure_unref ((GClosure *) closure);
1600
+ }
1601
+
1602
+ static gboolean
1603
+ fdn_signal_parse_arguments (napi_env env,
1604
+ napi_callback_info info,
1605
+ FdnSignal ** self,
1606
+ napi_value * js_self,
1607
+ napi_value * handler)
1608
+ {
1609
+ size_t argc = 1;
1610
+ napi_value jsthis;
1611
+
1612
+ if (napi_get_cb_info (env, info, &argc, handler, &jsthis, NULL) != napi_ok)
1613
+ goto propagate_error;
1614
+
1615
+ if (napi_unwrap (env, jsthis, (void **) self) != napi_ok)
1616
+ goto propagate_error;
1617
+
1618
+ if (js_self != NULL)
1619
+ *js_self = jsthis;
1620
+
1621
+ if (argc != 1)
1622
+ goto missing_handler;
1623
+
1624
+ if (!fdn_is_function (env, *handler))
1625
+ goto invalid_handler;
1626
+
1627
+ return TRUE;
1628
+
1629
+ missing_handler:
1630
+ {
1631
+ napi_throw_error (env, NULL, "missing argument: handler");
1632
+ return FALSE;
1633
+ }
1634
+ invalid_handler:
1635
+ {
1636
+ napi_throw_error (env, NULL, "expected a function");
1637
+ return FALSE;
1638
+ }
1639
+ propagate_error:
1640
+ {
1641
+ return FALSE;
1642
+ }
1643
+ }
1644
+
1645
+ static FdnSignalClosure *
1646
+ fdn_signal_closure_new (napi_env env,
1647
+ FdnSignal * sig,
1648
+ napi_value js_sig,
1649
+ napi_value handler)
1650
+ {
1651
+ FdnSignalClosure * sc;
1652
+ GClosure * closure;
1653
+
1654
+ closure = g_closure_new_simple (sizeof (FdnSignalClosure), NULL);
1655
+ g_closure_add_finalize_notifier (closure, NULL, fdn_signal_closure_finalize);
1656
+ g_closure_set_marshal (closure, fdn_signal_closure_marshal);
1657
+
1658
+ sc = (FdnSignalClosure *) closure;
1659
+ sc->sig = sig;
1660
+ napi_create_reference (env, js_sig, 1, &sc->js_sig);
1661
+ sc->state = FDN_SIGNAL_CLOSURE_OPEN;
1662
+ napi_create_threadsafe_function (env, NULL, NULL, fdn_utf8_to_value (env, g_signal_name (sig->id)), 0, 1, NULL, NULL, sc,
1663
+ fdn_signal_closure_deliver, &sc->tsfn);
1664
+
1665
+ if (sig->behavior == FDN_SIGNAL_ALLOW_EXIT)
1666
+ napi_unref_threadsafe_function (env, sc->tsfn);
1667
+
1668
+ napi_create_reference (env, handler, 1, &sc->handler);
1669
+
1670
+ return sc;
1671
+ }
1672
+
1673
+ static void
1674
+ fdn_signal_closure_finalize (gpointer data,
1675
+ GClosure * closure)
1676
+ {
1677
+ FdnSignalClosure * self = (FdnSignalClosure *) closure;
1678
+ FdnSignalClosureMessage * message;
1679
+ FdnSignalClosureMessageDestroy * d;
1680
+
1681
+ if (fdn_in_cleanup)
1682
+ return;
1683
+
1684
+ message = g_slice_new (FdnSignalClosureMessage);
1685
+ message->type = FDN_SIGNAL_CLOSURE_MESSAGE_DESTROY;
1686
+
1687
+ d = &message->payload.destroy;
1688
+ d->js_sig = self->js_sig;
1689
+ d->tsfn = self->tsfn;
1690
+ d->handler = self->handler;
1691
+
1692
+ napi_call_threadsafe_function (self->tsfn, message, napi_tsfn_blocking);
1693
+ }
1694
+
1695
+ static void
1696
+ fdn_signal_closure_marshal (GClosure * closure,
1697
+ GValue * return_gvalue,
1698
+ guint n_param_values,
1699
+ const GValue * param_values,
1700
+ gpointer invocation_hint,
1701
+ gpointer marshal_data)
1702
+ {
1703
+ FdnSignalClosure * self = (FdnSignalClosure *) closure;
1704
+ FdnSignalClosureMessage * message;
1705
+ GArray * args;
1706
+ guint i;
1707
+
1708
+ message = g_slice_new (FdnSignalClosureMessage);
1709
+ message->type = FDN_SIGNAL_CLOSURE_MESSAGE_MARSHAL;
1710
+
1711
+ g_assert (n_param_values >= 1);
1712
+ args = g_array_sized_new (FALSE, FALSE, sizeof (GValue), n_param_values - 1);
1713
+ message->payload.marshal.args = args;
1714
+
1715
+ for (i = 1; i != n_param_values; i++)
1716
+ {
1717
+ GValue val;
1718
+
1719
+ g_value_init (&val, param_values[i].g_type);
1720
+ g_value_copy (&param_values[i], &val);
1721
+ g_array_append_val (args, val);
1722
+ }
1723
+
1724
+ g_closure_ref (closure);
1725
+ napi_call_threadsafe_function (self->tsfn, message, napi_tsfn_blocking);
1726
+ }
1727
+
1728
+ static void
1729
+ fdn_signal_closure_deliver (napi_env env,
1730
+ napi_value js_cb,
1731
+ void * context,
1732
+ void * data)
1733
+ {
1734
+ FdnSignalClosureMessage * message = data;
1735
+
1736
+ switch (message->type)
1737
+ {
1738
+ case FDN_SIGNAL_CLOSURE_MESSAGE_DESTROY:
1739
+ {
1740
+ FdnSignalClosureMessageDestroy * d = &message->payload.destroy;
1741
+ napi_value js_sig;
1742
+ FdnSignal * sig;
1743
+ FdnSignalBehavior behavior;
1744
+
1745
+ napi_get_reference_value (env, d->js_sig, &js_sig);
1746
+ napi_unwrap (env, js_sig, (void **) &sig);
1747
+ behavior = sig->behavior;
1748
+
1749
+ napi_delete_reference (env, d->handler);
1750
+ napi_delete_reference (env, d->js_sig);
1751
+ if (behavior == FDN_SIGNAL_KEEP_ALIVE)
1752
+ napi_unref_threadsafe_function (env, d->tsfn);
1753
+ napi_release_threadsafe_function (d->tsfn, napi_tsfn_abort);
1754
+
1755
+ break;
1756
+ }
1757
+ case FDN_SIGNAL_CLOSURE_MESSAGE_MARSHAL:
1758
+ {
1759
+ FdnSignalClosure * self = context;
1760
+ GArray * args;
1761
+ guint i;
1762
+
1763
+ args = message->payload.marshal.args;
1764
+
1765
+ if (self->state == FDN_SIGNAL_CLOSURE_OPEN)
1766
+ {
1767
+ napi_value * js_args;
1768
+ napi_value global, handler, js_result;
1769
+
1770
+ js_args = g_newa (napi_value, args->len);
1771
+ for (i = 0; i != args->len; i++)
1772
+ js_args[i] = fdn_gvalue_to_value (env, &g_array_index (args, GValue, i));
1773
+
1774
+ napi_get_global (env, &global);
1775
+ napi_get_reference_value (env, self->handler, &handler);
1776
+
1777
+ napi_call_function (env, global, handler, args->len, js_args, &js_result);
1778
+ }
1779
+
1780
+ for (i = 0; i != args->len; i++)
1781
+ g_value_reset (&g_array_index (args, GValue, i));
1782
+ g_array_free (args, TRUE);
1783
+
1784
+ g_closure_unref ((GClosure *) self);
1785
+
1786
+ break;
1787
+ }
1788
+ default:
1789
+ g_assert_not_reached ();
1790
+ }
1791
+
1792
+ g_slice_free (FdnSignalClosureMessage, message);
1793
+ }
1794
+
1795
+ static void
1796
+ fdn_keep_alive_until (napi_env env,
1797
+ napi_value js_object,
1798
+ GObject * handle,
1799
+ FdnIsDestroyedFunc is_destroyed,
1800
+ const gchar * destroy_signal_name)
1801
+ {
1802
+ FdnKeepAliveContext * context;
1803
+
1804
+ context = g_slice_new (FdnKeepAliveContext);
1805
+ context->ref_count = 2;
1806
+ context->handle = g_object_ref (handle);
1807
+ context->signal_handler_id = 0;
1808
+
1809
+ napi_ref_threadsafe_function (env, fdn_keep_alive_tsfn);
1810
+
1811
+ napi_add_finalizer (env, js_object, context, fdn_keep_alive_on_finalize, NULL, NULL);
1812
+
1813
+ context->signal_handler_id = g_signal_connect_data (handle, destroy_signal_name, G_CALLBACK (fdn_keep_alive_on_destroy_signal), context,
1814
+ fdn_keep_alive_on_destroy_signal_handler_detached, 0);
1815
+
1816
+ if (is_destroyed (handle))
1817
+ {
1818
+ g_atomic_int_inc (&context->ref_count);
1819
+ fdn_keep_alive_schedule_cleanup (context);
1820
+ }
1821
+ }
1822
+
1823
+ static void
1824
+ fdn_keep_alive_on_finalize (napi_env env,
1825
+ void * finalize_data,
1826
+ void * finalize_hint)
1827
+ {
1828
+ FdnKeepAliveContext * context = finalize_data;
1829
+
1830
+ fdn_keep_alive_schedule_cleanup (context);
1831
+ }
1832
+
1833
+ static void
1834
+ fdn_keep_alive_on_destroy_signal (GObject * handle,
1835
+ gpointer user_data)
1836
+ {
1837
+ FdnKeepAliveContext * context = user_data;
1838
+
1839
+ g_atomic_int_inc (&context->ref_count);
1840
+ fdn_keep_alive_schedule_cleanup (context);
1841
+ }
1842
+
1843
+ static void
1844
+ fdn_keep_alive_on_destroy_signal_handler_detached (gpointer data,
1845
+ GClosure * closure)
1846
+ {
1847
+ FdnKeepAliveContext * context = data;
1848
+
1849
+ fdn_keep_alive_schedule_cleanup (context);
1850
+ }
1851
+
1852
+ static void
1853
+ fdn_keep_alive_schedule_cleanup (FdnKeepAliveContext * context)
1854
+ {
1855
+ if (fdn_in_cleanup)
1856
+ return;
1857
+
1858
+ napi_call_threadsafe_function (fdn_keep_alive_tsfn, context, napi_tsfn_blocking);
1859
+ }
1860
+
1861
+ static void
1862
+ fdn_keep_alive_on_tsfn_invoke (napi_env env,
1863
+ napi_value js_cb,
1864
+ void * context,
1865
+ void * data)
1866
+ {
1867
+ FdnKeepAliveContext * ctx = data;
1868
+
1869
+ if (ctx->signal_handler_id != 0)
1870
+ {
1871
+ g_signal_handler_disconnect (ctx->handle, ctx->signal_handler_id);
1872
+ ctx->signal_handler_id = 0;
1873
+
1874
+ g_object_unref (ctx->handle);
1875
+ ctx->handle = NULL;
1876
+
1877
+ napi_unref_threadsafe_function (env, fdn_keep_alive_tsfn);
1878
+ }
1879
+
1880
+ if (g_atomic_int_dec_and_test (&ctx->ref_count))
1881
+ g_slice_free (FdnKeepAliveContext, ctx);
1882
+ }
1883
+
1884
+ static void
1885
+ fdn_inherit_val_val (napi_env env,
1886
+ napi_value sub_ctor,
1887
+ napi_value super_ctor,
1888
+ napi_value object_ctor,
1889
+ napi_value set_proto)
1890
+ {
1891
+ napi_value argv[2], sub_proto, super_proto;
1892
+
1893
+ argv[0] = sub_ctor;
1894
+ argv[1] = super_ctor;
1895
+ napi_call_function (env, object_ctor, set_proto, G_N_ELEMENTS (argv), argv, NULL);
1896
+
1897
+ napi_get_named_property (env, sub_ctor, "prototype", &sub_proto);
1898
+ napi_get_named_property (env, super_ctor, "prototype", &super_proto);
1899
+ argv[0] = sub_proto;
1900
+ argv[1] = super_proto;
1901
+ napi_call_function (env, object_ctor, set_proto, G_N_ELEMENTS (argv), argv, NULL);
1902
+ }
1903
+
1904
+ static void
1905
+ fdn_inherit_val_ref (napi_env env,
1906
+ napi_value sub_ctor,
1907
+ napi_ref super_ctor,
1908
+ napi_value object_ctor,
1909
+ napi_value set_proto)
1910
+ {
1911
+ napi_value super_ctor_val;
1912
+
1913
+ napi_get_reference_value (env, super_ctor, &super_ctor_val);
1914
+
1915
+ fdn_inherit_val_val (env, sub_ctor, super_ctor_val, object_ctor, set_proto);
1916
+ }
1917
+
1918
+ static void
1919
+ fdn_inherit_ref_val (napi_env env,
1920
+ napi_ref sub_ctor,
1921
+ napi_value super_ctor,
1922
+ napi_value object_ctor,
1923
+ napi_value set_proto)
1924
+ {
1925
+ napi_value sub_ctor_val;
1926
+
1927
+ napi_get_reference_value (env, sub_ctor, &sub_ctor_val);
1928
+
1929
+ fdn_inherit_val_val (env, sub_ctor_val, super_ctor, object_ctor, set_proto);
1930
+ }
1931
+
1932
+ static void
1933
+ fdn_inherit_ref_ref (napi_env env,
1934
+ napi_ref sub_ctor,
1935
+ napi_ref super_ctor,
1936
+ napi_value object_ctor,
1937
+ napi_value set_proto)
1938
+ {
1939
+ napi_value sub_ctor_val, super_ctor_val;
1940
+
1941
+ napi_get_reference_value (env, sub_ctor, &sub_ctor_val);
1942
+ napi_get_reference_value (env, super_ctor, &super_ctor_val);
1943
+
1944
+ fdn_inherit_val_val (env, sub_ctor_val, super_ctor_val, object_ctor, set_proto);
1945
+ }
1946
+
1947
+ static gchar *
1948
+ fdn_camel_case_to_kebab_case (const gchar * name)
1949
+ {
1950
+ GString * result;
1951
+ const gchar * p;
1952
+
1953
+ result = g_string_new (NULL);
1954
+
1955
+ for (p = name; *p != '\0'; p++)
1956
+ {
1957
+ if (g_ascii_isupper (*p))
1958
+ {
1959
+ if (p != name)
1960
+ g_string_append_c (result, '-');
1961
+ g_string_append_c (result, g_ascii_tolower (*p));
1962
+ }
1963
+ else
1964
+ {
1965
+ g_string_append_c (result, *p);
1966
+ }
1967
+ }
1968
+
1969
+ return g_string_free (result, FALSE);
1970
+ }