@@ -354,7 +354,7 @@ long GIArgumentToLength(GITypeInfo *type_info, GIArgument *arg, bool is_pointer)
354354}
355355
356356
357- GArray * V8ToGArray (GITypeInfo *type_info, Local<Value> value) {
357+ GArray * V8ToGArray (GITypeInfo *type_info, Local<Value> value, GITransfer transfer ) {
358358 GArray* g_array = NULL ;
359359 bool zero_terminated = g_type_info_is_zero_terminated (type_info);
360360
@@ -382,8 +382,10 @@ GArray * V8ToGArray(GITypeInfo *type_info, Local<Value> value) {
382382 for (int i = 0 ; i < length; i++) {
383383 auto value = Nan::Get (array, i).ToLocalChecked ();
384384 GIArgument arg;
385+ GITransfer inner_transfer =
386+ (transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer);
385387
386- if (V8ToGIArgument (element_info, &arg, value, true )) {
388+ if (V8ToGIArgument (element_info, &arg, value, true , inner_transfer )) {
387389 g_array_append_val (g_array, arg);
388390 } else {
389391 g_warning (" V8ToGArray: couldnt convert value: %s" ,
@@ -399,7 +401,7 @@ GArray * V8ToGArray(GITypeInfo *type_info, Local<Value> value) {
399401 return g_array;
400402}
401403
402- static void *V8ArrayToCArray (GITypeInfo *type_info, Local<Value> value) {
404+ static void *V8ArrayToCArray (GITypeInfo *type_info, Local<Value> value, GITransfer transfer ) {
403405 auto array = Local<Array>::Cast (TO_OBJECT (value));
404406 int length = array->Length ();
405407
@@ -413,8 +415,10 @@ static void *V8ArrayToCArray(GITypeInfo *type_info, Local<Value> value) {
413415 auto value = Nan::Get (array, i).ToLocalChecked ();
414416
415417 GIArgument arg;
418+ GITransfer inner_transfer =
419+ (transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer);
416420
417- if (V8ToGIArgument (element_info, &arg, value, true )) {
421+ if (V8ToGIArgument (element_info, &arg, value, true , inner_transfer )) {
418422 void * pointer = (void *)((ulong)result + i * element_size);
419423 memcpy (pointer, &arg, element_size);
420424 } else {
@@ -453,15 +457,15 @@ static void *V8TypedArrayToCArray(GITypeInfo *type_info, Local<Value> value) {
453457 return result;
454458}
455459
456- void *V8ToCArray (GITypeInfo *type_info, Local<Value> value) {
460+ void *V8ToCArray (GITypeInfo *type_info, Local<Value> value, GITransfer transfer ) {
457461 if (value->IsString ()) {
458462 Local<String> string = TO_STRING (value);
459463 const char *utf8_data = *Nan::Utf8String (string);
460464 return g_strdup (utf8_data);
461465 }
462466
463467 if (value->IsArray ()) {
464- return V8ArrayToCArray (type_info, value);
468+ return V8ArrayToCArray (type_info, value, transfer );
465469 }
466470
467471 if (value->IsTypedArray ()) {
@@ -473,7 +477,7 @@ void *V8ToCArray(GITypeInfo *type_info, Local<Value> value) {
473477 return NULL ;
474478}
475479
476- gpointer V8ToGList (GITypeInfo *type_info, Local<Value> value) {
480+ gpointer V8ToGList (GITypeInfo *type_info, Local<Value> value, GITransfer transfer ) {
477481
478482 // FIXME can @value be null?
479483 if (!value->IsArray ()) {
@@ -504,7 +508,10 @@ gpointer V8ToGList (GITypeInfo *type_info, Local<Value> value) {
504508 GIArgument arg;
505509 Local<Value> value = Nan::Get (array, i).ToLocalChecked ();
506510
507- if (!V8ToGIArgument (element_info, &arg, value, false )) {
511+ GITransfer inner_transfer =
512+ (transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer);
513+
514+ if (!V8ToGIArgument (element_info, &arg, value, false , inner_transfer)) {
508515 g_warning (" V8ToGList: couldnt convert value #%i to GIArgument" , i);
509516 continue ;
510517 }
@@ -526,7 +533,7 @@ gpointer V8ToGList (GITypeInfo *type_info, Local<Value> value) {
526533 return list;
527534}
528535
529- gpointer V8ToGHash (GITypeInfo *type_info, Local<Value> value) {
536+ gpointer V8ToGHash (GITypeInfo *type_info, Local<Value> value, GITransfer transfer ) {
530537
531538 if (!value->IsObject ()) {
532539 Nan::ThrowTypeError (" Expected object" );
@@ -587,21 +594,24 @@ gpointer V8ToGHash (GITypeInfo *type_info, Local<Value> value) {
587594 auto object = TO_OBJECT (value);
588595 auto keys = Nan::GetOwnPropertyNames (object).ToLocalChecked ();
589596
597+ GITransfer inner_transfer =
598+ (transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer);
599+
590600 for (uint32_t i = 0 ; i < keys->Length (); i++) {
591601 auto key = Nan::Get (keys, i).ToLocalChecked ();
592602 auto value = Nan::Get (object, key).ToLocalChecked ();
593603
594604 GIArgument key_arg;
595605 GIArgument value_arg;
596606
597- if (!V8ToGIArgument (key_type_info, &key_arg, key, false )) {
607+ if (!V8ToGIArgument (key_type_info, &key_arg, key, false , inner_transfer )) {
598608 char * message = g_strdup_printf (" Couldn't convert key '%s'" , *Nan::Utf8String (key));
599609 Nan::ThrowError (message);
600610 free (message);
601611 goto item_error;
602612 }
603613
604- if (!V8ToGIArgument (value_type_info, &value_arg, value, false )) {
614+ if (!V8ToGIArgument (value_type_info, &value_arg, value, false , inner_transfer )) {
605615 char * message = g_strdup_printf (" Couldn't convert value for key '%s'" , *Nan::Utf8String (key));
606616 Nan::ThrowError (message);
607617 free (message);
@@ -614,7 +624,7 @@ gpointer V8ToGHash (GITypeInfo *type_info, Local<Value> value) {
614624
615625item_error:
616626 /* Free everything we have converted so far. */
617- FreeGIArgument (type_info, (GIArgument *) &hash_table, GI_TRANSFER_NOTHING , GI_DIRECTION_IN);
627+ FreeGIArgument (type_info, (GIArgument *) &hash_table, transfer , GI_DIRECTION_IN);
618628 hash_table = NULL ;
619629 break ;
620630 }
@@ -625,14 +635,30 @@ gpointer V8ToGHash (GITypeInfo *type_info, Local<Value> value) {
625635 return hash_table;
626636}
627637
628- bool V8ToGIArgument (GIBaseInfo *gi_info, GIArgument *arg, Local<Value> value) {
638+ bool V8ToGIArgument (GIBaseInfo *gi_info, GIArgument *arg, Local<Value> value, GITransfer transfer ) {
629639 GIInfoType type = g_base_info_get_type (gi_info);
630640
631641 switch (type) {
632642 case GI_INFO_TYPE_BOXED:
633643 case GI_INFO_TYPE_STRUCT:
634644 case GI_INFO_TYPE_UNION:
635645 arg->v_pointer = PointerFromWrapper (value);
646+ if (transfer == GI_TRANSFER_EVERYTHING) {
647+ GType gtype = g_registered_type_info_get_g_type (gi_info);
648+ size_t size;
649+
650+ if (gtype != G_TYPE_NONE) {
651+ arg->v_pointer = g_boxed_copy (gtype, arg->v_pointer );
652+ } else if ((size = Boxed::GetSize (gi_info)) != 0 ) {
653+ void *boxedCopy = malloc (size);
654+ memcpy (boxedCopy, arg->v_pointer , size);
655+ arg->v_pointer = boxedCopy;
656+ } else {
657+ // XXX what else can we do? Should we just abort?
658+ WARN (" Cannot copy a boxed object of type '%s'; memory corruption might occur." ,
659+ g_base_info_get_name (gi_info));
660+ }
661+ }
636662 break ;
637663
638664 case GI_INFO_TYPE_FLAGS:
@@ -652,6 +678,8 @@ bool V8ToGIArgument(GIBaseInfo *gi_info, GIArgument *arg, Local<Value> value) {
652678 }
653679 case GI_INFO_TYPE_INTERFACE:
654680 arg->v_pointer = GObjectFromWrapper (value);
681+ if (transfer == GI_TRANSFER_EVERYTHING)
682+ g_object_ref (arg->v_pointer );
655683 break ;
656684
657685 case GI_INFO_TYPE_CALLBACK:
@@ -662,7 +690,7 @@ bool V8ToGIArgument(GIBaseInfo *gi_info, GIArgument *arg, Local<Value> value) {
662690 return true ;
663691}
664692
665- bool V8ToGIArgument (GITypeInfo *type_info, GIArgument *arg, Local<Value> value, bool may_be_null) {
693+ bool V8ToGIArgument (GITypeInfo *type_info, GIArgument *arg, Local<Value> value, bool may_be_null, GITransfer transfer ) {
666694 GITypeTag type_tag = g_type_info_get_tag (type_info);
667695
668696 if (value->IsUndefined () || value->IsNull ()) {
@@ -680,6 +708,7 @@ bool V8ToGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> value,
680708 case GI_TYPE_TAG_VOID:
681709 if (g_type_info_is_pointer (type_info)) {
682710 arg->v_pointer = PointerFromWrapper (value);
711+ // XXX what to do with GI_TRANSFER_EVERYTHING
683712 break ;
684713 }
685714 arg->v_pointer = NULL ;
@@ -744,11 +773,11 @@ bool V8ToGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> value,
744773
745774 switch (array_type) {
746775 case GI_ARRAY_TYPE_C:
747- arg->v_pointer = V8ToCArray (type_info, value);
776+ arg->v_pointer = V8ToCArray (type_info, value, transfer );
748777 break ;
749778 case GI_ARRAY_TYPE_ARRAY:
750779 case GI_ARRAY_TYPE_BYTE_ARRAY:
751- arg->v_pointer = V8ToGArray (type_info, value);
780+ arg->v_pointer = V8ToGArray (type_info, value, transfer );
752781 break ;
753782 case GI_ARRAY_TYPE_PTR_ARRAY:
754783 default :
@@ -761,21 +790,21 @@ bool V8ToGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> value,
761790 case GI_TYPE_TAG_INTERFACE:
762791 {
763792 GIBaseInfo *interface_info = g_type_info_get_interface (type_info);
764- V8ToGIArgument (interface_info, arg, value);
793+ V8ToGIArgument (interface_info, arg, value, transfer );
765794 g_base_info_unref (interface_info);
766795 }
767796 break ;
768797
769798 case GI_TYPE_TAG_GLIST:
770799 case GI_TYPE_TAG_GSLIST:
771800 {
772- arg->v_pointer = V8ToGList (type_info, value);
801+ arg->v_pointer = V8ToGList (type_info, value, transfer );
773802 }
774803 break ;
775804
776805 case GI_TYPE_TAG_GHASH:
777806 {
778- arg->v_pointer = V8ToGHash (type_info, value);
807+ arg->v_pointer = V8ToGHash (type_info, value, transfer );
779808 }
780809 break ;
781810
0 commit comments