node-gtk 0.14.0 → 2.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/README.md +86 -196
- package/bin/node-gtk.js +31 -0
- package/lib/binding/node-v127-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v131-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v137-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v147-linux-x64/node_gtk.node +0 -0
- package/lib/bootstrap.js +22 -4
- package/lib/index.js +25 -0
- package/lib/overrides/Gtk-4.0.js +4 -2
- package/lib/register-class.js +1 -1
- package/package.json +12 -5
- package/scripts/build-test-fixtures.js +237 -0
- package/scripts/ci.sh +7 -3
- package/src/boxed.cc +47 -17
- package/src/boxed.h +15 -1
- package/src/callback.cc +14 -2
- package/src/callback.h +1 -0
- package/src/closure.cc +105 -10
- package/src/debug.cc +4 -3
- package/src/function.cc +97 -40
- package/src/function.h +4 -3
- package/src/gi.cc +70 -3
- package/src/gobject.cc +54 -36
- package/src/loop.cc +1 -1
- package/src/modules/cairo/glyph.cc +1 -0
- package/src/modules/cairo/text-cluster.cc +1 -0
- package/src/modules/system.cc +2 -2
- package/src/type.cc +3 -2
- package/src/value.cc +358 -44
- package/src/value.h +27 -5
- package/tools/README.md +91 -0
- package/tools/generate-types.js +1045 -0
- package/lib/binding/node-v102-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v108-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v115-linux-x64/node_gtk.node +0 -0
- package/lib/binding/node-v93-linux-x64/node_gtk.node +0 -0
package/src/debug.cc
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "type.h"
|
|
11
11
|
|
|
12
12
|
#include <cstdio>
|
|
13
|
+
#include <cinttypes>
|
|
13
14
|
|
|
14
15
|
namespace GNodeJS {
|
|
15
16
|
|
|
@@ -245,16 +246,16 @@ void print_gtype (GType type) {
|
|
|
245
246
|
void print_type (GType type) {
|
|
246
247
|
GType t = type;
|
|
247
248
|
while(!G_TYPE_IS_FUNDAMENTAL(type) && t != 0) {
|
|
248
|
-
printf("\t\x1b[92m -> %s \t (%
|
|
249
|
+
printf("\t\x1b[92m -> %s \t (%" PRIuPTR ")\x1b[0m\n", g_type_name(t), (uintptr_t)t);
|
|
249
250
|
t = g_type_parent(t);
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
void print_klass (void * klass) {
|
|
254
255
|
printf("\x1b[38;5;202m");
|
|
255
|
-
printf("klass: %s (type: %
|
|
256
|
+
printf("klass: %s (type: %" PRIuPTR " )",
|
|
256
257
|
G_OBJECT_CLASS_NAME (klass),
|
|
257
|
-
G_OBJECT_CLASS_TYPE (klass) );
|
|
258
|
+
(uintptr_t)G_OBJECT_CLASS_TYPE (klass) );
|
|
258
259
|
printf("\x1b[0m\n");
|
|
259
260
|
}
|
|
260
261
|
|
package/src/function.cc
CHANGED
|
@@ -55,7 +55,9 @@ static void* AllocateArgument (GIBaseInfo *arg_info) {
|
|
|
55
55
|
|
|
56
56
|
GIBaseInfo* base_info = g_type_info_get_interface (&arg_type);
|
|
57
57
|
size_t size = Boxed::GetSize (base_info);
|
|
58
|
-
|
|
58
|
+
GType gtype = g_registered_type_info_get_g_type (base_info);
|
|
59
|
+
// Match g_boxed_free's allocator for registered boxed types (#290, #213).
|
|
60
|
+
void* pointer = AllocateBoxed(gtype, size);
|
|
59
61
|
|
|
60
62
|
g_base_info_unref(base_info);
|
|
61
63
|
return pointer;
|
|
@@ -67,6 +69,35 @@ static bool IsMethod (GIBaseInfo *info) {
|
|
|
67
69
|
(flags & GI_FUNCTION_IS_CONSTRUCTOR) == 0);
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
static bool EndsWith (const char *str, const char *suffix) {
|
|
73
|
+
size_t str_len = strlen (str);
|
|
74
|
+
size_t suffix_len = strlen (suffix);
|
|
75
|
+
return str_len >= suffix_len && strcmp (str + str_len - suffix_len, suffix) == 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* True for an instance method that deallocates the instance itself — a *_free
|
|
79
|
+
* or *_unref on a boxed/struct/union. node-gtk's wrapper owns the memory and
|
|
80
|
+
* frees it on GC, so after such a call the wrapper must disown it or GC will
|
|
81
|
+
* double-free (#429). Restricted to boxed-like containers: GObject lifetime is
|
|
82
|
+
* handled separately, and gtk_widget_destroy() etc. don't free the wrapper. */
|
|
83
|
+
static bool FreesInstance (GIFunctionInfo *info) {
|
|
84
|
+
if (!IsMethod (info))
|
|
85
|
+
return false;
|
|
86
|
+
|
|
87
|
+
const char *symbol = g_function_info_get_symbol (info);
|
|
88
|
+
if (symbol == NULL || !(EndsWith (symbol, "_free") || EndsWith (symbol, "_unref")))
|
|
89
|
+
return false;
|
|
90
|
+
|
|
91
|
+
GIBaseInfo *container = g_base_info_get_container (info);
|
|
92
|
+
if (container == NULL)
|
|
93
|
+
return false;
|
|
94
|
+
|
|
95
|
+
GIInfoType type = g_base_info_get_type (container);
|
|
96
|
+
return type == GI_INFO_TYPE_STRUCT
|
|
97
|
+
|| type == GI_INFO_TYPE_UNION
|
|
98
|
+
|| type == GI_INFO_TYPE_BOXED;
|
|
99
|
+
}
|
|
100
|
+
|
|
70
101
|
static bool ShouldSkipReturn(GIBaseInfo *info, GITypeInfo *return_type) {
|
|
71
102
|
return g_type_info_get_tag(return_type) == GI_TYPE_TAG_VOID
|
|
72
103
|
|| g_callable_info_skip_return(info) == TRUE;
|
|
@@ -134,6 +165,7 @@ bool FunctionInfo::Init() {
|
|
|
134
165
|
|
|
135
166
|
is_method = IsMethod(info);
|
|
136
167
|
can_throw = g_callable_info_can_throw_gerror (info);
|
|
168
|
+
frees_instance = FreesInstance(info);
|
|
137
169
|
|
|
138
170
|
n_callable_args = g_callable_info_get_n_args (info);
|
|
139
171
|
n_total_args = n_callable_args;
|
|
@@ -208,14 +240,14 @@ bool FunctionInfo::Init() {
|
|
|
208
240
|
if (closure_i >= 0 && closure_i < n_callable_args)
|
|
209
241
|
call_parameters[closure_i].type = ParameterType::kSKIP;
|
|
210
242
|
|
|
211
|
-
if (destroy_i < i) {
|
|
243
|
+
if (destroy_i >= 0 && destroy_i < i) {
|
|
212
244
|
if (IsDirectionIn(call_parameters[destroy_i].direction))
|
|
213
245
|
n_in_args--;
|
|
214
246
|
if (IsDirectionOut(call_parameters[destroy_i].direction))
|
|
215
247
|
n_out_args--;
|
|
216
248
|
}
|
|
217
249
|
|
|
218
|
-
if (closure_i < i) {
|
|
250
|
+
if (closure_i >= 0 && closure_i < i) {
|
|
219
251
|
if (IsDirectionIn(call_parameters[closure_i].direction))
|
|
220
252
|
n_in_args--;
|
|
221
253
|
if (IsDirectionOut(call_parameters[closure_i].direction))
|
|
@@ -335,7 +367,7 @@ Local<Value> FunctionCall (
|
|
|
335
367
|
|
|
336
368
|
if (func->is_method) {
|
|
337
369
|
GIBaseInfo *container = g_base_info_get_container (gi_info);
|
|
338
|
-
|
|
370
|
+
V8ToGIArgumentInterface(container, &total_arg_values[0], info.This());
|
|
339
371
|
callable_arg_values = &total_arg_values[1];
|
|
340
372
|
} else {
|
|
341
373
|
callable_arg_values = &total_arg_values[0];
|
|
@@ -388,16 +420,16 @@ Local<Value> FunctionCall (
|
|
|
388
420
|
}
|
|
389
421
|
else if (param.type == ParameterType::kCALLBACK) {
|
|
390
422
|
Callback *callback;
|
|
391
|
-
|
|
423
|
+
gpointer callable; /* executable trampoline address (see Callback) */
|
|
392
424
|
|
|
393
425
|
if (info[in_arg]->IsNullOrUndefined()) {
|
|
394
|
-
|
|
426
|
+
callable = nullptr;
|
|
395
427
|
callback = nullptr;
|
|
396
428
|
} else {
|
|
397
429
|
GICallableInfo *callback_info = g_type_info_get_interface (&type_info);
|
|
398
430
|
GIScopeType scope_type = g_arg_info_get_scope(&arg_info);
|
|
399
431
|
callback = new Callback(info[in_arg].As<Function>(), callback_info, scope_type);
|
|
400
|
-
|
|
432
|
+
callable = callback->native_address;
|
|
401
433
|
g_base_info_unref (callback_info);
|
|
402
434
|
}
|
|
403
435
|
|
|
@@ -414,7 +446,7 @@ Local<Value> FunctionCall (
|
|
|
414
446
|
callable_arg_values[closure_i].v_pointer = callback;
|
|
415
447
|
}
|
|
416
448
|
|
|
417
|
-
callable_arg_values[i].v_pointer =
|
|
449
|
+
callable_arg_values[i].v_pointer = callable;
|
|
418
450
|
func->call_parameters[i].data.v_pointer = callback;
|
|
419
451
|
}
|
|
420
452
|
|
|
@@ -440,6 +472,22 @@ Local<Value> FunctionCall (
|
|
|
440
472
|
param.data.v_pointer = callable_arg_values[i].v_pointer;
|
|
441
473
|
callable_arg_values[i].v_pointer = ¶m.data;
|
|
442
474
|
}
|
|
475
|
+
// For a transfer-container IN GList/GSList/GHashTable the callee
|
|
476
|
+
// frees the container; snapshot the (caller-owned) element
|
|
477
|
+
// pointers now so they can be freed after the call (#399).
|
|
478
|
+
else if (IsTransferContainerInList(&type_info,
|
|
479
|
+
g_arg_info_get_ownership_transfer(&arg_info), direction)) {
|
|
480
|
+
param.data = {};
|
|
481
|
+
param.data.v_pointer = CaptureTransferContainerElements(
|
|
482
|
+
&type_info, callable_arg_values[i].v_pointer);
|
|
483
|
+
}
|
|
484
|
+
// For a transfer-full IN boxed (or array of boxed) the callee
|
|
485
|
+
// frees the memory; hand it a copy so the JS wrapper's own
|
|
486
|
+
// memory isn't double-freed when it's finalized (#409).
|
|
487
|
+
else if (direction == GI_DIRECTION_IN
|
|
488
|
+
&& g_arg_info_get_ownership_transfer(&arg_info) == GI_TRANSFER_EVERYTHING) {
|
|
489
|
+
CopyBoxedForTransferFullIn(&type_info, &callable_arg_values[i], param.length);
|
|
490
|
+
}
|
|
443
491
|
}
|
|
444
492
|
|
|
445
493
|
in_arg++;
|
|
@@ -488,24 +536,29 @@ Local<Value> FunctionCall (
|
|
|
488
536
|
Nan::ThrowError(error_stack->message);
|
|
489
537
|
g_error_free(error_stack);
|
|
490
538
|
}
|
|
539
|
+
|
|
540
|
+
/*
|
|
541
|
+
* Fifth, free the return value and arguments
|
|
542
|
+
*/
|
|
543
|
+
|
|
544
|
+
if (!use_return_value)
|
|
545
|
+
FreeGIArgument(&return_type, &return_value_stack, return_transfer);
|
|
546
|
+
|
|
491
547
|
} else if (!use_return_value) {
|
|
492
|
-
|
|
548
|
+
|
|
549
|
+
// Value transferred to jsReturnValue
|
|
550
|
+
jsReturnValue = func->JsReturnValue (
|
|
493
551
|
info.This(),
|
|
494
552
|
&return_type,
|
|
495
|
-
|
|
496
|
-
callable_arg_values
|
|
553
|
+
&return_value_stack,
|
|
554
|
+
callable_arg_values,
|
|
555
|
+
return_transfer);
|
|
497
556
|
} else {
|
|
557
|
+
|
|
558
|
+
// Value returned in return_value
|
|
498
559
|
jsReturnValue = Nan::Undefined();
|
|
499
560
|
}
|
|
500
561
|
|
|
501
|
-
|
|
502
|
-
/*
|
|
503
|
-
* Fifth, free the return value and arguments
|
|
504
|
-
*/
|
|
505
|
-
|
|
506
|
-
if (!use_return_value)
|
|
507
|
-
FreeGIArgument(&return_type, &return_value_stack, return_transfer);
|
|
508
|
-
|
|
509
562
|
for (int i = 0; i < func->n_callable_args; i++) {
|
|
510
563
|
GIArgInfo arg_info = {};
|
|
511
564
|
GITypeInfo arg_type;
|
|
@@ -533,6 +586,11 @@ Local<Value> FunctionCall (
|
|
|
533
586
|
delete callback;
|
|
534
587
|
}
|
|
535
588
|
}
|
|
589
|
+
else if (IsTransferContainerInList (&arg_type, transfer, direction)) {
|
|
590
|
+
// The callee already freed the container structure; free only the
|
|
591
|
+
// captured (caller-owned) elements, never the freed container (#399).
|
|
592
|
+
FreeTransferContainerElements (&arg_type, param.data.v_pointer);
|
|
593
|
+
}
|
|
536
594
|
else {
|
|
537
595
|
if (direction == GI_DIRECTION_INOUT || (direction == GI_DIRECTION_OUT && !g_arg_info_is_caller_allocates (&arg_info)))
|
|
538
596
|
FreeGIArgument (&arg_type, (GIArgument*)arg_value.v_pointer, transfer, direction);
|
|
@@ -541,6 +599,11 @@ Local<Value> FunctionCall (
|
|
|
541
599
|
}
|
|
542
600
|
}
|
|
543
601
|
|
|
602
|
+
// If this method freed the instance, drop node-gtk's ownership of it so the
|
|
603
|
+
// GC finalizer won't free it a second time (#429).
|
|
604
|
+
if (func->frees_instance && !didThrow)
|
|
605
|
+
DisownBoxed (info.This());
|
|
606
|
+
|
|
544
607
|
#ifndef __linux__
|
|
545
608
|
delete[] total_arg_values;
|
|
546
609
|
#endif
|
|
@@ -553,11 +616,12 @@ Local<Value> FunctionCall (
|
|
|
553
616
|
* Creates the JS return value from the C arguments list
|
|
554
617
|
* @returns the JS return value
|
|
555
618
|
*/
|
|
556
|
-
Local<Value> FunctionInfo::
|
|
619
|
+
Local<Value> FunctionInfo::JsReturnValue (
|
|
557
620
|
Local<Value> self,
|
|
558
621
|
GITypeInfo* return_type,
|
|
559
622
|
GIArgument* return_value,
|
|
560
|
-
GIArgument* callable_arg_values
|
|
623
|
+
GIArgument* callable_arg_values,
|
|
624
|
+
GITransfer return_transfer) {
|
|
561
625
|
|
|
562
626
|
Local<Value> jsReturnValue;
|
|
563
627
|
int jsReturnIndex = 0;
|
|
@@ -591,7 +655,10 @@ Local<Value> FunctionInfo::GetReturnValue (
|
|
|
591
655
|
// When a method returns the instance itself, skip the conversion and just return the
|
|
592
656
|
// existent wrapper
|
|
593
657
|
bool isReturningSelf = is_method && PointerFromWrapper(self) == return_value->v_pointer;
|
|
594
|
-
ADD_RETURN (isReturningSelf ? self :
|
|
658
|
+
ADD_RETURN (isReturningSelf ? self :
|
|
659
|
+
GIArgumentToV8 (
|
|
660
|
+
return_type, return_value, length,
|
|
661
|
+
return_transfer == GI_TRANSFER_EVERYTHING ? kTransfer : kNone))
|
|
595
662
|
}
|
|
596
663
|
|
|
597
664
|
for (int i = 0; i < n_callable_args; i++) {
|
|
@@ -630,13 +697,15 @@ Local<Value> FunctionInfo::GetReturnValue (
|
|
|
630
697
|
ADD_RETURN (result)
|
|
631
698
|
|
|
632
699
|
} else if (param.type == ParameterType::kNORMAL) {
|
|
700
|
+
GITransfer transfer = g_arg_info_get_ownership_transfer(&arg_info);
|
|
701
|
+
ResourceOwnership ownership = transfer == GI_TRANSFER_EVERYTHING ? kTransfer : kNone;
|
|
633
702
|
|
|
634
703
|
if (IsPointerType(&arg_type) && g_arg_info_is_caller_allocates(&arg_info)) {
|
|
635
704
|
void *pointer = &arg_value.v_pointer;
|
|
636
|
-
ADD_RETURN (GIArgumentToV8(&arg_type, (GIArgument*) pointer))
|
|
705
|
+
ADD_RETURN (GIArgumentToV8(&arg_type, (GIArgument*) pointer, -1, ownership))
|
|
637
706
|
}
|
|
638
707
|
else {
|
|
639
|
-
ADD_RETURN (GIArgumentToV8(&arg_type, (GIArgument*) arg_value.v_pointer))
|
|
708
|
+
ADD_RETURN (GIArgumentToV8(&arg_type, (GIArgument*) arg_value.v_pointer, -1, ownership))
|
|
640
709
|
}
|
|
641
710
|
}
|
|
642
711
|
}
|
|
@@ -647,19 +716,6 @@ Local<Value> FunctionInfo::GetReturnValue (
|
|
|
647
716
|
return jsReturnValue;
|
|
648
717
|
}
|
|
649
718
|
|
|
650
|
-
/**
|
|
651
|
-
* Frees the C return value
|
|
652
|
-
* @param return_value the return value pointer
|
|
653
|
-
*/
|
|
654
|
-
void FunctionInfo::FreeReturnValue (GIArgument *return_value) {
|
|
655
|
-
GITypeInfo return_type;
|
|
656
|
-
g_callable_info_load_return_type(info, &return_type);
|
|
657
|
-
GITransfer return_transfer = g_callable_info_get_caller_owns(info);
|
|
658
|
-
|
|
659
|
-
FreeGIArgument(&return_type, return_value, return_transfer);
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
|
|
663
719
|
|
|
664
720
|
Local<Function> MakeFunction(GIBaseInfo *info) {
|
|
665
721
|
FunctionInfo *func = new FunctionInfo(info);
|
|
@@ -673,8 +729,8 @@ Local<Function> MakeFunction(GIBaseInfo *info) {
|
|
|
673
729
|
auto fn = Nan::GetFunction (tpl).ToLocalChecked();
|
|
674
730
|
fn->SetName(name);
|
|
675
731
|
|
|
676
|
-
Persistent<FunctionTemplate>
|
|
677
|
-
persistent
|
|
732
|
+
func->persistent = new Nan::Persistent<FunctionTemplate>(tpl);
|
|
733
|
+
func->persistent->SetWeak(func, FunctionDestroyed, WeakCallbackType::kParameter);
|
|
678
734
|
|
|
679
735
|
return fn;
|
|
680
736
|
}
|
|
@@ -691,8 +747,9 @@ void FunctionInvoker(const Nan::FunctionCallbackInfo<Value> &info) {
|
|
|
691
747
|
Callback::AsyncFree();
|
|
692
748
|
}
|
|
693
749
|
|
|
694
|
-
void FunctionDestroyed(const
|
|
750
|
+
void FunctionDestroyed(const Nan::WeakCallbackInfo<FunctionInfo> &data) {
|
|
695
751
|
FunctionInfo *func = data.GetParameter ();
|
|
752
|
+
delete func->persistent;
|
|
696
753
|
delete func;
|
|
697
754
|
}
|
|
698
755
|
|
package/src/function.h
CHANGED
|
@@ -33,6 +33,7 @@ struct FunctionInfo {
|
|
|
33
33
|
|
|
34
34
|
bool is_method;
|
|
35
35
|
bool can_throw;
|
|
36
|
+
bool frees_instance; /* a *_free/*_unref method that deallocates the instance (#429) */
|
|
36
37
|
|
|
37
38
|
int n_callable_args;
|
|
38
39
|
int n_total_args;
|
|
@@ -40,14 +41,14 @@ struct FunctionInfo {
|
|
|
40
41
|
int n_in_args;
|
|
41
42
|
|
|
42
43
|
Parameter* call_parameters;
|
|
44
|
+
Nan::Persistent<FunctionTemplate> *persistent;
|
|
43
45
|
|
|
44
46
|
FunctionInfo(GIBaseInfo* info);
|
|
45
47
|
~FunctionInfo();
|
|
46
48
|
|
|
47
49
|
bool Init();
|
|
48
50
|
bool TypeCheck (const Nan::FunctionCallbackInfo<Value> &info);
|
|
49
|
-
Local<Value>
|
|
50
|
-
void FreeReturnValue (GIArgument *return_value);
|
|
51
|
+
Local<Value> JsReturnValue (Local<Value> self, GITypeInfo* return_type, GIArgument* return_value, GIArgument* callable_arg_values, GITransfer return_transfer);
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
bool IsDestroyNotify (GIBaseInfo *info);
|
|
@@ -55,7 +56,7 @@ bool IsDestroyNotify (GIBaseInfo *info);
|
|
|
55
56
|
Local<Value> FunctionCall (FunctionInfo *func, const Nan::FunctionCallbackInfo<Value> &info, GIArgument *return_value = NULL, GError **error = NULL);
|
|
56
57
|
|
|
57
58
|
void FunctionInvoker (const Nan::FunctionCallbackInfo<Value> &info);
|
|
58
|
-
void FunctionDestroyed (const
|
|
59
|
+
void FunctionDestroyed (const Nan::WeakCallbackInfo<FunctionInfo> &data);
|
|
59
60
|
|
|
60
61
|
Local<Function> MakeFunction (GIBaseInfo *base_info);
|
|
61
62
|
|
package/src/gi.cc
CHANGED
|
@@ -208,6 +208,49 @@ NAN_METHOD(ObjectPropertySetter) {
|
|
|
208
208
|
RETURN(success.ToLocalChecked());
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
// All members of a C union live at offset 0. Some GLib versions (the
|
|
212
|
+
// regression fixed in 2.86.1 — glib#3745) emit a bogus 0xffff offset for union
|
|
213
|
+
// field members in the compiled typelib, so g_field_info_get_field /
|
|
214
|
+
// g_field_info_set_field would read/write far out of bounds and crash. Detect
|
|
215
|
+
// union fields so they can be accessed directly at offset 0 instead (#376).
|
|
216
|
+
static bool FieldIsInUnion (GIFieldInfo *field) {
|
|
217
|
+
GIBaseInfo *container = g_base_info_get_container (field);
|
|
218
|
+
return container != NULL
|
|
219
|
+
&& g_base_info_get_type (container) == GI_INFO_TYPE_UNION;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Whether a field type is a simple (non-pointer) C value that can be read or
|
|
223
|
+
// written by copying its bytes — mirrors what g_field_info_get/set_field
|
|
224
|
+
// accept. Pointer-backed types (strings, nested structs, arrays, ...) return
|
|
225
|
+
// false and are rejected, as before.
|
|
226
|
+
static bool IsSimpleFieldType (GITypeInfo *type_info) {
|
|
227
|
+
switch (g_type_info_get_tag (type_info)) {
|
|
228
|
+
case GI_TYPE_TAG_BOOLEAN:
|
|
229
|
+
case GI_TYPE_TAG_INT8:
|
|
230
|
+
case GI_TYPE_TAG_UINT8:
|
|
231
|
+
case GI_TYPE_TAG_INT16:
|
|
232
|
+
case GI_TYPE_TAG_UINT16:
|
|
233
|
+
case GI_TYPE_TAG_INT32:
|
|
234
|
+
case GI_TYPE_TAG_UINT32:
|
|
235
|
+
case GI_TYPE_TAG_INT64:
|
|
236
|
+
case GI_TYPE_TAG_UINT64:
|
|
237
|
+
case GI_TYPE_TAG_FLOAT:
|
|
238
|
+
case GI_TYPE_TAG_DOUBLE:
|
|
239
|
+
case GI_TYPE_TAG_UNICHAR:
|
|
240
|
+
case GI_TYPE_TAG_GTYPE:
|
|
241
|
+
return true;
|
|
242
|
+
case GI_TYPE_TAG_INTERFACE: {
|
|
243
|
+
GIBaseInfo *iface = g_type_info_get_interface (type_info);
|
|
244
|
+
GIInfoType itype = g_base_info_get_type (iface);
|
|
245
|
+
bool simple = (itype == GI_INFO_TYPE_ENUM || itype == GI_INFO_TYPE_FLAGS);
|
|
246
|
+
g_base_info_unref (iface);
|
|
247
|
+
return simple;
|
|
248
|
+
}
|
|
249
|
+
default:
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
211
254
|
NAN_METHOD(StructFieldSetter) {
|
|
212
255
|
Local<Object> boxedWrapper = info[0].As<Object>();
|
|
213
256
|
Local<Object> fieldInfo = info[1].As<Object>();
|
|
@@ -231,6 +274,17 @@ NAN_METHOD(StructFieldSetter) {
|
|
|
231
274
|
|
|
232
275
|
RETURN (Nan::Undefined());
|
|
233
276
|
|
|
277
|
+
} else if (FieldIsInUnion(field)) {
|
|
278
|
+
|
|
279
|
+
// Union members are at offset 0; write directly to avoid the bogus
|
|
280
|
+
// introspected offset (glib#3745, #376).
|
|
281
|
+
if (IsSimpleFieldType(field_type)) {
|
|
282
|
+
memcpy(boxed, &arg, GNodeJS::GetTypeSize(field_type));
|
|
283
|
+
} else {
|
|
284
|
+
Nan::ThrowError("Unable to set field (complex types not allowed)");
|
|
285
|
+
RETURN (Nan::Undefined());
|
|
286
|
+
}
|
|
287
|
+
|
|
234
288
|
} else {
|
|
235
289
|
|
|
236
290
|
if (g_field_info_set_field(field, boxed, &arg) == FALSE) {
|
|
@@ -283,9 +337,22 @@ NAN_METHOD(StructFieldGetter) {
|
|
|
283
337
|
}
|
|
284
338
|
|
|
285
339
|
GIArgument value;
|
|
286
|
-
|
|
340
|
+
GNodeJS::ResourceOwnership ownership = GNodeJS::kCopy;
|
|
287
341
|
BaseInfo typeInfo = g_field_info_get_type(*fieldInfo);
|
|
288
342
|
|
|
343
|
+
if (FieldIsInUnion(*fieldInfo)) {
|
|
344
|
+
// Union members are at offset 0; read directly to avoid the bogus
|
|
345
|
+
// introspected offset (glib#3745, #376).
|
|
346
|
+
if (!IsSimpleFieldType(*typeInfo)) {
|
|
347
|
+
Nan::ThrowError("Converting non-primitive fields is not allowed");
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
memset(&value, 0, sizeof(value));
|
|
351
|
+
memcpy(&value, boxed, GNodeJS::GetTypeSize(*typeInfo));
|
|
352
|
+
RETURN(GNodeJS::GIArgumentToV8(*typeInfo, &value, -1, ownership));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
289
356
|
if (!g_field_info_get_field(*fieldInfo, boxed, &value)) {
|
|
290
357
|
/* If g_field_info_get_field() failed, this is a non-primitive type */
|
|
291
358
|
|
|
@@ -300,13 +367,13 @@ NAN_METHOD(StructFieldGetter) {
|
|
|
300
367
|
// auto offset = g_field_info_get_offset(*fieldInfo);
|
|
301
368
|
// auto fieldPtr = G_STRUCT_MEMBER_P(boxed, offset);
|
|
302
369
|
// value.v_pointer = fieldPtr;
|
|
303
|
-
//
|
|
370
|
+
// ownership = kNone;
|
|
304
371
|
|
|
305
372
|
Nan::ThrowError("Converting non-primitive fields is not allowed");
|
|
306
373
|
return;
|
|
307
374
|
}
|
|
308
375
|
|
|
309
|
-
RETURN(GNodeJS::GIArgumentToV8(*typeInfo, &value, -1,
|
|
376
|
+
RETURN(GNodeJS::GIArgumentToV8(*typeInfo, &value, -1, ownership));
|
|
310
377
|
}
|
|
311
378
|
|
|
312
379
|
NAN_METHOD(StartLoop) {
|