1 /* -*- mode: C; indent-tabs-mode: t; tab-width: 8; c-basic-offset: 2; -*- */
4 * This file is part of Seed, the GObject Introspection<->Javascript bindings.
6 * Seed is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 * Seed is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with Seed. If not, see <http://www.gnu.org/licenses/>.
17 * Copyright (C) Robert Carr 2009 <carrr@rpi.edu>
20 #include "seed-private.h"
24 JSClassRef gobject_class;
25 JSClassRef gobject_method_class;
26 JSClassRef gobject_constructor_class;
27 JSClassRef seed_callback_class;
28 JSClassRef gobject_init_method_class;
32 seed_value_is_gobject (JSContextRef ctx, JSValueRef value)
34 if (!JSValueIsObject (ctx, value) || JSValueIsNull (ctx, value))
37 return JSValueIsObjectOfClass (ctx, value, gobject_class);
41 seed_toggle_ref (gpointer data, GObject * object, gboolean is_last_ref)
45 if (!g_object_get_data (object, "js-ref"))
48 wrapper = (JSValueRef) data;
52 JSValueUnprotect (eng->context, wrapper);
56 JSValueProtect (eng->context, wrapper);
61 seed_gobject_destroyed (gpointer object)
63 JSValueUnprotect (eng->context, (JSValueRef) object);
64 JSObjectSetPrivate ((JSObjectRef) object, 0);
68 seed_make_wrapper_for_type (JSContextRef ctx, GType type)
74 class = seed_gobject_get_class_for_gtype (ctx, type);
76 while (!class && (type = g_type_parent (type)))
77 class = seed_gobject_get_class_for_gtype (ctx, type);
79 prototype = seed_gobject_get_prototype_for_gtype (type);
80 ret = JSObjectMake (ctx, class, NULL);
82 JSObjectSetPrototype (ctx, ret, prototype);
84 g_assert_not_reached ();
90 seed_wrap_object (JSContextRef ctx, GObject * object)
96 type = G_OBJECT_TYPE (object);
98 user_data = (JSValueRef) g_object_get_qdata (object, js_ref_quark);
103 if (pthread_getspecific(seed_next_gobject_wrapper_key))
104 js_ref = pthread_getspecific(seed_next_gobject_wrapper_key);
106 js_ref = seed_make_wrapper_for_type (ctx, type);
108 JSObjectSetPrivate (js_ref, object);
110 g_object_set_qdata_full (object, js_ref_quark, (gpointer) js_ref,
111 seed_gobject_destroyed);
113 JSValueProtect (eng->context, js_ref);
114 g_object_add_toggle_ref (object, seed_toggle_ref, (gpointer) js_ref);
116 seed_add_signals_to_object (ctx, js_ref, object);
118 pthread_setspecific(seed_next_gobject_wrapper_key, NULL);
124 seed_release_arg (GITransfer transfer,
125 GITypeInfo * type_info, GITypeTag type_tag, GArgument * arg)
128 GITypeInfo *param_type;
129 GIBaseInfo *interface_info;
134 case GI_TYPE_TAG_UTF8:
135 case GI_TYPE_TAG_FILENAME:
136 g_free (arg->v_string);
138 case GI_TYPE_TAG_ARRAY:
141 param_type = g_type_info_get_param_type (type_info, 0);
143 switch (g_type_info_get_tag (param_type))
145 case GI_TYPE_TAG_UTF8:
146 if (transfer == GI_TRANSFER_EVERYTHING)
147 g_strfreev (arg->v_pointer);
148 else if (transfer == GI_TRANSFER_CONTAINER)
149 g_free (arg->v_pointer);
151 case GI_TYPE_TAG_GTYPE:
152 case GI_TYPE_TAG_FLOAT:
153 case GI_TYPE_TAG_UINT8:
154 g_free (arg->v_pointer);
156 case GI_TYPE_TAG_INTERFACE:
159 g_assert_not_reached ();
162 g_base_info_unref ((GIBaseInfo *) param_type);
165 case GI_TYPE_TAG_INTERFACE:
169 interface_info = g_type_info_get_interface (type_info);
172 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
175 if (g_type_is_a (gtype, G_TYPE_OBJECT)
176 || g_type_is_a (gtype, G_TYPE_INTERFACE))
179 "Unreffing object of type: %s in"
180 "argument release. Reference count: %d\n",
181 g_type_name (G_OBJECT_TYPE
182 (G_OBJECT (arg->v_pointer))),
183 G_OBJECT (arg->v_pointer)->ref_count);
184 g_object_unref (G_OBJECT (arg->v_pointer));
186 else if (g_type_is_a (gtype, G_TYPE_VALUE))
188 gval = (GValue *) arg->v_pointer;
189 // Free/unref the GValue's contents.
190 g_value_unset (gval);
192 g_slice_free1 (sizeof (GValue), gval);
194 else if (g_type_is_a (gtype, G_TYPE_CLOSURE))
196 g_closure_unref (arg->v_pointer);
199 g_base_info_unref (interface_info);
212 seed_gi_release_arg (GITransfer transfer,
213 GITypeInfo * type_info, GArgument * arg)
217 if (transfer == GI_TRANSFER_NOTHING)
220 type_tag = g_type_info_get_tag ((GITypeInfo *) type_info);
222 return seed_release_arg (transfer, type_info, type_tag, arg);
226 seed_gi_release_in_arg (GITransfer transfer,
227 GITypeInfo * type_info, GArgument * arg)
231 if (transfer == GI_TRANSFER_EVERYTHING)
234 type_tag = g_type_info_get_tag ((GITypeInfo *) type_info);
238 // TODO: FIXME: Leaaaks?
239 case GI_TYPE_TAG_INTERFACE:
241 // TODO: FIXME: Need some safe way to look for GClosure.
244 case GI_TYPE_TAG_UTF8:
245 case GI_TYPE_TAG_FILENAME:
246 case GI_TYPE_TAG_ARRAY:
247 return seed_release_arg (GI_TRANSFER_EVERYTHING,
248 type_info, type_tag, arg);
257 seed_gi_make_jsarray (JSContextRef ctx,
259 GITypeInfo * param_type, JSValueRef * exception)
261 GITypeTag element_type;
262 JSValueRef *elements;
264 gchar **str_array = (gchar **) array;
265 JSValueRef ret = JSValueMakeNull (ctx);
267 element_type = g_type_info_get_tag (param_type);
269 if (element_type == GI_TYPE_TAG_UTF8)
272 length = g_strv_length (str_array);
276 elements = g_alloca (sizeof (JSValueRef) * length);
277 for (i = 0; i < length; ++i)
279 elements[i] = seed_value_from_string (ctx, str_array[i], exception);
282 ret = (JSValueRef) JSObjectMakeArray (ctx, length, elements, exception);
285 if (element_type == GI_TYPE_TAG_GTYPE)
287 GType* ptr = (GType*)array;
289 while (ptr[length]) length++;
291 elements = g_alloca (sizeof (JSValueRef) * length);
293 for (i = 0; i < length; ++i)
294 elements[i] = seed_value_from_int (ctx, ptr[i], exception);
296 return (JSValueRef) JSObjectMakeArray (ctx, length, elements, exception);
304 seed_gi_make_array (JSContextRef ctx,
307 GITypeInfo * param_type,
308 void **array_p, JSValueRef * exception)
310 GITypeTag element_type;
314 element_type = g_type_info_get_tag (param_type);
316 switch (element_type)
318 case GI_TYPE_TAG_UTF8:
320 gchar **strresult = g_new0 (gchar *, length + 1);
322 for (i = 0; i < length; i++)
324 elem = JSObjectGetPropertyAtIndex (ctx,
327 strresult[i] = seed_value_to_string (ctx, elem, exception);
330 *array_p = strresult;
333 case GI_TYPE_TAG_GTYPE:
337 typeresult = g_new0 (GType, length + 1);
339 for (i = 0; i < length; i++)
341 elem = JSObjectGetPropertyAtIndex (ctx,
344 typeresult[i] = seed_value_to_int (ctx, elem, exception);
347 *array_p = typeresult;
350 case GI_TYPE_TAG_FLOAT:
354 floatresult = g_new0 (gfloat, length + 1);
356 for (i = 0; i < length; i++)
358 elem = JSObjectGetPropertyAtIndex (ctx,
361 floatresult[i] = seed_value_to_float (ctx, elem, exception);
364 *array_p = floatresult;
367 case GI_TYPE_TAG_DOUBLE:
371 dblresult = g_new0 (gdouble, length + 1);
373 for (i = 0; i < length; i++)
375 elem = JSObjectGetPropertyAtIndex (ctx,
378 dblresult[i] = seed_value_to_double (ctx, elem, exception);
381 *array_p = dblresult;
384 case GI_TYPE_TAG_INT:
388 intresult = g_new0 (gint, length + 1);
390 for (i = 0; i < length; i++)
392 elem = JSObjectGetPropertyAtIndex (ctx,
395 intresult[i] = seed_value_to_int (ctx, elem, exception);
398 *array_p = intresult;
401 case GI_TYPE_TAG_UINT8:
403 guint8 *guint8result;
405 guint8result = g_new0 (guint8, length + 1);
407 for (i = 0; i < length; i++)
409 elem = JSObjectGetPropertyAtIndex (ctx,
412 guint8result[i] = seed_value_to_uchar (ctx, elem, exception);
415 *array_p = guint8result;
418 case GI_TYPE_TAG_INTERFACE:
420 GIBaseInfo *interface = g_type_info_get_interface (param_type);
421 GIInfoType interface_type = g_base_info_get_type (interface);
422 if (interface_type == GI_INFO_TYPE_OBJECT
423 || interface_type == GI_INFO_TYPE_INTERFACE
424 || interface_type == GI_INFO_TYPE_STRUCT)
427 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
429 if (g_type_is_a (type, G_TYPE_VALUE))
433 // TODO:FIXME: Robb. Valgrind thinks there's a leak here,
434 // at least while running Same Seed.
435 gvalresult = g_new0 (GValue, length + 1);
437 for (i = 0; i < length; i++)
439 elem = JSObjectGetPropertyAtIndex (ctx,
442 seed_gvalue_from_seed_value (ctx, elem,
444 &gvalresult[i], exception);
446 *array_p = gvalresult;
448 g_base_info_unref (interface);
453 g_base_info_unref (interface);
456 seed_make_exception (ctx, exception, "ArgumentError",
457 "Unhandled array element type");
465 seed_gi_make_argument (JSContextRef ctx,
467 GITypeInfo * type_info,
469 JSValueRef * exception)
471 GITypeTag gi_tag = g_type_info_get_tag (type_info);
473 // FIXME: Some types are not "nullable", also need to check if argument
474 // can be null before doing this.
475 if (!value || JSValueIsNull (ctx, value))
483 case GI_TYPE_TAG_VOID:
484 // things like gio.outputstream.write use void pointers
485 if (g_type_info_is_pointer (type_info))
486 arg->v_string = seed_value_to_string (ctx, value, exception);
489 case GI_TYPE_TAG_BOOLEAN:
490 arg->v_boolean = seed_value_to_boolean (ctx, value, exception);
492 case GI_TYPE_TAG_INT8:
493 arg->v_int8 = seed_value_to_char (ctx, value, exception);
495 case GI_TYPE_TAG_UINT8:
496 arg->v_uint8 = seed_value_to_uchar (ctx, value, exception);
498 case GI_TYPE_TAG_INT16:
499 arg->v_int16 = seed_value_to_int (ctx, value, exception);
501 case GI_TYPE_TAG_UINT16:
502 arg->v_uint16 = seed_value_to_uint (ctx, value, exception);
504 case GI_TYPE_TAG_INT32:
505 arg->v_int32 = seed_value_to_int (ctx, value, exception);
507 case GI_TYPE_TAG_UINT32:
508 arg->v_uint32 = seed_value_to_uint (ctx, value, exception);
510 case GI_TYPE_TAG_LONG:
511 arg->v_long = seed_value_to_long (ctx, value, exception);
513 case GI_TYPE_TAG_INT64:
514 arg->v_int64 = seed_value_to_int64 (ctx, value, exception);
516 case GI_TYPE_TAG_ULONG:
517 arg->v_ulong = seed_value_to_ulong (ctx, value, exception);
519 case GI_TYPE_TAG_UINT64:
520 arg->v_uint64 = seed_value_to_uint64 (ctx, value, exception);
522 case GI_TYPE_TAG_INT:
523 arg->v_int = seed_value_to_int (ctx, value, exception);
525 case GI_TYPE_TAG_UINT:
526 arg->v_uint = seed_value_to_uint (ctx, value, exception);
528 case GI_TYPE_TAG_SIZE:
529 arg->v_size = seed_value_to_size (ctx, value, exception);
531 case GI_TYPE_TAG_SSIZE:
532 arg->v_ssize = seed_value_to_ssize (ctx, value, exception);
534 case GI_TYPE_TAG_FLOAT:
535 arg->v_float = seed_value_to_float (ctx, value, exception);
537 case GI_TYPE_TAG_DOUBLE:
538 arg->v_double = seed_value_to_double (ctx, value, exception);
540 case GI_TYPE_TAG_UTF8:
541 arg->v_string = seed_value_to_string (ctx, value, exception);
543 case GI_TYPE_TAG_FILENAME:
544 arg->v_string = seed_value_to_filename (ctx, value, exception);
546 case GI_TYPE_TAG_GTYPE:
547 arg->v_int = seed_value_to_int (ctx, value, exception);
549 case GI_TYPE_TAG_TIME_T:
550 arg->v_long = seed_value_to_time_t (ctx, value, exception);
552 case GI_TYPE_TAG_INTERFACE:
554 GIBaseInfo *interface;
555 GIInfoType interface_type;
556 GType required_gtype;
559 interface = g_type_info_get_interface (type_info);
560 interface_type = g_base_info_get_type (interface);
562 arg->v_pointer = NULL;
564 if (interface_type == GI_INFO_TYPE_OBJECT ||
565 interface_type == GI_INFO_TYPE_INTERFACE)
567 gobject = seed_value_to_object (ctx, value, exception);
569 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
572 // FIXME: Not clear if the g_type_is_a check is desired here.
573 // Possibly 'breaks things' when we don't have introspection
574 // data for some things in an interface hierarchy. Hasn't
575 // provided any problems so far.
577 || !g_type_is_a (G_OBJECT_TYPE (gobject), required_gtype))
579 g_base_info_unref (interface);
583 arg->v_pointer = gobject;
584 g_base_info_unref (interface);
587 else if (interface_type == GI_INFO_TYPE_ENUM ||
588 interface_type == GI_INFO_TYPE_FLAGS)
590 arg->v_long = seed_value_to_long (ctx, value, exception);
591 if (!(interface_type == GI_INFO_TYPE_FLAGS)
592 && !seed_validate_enum ((GIEnumInfo *) interface,
595 seed_make_exception (ctx, exception, "EnumRange",
596 "Enum value: %ld is out of range",
598 g_base_info_unref (interface);
603 g_base_info_unref (interface);
606 else if (interface_type == GI_INFO_TYPE_STRUCT ||
607 interface_type == GI_INFO_TYPE_UNION)
609 if (JSValueIsObjectOfClass (ctx, value, seed_struct_class))
610 arg->v_pointer = seed_pointer_get_pointer (ctx, value);
611 else if (JSValueIsObjectOfClass (ctx, value, seed_union_class))
612 arg->v_pointer = seed_pointer_get_pointer (ctx, value);
616 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo
620 g_base_info_unref (interface);
623 else if (type == G_TYPE_VALUE)
625 GValue *gval = g_slice_alloc0 (sizeof (GValue));
626 seed_gvalue_from_seed_value (ctx,
630 arg->v_pointer = gval;
632 g_base_info_unref (interface);
635 // Automatically convert between functions and
636 // GClosures where expected.
637 else if (g_type_is_a (type, G_TYPE_CLOSURE))
639 if (JSObjectIsFunction (ctx, (JSObjectRef) value))
642 seed_closure_new (ctx, (JSObjectRef) value, NULL,
649 seed_construct_struct_type_with_parameters (ctx,
653 arg->v_pointer = seed_pointer_get_pointer (ctx, strukt);
656 g_base_info_unref (interface);
659 else if (interface_type == GI_INFO_TYPE_CALLBACK)
661 if (JSValueIsNull (ctx, value))
663 arg->v_pointer = NULL;
664 g_base_info_unref (interface);
667 // Someone passes in a wrapper around a method where a
668 // callback is expected, i.e Clutter.sine_inc_func, as an alpha
669 // Have to dlsym the symbol to be able to do this.
670 // NOTE: Some cases where dlsym(NULL, symbol) doesn't work depending
671 // On how libseed is loaded.
672 else if (JSValueIsObjectOfClass (ctx,
673 value, gobject_method_class))
675 GIFunctionInfo *info =
676 JSObjectGetPrivate ((JSObjectRef) value);
677 const gchar *symbol = g_function_info_get_symbol (info);
682 fp = (void *) dlsym (0, symbol);
683 if ((error = dlerror ()) != NULL)
685 g_critical ("dlerror: %s \n", error);
690 g_base_info_unref (interface);
694 // Somewhat deprecated from when it was necessary to manually
695 // create closure objects...
696 else if (JSValueIsObjectOfClass (ctx,
698 seed_native_callback_class))
700 SeedNativeClosure *privates =
701 (SeedNativeClosure *)
702 JSObjectGetPrivate ((JSObjectRef) value);
703 arg->v_pointer = privates->closure;
704 g_base_info_unref (interface);
707 // Automagically create closure around function passed in as
709 else if (JSObjectIsFunction (ctx, (JSObjectRef) value))
711 SeedNativeClosure *privates = seed_make_native_closure (ctx,
712 (GICallableInfo *) interface,
714 arg->v_pointer = privates->closure;
715 g_base_info_unref (interface);
721 case GI_TYPE_TAG_ARRAY:
723 if (JSValueIsNull (ctx, value))
725 arg->v_pointer = NULL;
728 else if (!JSValueIsObject (ctx, value))
730 // TODO: FIXME: Is this right?
735 GITypeInfo *param_type;
736 //TODO: FIXME: Better array test like the cool one on reddit.
738 seed_value_to_int (ctx, seed_object_get_property (ctx,
745 arg->v_pointer = NULL;
749 param_type = g_type_info_get_param_type (type_info, 0);
750 if (!seed_gi_make_array (ctx, value, length, param_type,
751 &arg->v_pointer, exception))
753 g_base_info_unref ((GIBaseInfo *) param_type);
756 g_base_info_unref ((GIBaseInfo *) param_type);
769 seed_gi_argument_make_js (JSContextRef ctx,
770 GArgument * arg, GITypeInfo * type_info,
771 JSValueRef * exception)
773 GITypeTag gi_tag = g_type_info_get_tag (type_info);
776 case GI_TYPE_TAG_VOID:
777 return JSValueMakeUndefined (ctx);
778 case GI_TYPE_TAG_BOOLEAN:
779 return seed_value_from_boolean (ctx, arg->v_boolean, exception);
780 case GI_TYPE_TAG_INT8:
781 return seed_value_from_char (ctx, arg->v_int8, exception);
782 case GI_TYPE_TAG_UINT8:
783 return seed_value_from_uchar (ctx, arg->v_uint8, exception);
784 case GI_TYPE_TAG_INT16:
785 return seed_value_from_int (ctx, arg->v_int16, exception);
786 case GI_TYPE_TAG_UINT16:
787 return seed_value_from_uint (ctx, arg->v_uint16, exception);
788 case GI_TYPE_TAG_INT32:
789 return seed_value_from_int (ctx, arg->v_int32, exception);
790 case GI_TYPE_TAG_UINT32:
791 return seed_value_from_uint (ctx, arg->v_uint32, exception);
792 case GI_TYPE_TAG_LONG:
793 return seed_value_from_long (ctx, arg->v_long, exception);
794 case GI_TYPE_TAG_INT64:
795 return seed_value_from_int64 (ctx, arg->v_int64, exception);
796 case GI_TYPE_TAG_ULONG:
797 return seed_value_from_ulong (ctx, arg->v_ulong, exception);
798 case GI_TYPE_TAG_UINT64:
799 return seed_value_from_uint64 (ctx, arg->v_uint64, exception);
800 case GI_TYPE_TAG_INT:
801 return seed_value_from_int (ctx, arg->v_int32, exception);
802 case GI_TYPE_TAG_UINT:
803 return seed_value_from_uint (ctx, arg->v_uint32, exception);
804 case GI_TYPE_TAG_SSIZE:
805 return seed_value_from_ssize (ctx, arg->v_ssize, exception);
806 case GI_TYPE_TAG_SIZE:
807 return seed_value_from_size (ctx, arg->v_size, exception);
808 case GI_TYPE_TAG_FLOAT:
809 return seed_value_from_float (ctx, arg->v_float, exception);
810 case GI_TYPE_TAG_DOUBLE:
811 return seed_value_from_double (ctx, arg->v_double, exception);
812 case GI_TYPE_TAG_UTF8:
813 return seed_value_from_string (ctx, arg->v_string, exception);
814 case GI_TYPE_TAG_FILENAME:
815 return seed_value_from_filename (ctx, arg->v_string, exception);
816 case GI_TYPE_TAG_GTYPE:
817 return seed_value_from_int (ctx, arg->v_int, exception);
818 case GI_TYPE_TAG_TIME_T:
819 return seed_value_from_time_t (ctx, arg->v_long, exception);
820 case GI_TYPE_TAG_ARRAY:
822 GITypeInfo *param_type;
825 if (arg->v_pointer == NULL)
826 return JSValueMakeNull (ctx);
827 if (!g_type_info_is_zero_terminated (type_info))
830 param_type = g_type_info_get_param_type (type_info, 0);
832 ret = seed_gi_make_jsarray (ctx, arg->v_pointer, param_type,
835 g_base_info_unref ((GIBaseInfo *) param_type);
839 case GI_TYPE_TAG_INTERFACE:
841 GIBaseInfo *interface;
842 GIInfoType interface_type;
844 interface = g_type_info_get_interface (type_info);
845 interface_type = g_base_info_get_type (interface);
847 if (interface_type == GI_INFO_TYPE_OBJECT ||
848 interface_type == GI_INFO_TYPE_INTERFACE)
850 if (arg->v_pointer == 0)
852 g_base_info_unref (interface);
853 return JSValueMakeNull (ctx);
855 g_base_info_unref (interface);
856 return seed_value_from_object (ctx, arg->v_pointer, exception);
858 else if (interface_type == GI_INFO_TYPE_ENUM
859 || interface_type == GI_INFO_TYPE_FLAGS)
861 g_base_info_unref (interface);
862 return seed_value_from_long (ctx, arg->v_long, exception);
864 else if (interface_type == GI_INFO_TYPE_STRUCT)
868 strukt = seed_make_struct (ctx, arg->v_pointer, interface);
869 g_base_info_unref (interface);
874 case GI_TYPE_TAG_GLIST:
876 GITypeInfo *list_type;
880 GList *list = arg->v_pointer;
882 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
883 list_type = g_type_info_get_param_type (type_info, 0);
885 for (; list != NULL; list = list->next)
889 larg.v_pointer = list->data;
891 (JSValueRef) seed_gi_argument_make_js (ctx, &larg,
892 list_type, exception);
894 ival = JSValueMakeNull (ctx);
895 JSObjectSetPropertyAtIndex (ctx, ret, i, ival, NULL);
901 case GI_TYPE_TAG_GSLIST:
903 GITypeInfo *list_type;
908 GSList *list = arg->v_pointer;
910 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
911 list_type = g_type_info_get_param_type (type_info, 0);
913 for (; list != NULL; list = list->next)
915 larg.v_pointer = list->data;
917 (JSValueRef) seed_gi_argument_make_js (ctx, &larg,
918 list_type, exception);
920 ival = JSValueMakeNull (ctx);
921 JSObjectSetPropertyAtIndex (ctx, ret, i, ival, NULL);
926 case GI_TYPE_TAG_ERROR:
929 seed_make_exception_from_gerror (ctx, &ret, (GError*) arg->v_pointer);
941 seed_value_from_gvalue (JSContextRef ctx,
942 GValue * gval, JSValueRef * exception)
944 if (!G_IS_VALUE (gval))
948 switch (G_VALUE_TYPE (gval))
951 return seed_value_from_boolean (ctx,
952 g_value_get_boolean (gval), exception);
954 return seed_value_from_char (ctx, g_value_get_char (gval), exception);
956 return seed_value_from_uchar (ctx, g_value_get_uchar (gval), exception);
958 return seed_value_from_int (ctx, g_value_get_int (gval), exception);
960 return seed_value_from_uint (ctx, g_value_get_uint (gval), exception);
962 return seed_value_from_long (ctx, g_value_get_long (gval), exception);
964 return seed_value_from_ulong (ctx, g_value_get_ulong (gval), exception);
966 return seed_value_from_int64 (ctx, g_value_get_int64 (gval), exception);
968 return seed_value_from_uint64 (ctx, g_value_get_uint64 (gval),
971 return seed_value_from_float (ctx, g_value_get_float (gval), exception);
973 return seed_value_from_double (ctx, g_value_get_double (gval),
976 return seed_value_from_string (ctx, (gchar *)
977 g_value_get_string (gval), exception);
979 return seed_make_pointer (ctx, g_value_get_pointer (gval));
981 // Might need to dup and make a boxed.
982 return seed_make_pointer (ctx, g_value_get_param (gval));
985 if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM) ||
986 g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_FLAGS))
987 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
988 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM))
989 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
990 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_OBJECT))
992 GObject *obj = g_value_get_object (gval);
993 return seed_value_from_object (ctx, obj, exception);
1000 info = g_irepository_find_by_gtype (0, G_VALUE_TYPE (gval));
1003 type = g_base_info_get_type (info);
1005 if (type == GI_INFO_TYPE_UNION)
1007 return seed_make_union (ctx, g_value_peek_pointer (gval), info);
1009 else if (type == GI_INFO_TYPE_STRUCT)
1011 return seed_make_struct (ctx, g_value_peek_pointer (gval), info);
1013 else if (type == GI_INFO_TYPE_BOXED)
1015 return seed_make_boxed (ctx, g_value_dup_boxed (gval), info);
1024 seed_gvalue_from_seed_value (JSContextRef ctx,
1026 GType type, GValue * ret, JSValueRef * exception)
1028 if (G_IS_VALUE (ret))
1029 g_value_unset (ret);
1031 if (type == G_TYPE_STRV)
1037 if (JSValueIsNull (ctx, val) || !JSValueIsObject (ctx, val))
1040 jslen = seed_object_get_property (ctx, (JSObjectRef) val, "length");
1041 length = seed_value_to_uint (ctx, jslen, exception);
1043 result = g_new0 (gchar *, length+1);
1045 for (i = 0; i < length; i++)
1047 result[i] = seed_value_to_string (ctx,
1048 JSObjectGetPropertyAtIndex (ctx,
1058 g_value_init (ret, G_TYPE_STRV);
1059 g_value_take_boxed (ret, result);
1063 else if (g_type_is_a (type, G_TYPE_ENUM) && JSValueIsNumber (ctx, val))
1065 g_value_init (ret, type);
1066 g_value_set_enum (ret, seed_value_to_long (ctx, val, exception));
1069 else if (g_type_is_a (type, G_TYPE_FLAGS) && JSValueIsNumber (ctx, val))
1071 g_value_init (ret, type);
1072 g_value_set_flags (ret, seed_value_to_long (ctx, val, exception));
1075 else if (g_type_is_a (type, G_TYPE_OBJECT)
1076 && (JSValueIsNull (ctx, val) || seed_value_is_gobject (ctx, val)))
1078 GObject *o = seed_value_to_object (ctx,
1081 if (o == NULL || g_type_is_a (G_OBJECT_TYPE (o), type))
1083 g_value_init (ret, type);
1084 g_value_set_object (ret, o);
1089 /* Boxed handling is broken. Will be fixed in struct overhall. */
1090 else if (g_type_is_a (type, G_TYPE_BOXED))
1092 gpointer p = seed_pointer_get_pointer (ctx, val);
1095 g_value_init (ret, type);
1096 g_value_set_boxed (ret, p);
1101 if (JSValueIsObject (ctx, val))
1103 GIBaseInfo *info = g_irepository_find_by_gtype (0, type);
1104 JSObjectRef new_struct;
1109 seed_construct_struct_type_with_parameters (ctx,
1113 p = seed_pointer_get_pointer (ctx, new_struct);
1116 g_value_init (ret, type);
1117 g_value_set_boxed (ret, p);
1118 g_base_info_unref (info);
1121 g_base_info_unref (info);
1128 case G_TYPE_BOOLEAN:
1130 g_value_init (ret, G_TYPE_BOOLEAN);
1131 g_value_set_boolean (ret, seed_value_to_boolean (ctx,
1138 g_value_init (ret, type);
1139 if (type == G_TYPE_INT)
1140 g_value_set_int (ret, seed_value_to_int (ctx, val, exception));
1142 g_value_set_uint (ret, seed_value_to_uint (ctx, val, exception));
1147 g_value_init (ret, G_TYPE_CHAR);
1148 g_value_set_char (ret, seed_value_to_char (ctx, val, exception));
1153 g_value_init (ret, G_TYPE_UCHAR);
1154 g_value_set_uchar (ret, seed_value_to_uchar (ctx, val, exception));
1167 g_value_init (ret, G_TYPE_LONG);
1168 g_value_set_long (ret, seed_value_to_long (ctx, val, exception));
1171 g_value_init (ret, G_TYPE_ULONG);
1172 g_value_set_ulong (ret, seed_value_to_ulong (ctx,
1176 g_value_init (ret, G_TYPE_INT64);
1177 g_value_set_int64 (ret, seed_value_to_int64 (ctx,
1181 g_value_init (ret, G_TYPE_UINT64);
1182 g_value_set_uint64 (ret, seed_value_to_uint64 (ctx,
1186 g_value_init (ret, G_TYPE_FLOAT);
1187 g_value_set_float (ret, seed_value_to_float (ctx,
1191 g_value_init (ret, G_TYPE_DOUBLE);
1192 g_value_set_double (ret, seed_value_to_double (ctx,
1200 gchar *cval = seed_value_to_string (ctx, val, exception);
1202 g_value_init (ret, G_TYPE_STRING);
1203 g_value_take_string (ret, cval);
1209 // TODO: FIXME: This whole undefined type area
1210 // needs some heaaavy improvement.
1212 // Support [GObject.TYPE_INT, 3]
1213 // TODO: FIXME: Might crash.
1214 if (type == 0 && JSValueIsObject (ctx, val))
1216 // TODO: FIXME: Better array test like the cool one on reddit.
1217 guint length = seed_value_to_int (ctx,
1218 seed_object_get_property (ctx,
1226 seed_value_to_int (ctx,
1227 JSObjectGetPropertyAtIndex (ctx,
1233 JSObjectGetPropertyAtIndex (ctx, (JSObjectRef) val, 1,
1235 if (type) // Prevents recursion.
1237 return seed_gvalue_from_seed_value (ctx, val,
1238 type, ret, exception);
1240 // TODO: FIXME: Handle better?
1242 g_assert_not_reached ();
1245 switch (JSValueGetType (ctx, val))
1247 case kJSTypeBoolean:
1249 g_value_init (ret, G_TYPE_BOOLEAN);
1250 g_value_set_boolean (ret,
1251 seed_value_to_boolean (ctx,
1257 g_value_init (ret, G_TYPE_DOUBLE);
1258 g_value_set_double (ret,
1259 seed_value_to_double (ctx, val, exception));
1264 gchar *cv = seed_value_to_string (ctx, val,
1267 g_value_init (ret, G_TYPE_STRING);
1268 g_value_take_string (ret, cv);
1282 * seed_object_get_property
1283 * @ctx: A #SeedContext
1284 * @object: A #SeedObject
1285 * @name: The property to get, should be a valid JavaScript identifier
1287 * Returns: The value of the property or %NULL
1290 seed_object_get_property (JSContextRef ctx,
1291 JSObjectRef val, const gchar * name)
1294 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1295 JSValueRef ret = JSObjectGetProperty (ctx,
1299 JSStringRelease (jname);
1305 * seed_object_set_property
1306 * @ctx: A #SeedContext
1307 * @object: A #SeedObject
1308 * @name: The property to set, should be a valid JavaScript identifier
1309 * @value: The value to set the property to.
1311 * Returns: %TRUE on success, %FALSE otherwise.
1314 seed_object_set_property (JSContextRef ctx, JSObjectRef object,
1315 const gchar * name, JSValueRef value)
1317 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1318 JSValueRef exception = NULL;
1322 JSObjectSetProperty (ctx, (JSObjectRef) object, jname, value, 0,
1326 JSStringRelease (jname);
1331 /* TODO: Make some macros or something for making exceptions, code is littered
1332 with annoyingness right now */
1335 * seed_value_to_boolean:
1336 * @ctx: A #SeedContext.
1337 * @val: The #SeedValue to convert.
1338 * @exception: A reference to a #SeedValue in which to store any exceptions.
1339 * Pass %NULL to ignore exceptions.
1341 * Converts the given #SeedValue into a #gboolean. Keep in mind that this will
1342 * not convert a JavaScript number type, only a boolean.
1344 * Return value: The #gboolean represented by @val, or %NULL if an exception
1345 * is raised during the conversion.
1349 seed_value_to_boolean (JSContextRef ctx,
1350 JSValueRef val, JSValueRef * exception)
1352 if (!JSValueIsBoolean (ctx, val) && !JSValueIsNumber (ctx, val))
1354 if (!JSValueIsNull (ctx, val))
1356 seed_make_exception (eng->context, exception, "ConversionError",
1357 "Can not convert Javascript value to boolean");
1364 return JSValueToBoolean (ctx, val);
1368 * seed_value_from_boolean:
1369 * @ctx: A #SeedContext.
1370 * @val: The #gboolean to represent.
1371 * @exception: A reference to a #SeedValue in which to store any exceptions.
1372 * Pass %NULL to ignore exceptions.
1374 * Converts the given #gboolean into a #SeedValue.
1376 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1377 * is raised during the conversion.
1381 seed_value_from_boolean (JSContextRef ctx,
1382 gboolean val, JSValueRef * exception)
1384 return JSValueMakeBoolean (ctx, val);
1388 * seed_value_to_uint:
1389 * @ctx: A #SeedContext.
1390 * @val: The #SeedValue to convert.
1391 * @exception: A reference to a #SeedValue in which to store any exceptions.
1392 * Pass %NULL to ignore exceptions.
1394 * Converts the given #SeedValue into a #guint.
1396 * Return value: The #guint represented by @val, or %NULL if an exception
1397 * is raised during the conversion.
1401 seed_value_to_uint (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1403 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1405 if (!JSValueIsNull (ctx, val))
1407 seed_make_exception (ctx, exception, "ConversionError",
1408 "Can not convert Javascript value to"
1414 return (guint) JSValueToNumber (ctx, val, NULL);
1418 * seed_value_from_uint:
1419 * @ctx: A #SeedContext.
1420 * @val: The #guint to represent.
1421 * @exception: A reference to a #SeedValue in which to store any exceptions.
1422 * Pass %NULL to ignore exceptions.
1424 * Converts the given #guint into a #SeedValue.
1426 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1427 * is raised during the conversion.
1431 seed_value_from_uint (JSContextRef ctx, guint val, JSValueRef * exception)
1433 return JSValueMakeNumber (ctx, (gdouble) val);
1437 * seed_value_to_int:
1438 * @ctx: A #SeedContext.
1439 * @val: The #SeedValue to convert.
1440 * @exception: A reference to a #SeedValue in which to store any exceptions.
1441 * Pass %NULL to ignore exceptions.
1443 * Converts the given #SeedValue into a #gint.
1445 * Return value: The #gint represented by @val, or %NULL if an exception
1446 * is raised during the conversion.
1450 seed_value_to_int (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1452 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1454 if (!JSValueIsNull (ctx, val))
1455 seed_make_exception (ctx, exception, "ConversionError",
1456 "Can not convert Javascript value to" " int");
1460 return (gint) JSValueToNumber (ctx, val, NULL);
1464 * seed_value_from_int:
1465 * @ctx: A #SeedContext.
1466 * @val: The #gint to represent.
1467 * @exception: A reference to a #SeedValue in which to store any exceptions.
1468 * Pass %NULL to ignore exceptions.
1470 * Converts the given #gint into a #SeedValue.
1472 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1473 * is raised during the conversion.
1477 seed_value_from_int (JSContextRef ctx, gint val, JSValueRef * exception)
1479 return JSValueMakeNumber (ctx, (gdouble) val);
1483 * seed_value_to_char:
1484 * @ctx: A #SeedContext.
1485 * @val: The #SeedValue to convert.
1486 * @exception: A reference to a #SeedValue in which to store any exceptions.
1487 * Pass %NULL to ignore exceptions.
1489 * Converts the given #SeedValue into a #gchar.
1491 * Return value: The #gchar represented by @val, or %NULL if an exception
1492 * is raised during the conversion.
1496 seed_value_to_char (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1500 if (!JSValueIsNumber (ctx, val))
1502 if (!JSValueIsNull (ctx, val))
1503 seed_make_exception (ctx, exception, "ConversionError",
1504 "Can not convert Javascript value to" " gchar");
1508 cv = JSValueToNumber (ctx, val, NULL);
1510 if (cv < G_MININT8 || cv > G_MAXINT8)
1512 seed_make_exception (ctx, exception, "ConversionError",
1513 "Javascript number out of range of gchar");
1521 * seed_value_from_char:
1522 * @ctx: A #SeedContext.
1523 * @val: The #gchar to represent.
1524 * @exception: A reference to a #SeedValue in which to store any exceptions.
1525 * Pass %NULL to ignore exceptions.
1527 * Converts the given #gchar into a #SeedValue.
1529 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1530 * is raised during the conversion.
1534 seed_value_from_char (JSContextRef ctx, gchar val, JSValueRef * exception)
1536 return JSValueMakeNumber (ctx, (gdouble) val);
1540 * seed_value_to_uchar:
1541 * @ctx: A #SeedContext.
1542 * @val: The #SeedValue to convert.
1543 * @exception: A reference to a #SeedValue in which to store any exceptions.
1544 * Pass %NULL to ignore exceptions.
1546 * Converts the given #SeedValue into a #guchar.
1548 * Return value: The #guchar represented by @val, or %NULL if an exception
1549 * is raised during the conversion.
1553 seed_value_to_uchar (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1557 if (!JSValueIsNumber (ctx, val))
1559 if (!JSValueIsNull (ctx, val))
1560 seed_make_exception (ctx, exception, "ConversionError",
1561 "Can not convert Javascript value to" " guchar");
1565 cv = JSValueToNumber (ctx, val, NULL);
1567 if (cv > G_MAXUINT8)
1569 seed_make_exception (ctx, exception, "ConversionError",
1570 "Javascript number out of range of guchar");
1578 * seed_value_from_uchar:
1579 * @ctx: A #SeedContext.
1580 * @val: The #guchar to represent.
1581 * @exception: A reference to a #SeedValue in which to store any exceptions.
1582 * Pass %NULL to ignore exceptions.
1584 * Converts the given #guchar into a #SeedValue.
1586 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1587 * is raised during the conversion.
1591 seed_value_from_uchar (JSContextRef ctx, guchar val, JSValueRef * exception)
1593 return JSValueMakeNumber (ctx, (gdouble) val);
1597 * seed_value_to_short:
1598 * @ctx: A #SeedContext.
1599 * @val: The #SeedValue to convert.
1600 * @exception: A reference to a #SeedValue in which to store any exceptions.
1601 * Pass %NULL to ignore exceptions.
1603 * Converts the given #SeedValue into a #gshort.
1605 * Return value: The #gshort represented by @val, or %NULL if an exception
1606 * is raised during the conversion.
1610 seed_value_to_short (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1612 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1614 if (!JSValueIsNull (ctx, val))
1615 seed_make_exception (ctx, exception, "ConversionError",
1616 "Can not convert Javascript value to" " short");
1620 return (gshort) JSValueToNumber (ctx, val, NULL);
1624 * seed_value_from_short:
1625 * @ctx: A #SeedContext.
1626 * @val: The #gshort to represent.
1627 * @exception: A reference to a #SeedValue in which to store any exceptions.
1628 * Pass %NULL to ignore exceptions.
1630 * Converts the given #gshort into a #SeedValue.
1632 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1633 * is raised during the conversion.
1637 seed_value_from_short (JSContextRef ctx, gshort val, JSValueRef * exception)
1639 return JSValueMakeNumber (ctx, (gdouble) val);
1643 * seed_value_to_ushort:
1644 * @ctx: A #SeedContext.
1645 * @val: The #SeedValue to convert.
1646 * @exception: A reference to a #SeedValue in which to store any exceptions.
1647 * Pass %NULL to ignore exceptions.
1649 * Converts the given #SeedValue into a #gushort.
1651 * Return value: The #gushort represented by @val, or %NULL if an exception
1652 * is raised during the conversion.
1656 seed_value_to_ushort (JSContextRef ctx, JSValueRef val,
1657 JSValueRef * exception)
1659 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1661 if (!JSValueIsNull (ctx, val))
1662 seed_make_exception (ctx, exception, "ConversionError",
1663 "Can not convert Javascript value to" " ushort");
1667 return (gushort) JSValueToNumber (ctx, val, NULL);
1671 * seed_value_from_ushort:
1672 * @ctx: A #SeedContext.
1673 * @val: The #gushort to represent.
1674 * @exception: A reference to a #SeedValue in which to store any exceptions.
1675 * Pass %NULL to ignore exceptions.
1677 * Converts the given #gushort into a #SeedValue.
1679 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1680 * is raised during the conversion.
1684 seed_value_from_ushort (JSContextRef ctx, gushort val, JSValueRef * exception)
1686 return JSValueMakeNumber (ctx, (gdouble) val);
1690 * seed_value_to_long:
1691 * @ctx: A #SeedContext.
1692 * @val: The #SeedValue to convert.
1693 * @exception: A reference to a #SeedValue in which to store any exceptions.
1694 * Pass %NULL to ignore exceptions.
1696 * Converts the given #SeedValue into a #glong.
1698 * Return value: The #glong represented by @val, or %NULL if an exception
1699 * is raised during the conversion.
1703 seed_value_to_long (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1705 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1707 if (!JSValueIsNull (ctx, val))
1708 seed_make_exception (ctx, exception, "ConversionError",
1709 "Can not convert Javascript value to" " long");
1713 return (glong) JSValueToNumber (ctx, val, NULL);
1717 * seed_value_from_long:
1718 * @ctx: A #SeedContext.
1719 * @val: The #glong to represent.
1720 * @exception: A reference to a #SeedValue in which to store any exceptions.
1721 * Pass %NULL to ignore exceptions.
1723 * Converts the given #glong into a #SeedValue.
1725 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1726 * is raised during the conversion.
1730 seed_value_from_long (JSContextRef ctx, glong val, JSValueRef * exception)
1732 return JSValueMakeNumber (ctx, (gdouble) val);
1736 * seed_value_to_ulong:
1737 * @ctx: A #SeedContext.
1738 * @val: The #SeedValue to convert.
1739 * @exception: A reference to a #SeedValue in which to store any exceptions.
1740 * Pass %NULL to ignore exceptions.
1742 * Converts the given #SeedValue into a #gulong.
1744 * Return value: The #gulong represented by @val, or %NULL if an exception
1745 * is raised during the conversion.
1749 seed_value_to_ulong (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1751 if (!JSValueIsNumber (ctx, val))
1753 if (!JSValueIsNull (ctx, val))
1754 seed_make_exception (ctx, exception, "ConversionError",
1755 "Can not convert Javascript value to" " ulong");
1760 return (gulong) JSValueToNumber (ctx, val, NULL);
1764 * seed_value_from_ulong:
1765 * @ctx: A #SeedContext.
1766 * @val: The #gulong to represent.
1767 * @exception: A reference to a #SeedValue in which to store any exceptions.
1768 * Pass %NULL to ignore exceptions.
1770 * Converts the given #gulong into a #SeedValue.
1772 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1773 * is raised during the conversion.
1777 seed_value_from_ulong (JSContextRef ctx, gulong val, JSValueRef * exception)
1779 return JSValueMakeNumber (ctx, (gdouble) val);
1783 * seed_value_to_int64:
1784 * @ctx: A #SeedContext.
1785 * @val: The #SeedValue to convert.
1786 * @exception: A reference to a #SeedValue in which to store any exceptions.
1787 * Pass %NULL to ignore exceptions.
1789 * Converts the given #SeedValue into a #gint64.
1791 * Return value: The #gint64 represented by @val, or %NULL if an exception
1792 * is raised during the conversion.
1796 seed_value_to_int64 (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1798 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1800 if (!JSValueIsNull (ctx, val))
1801 seed_make_exception (ctx, exception, "ConversionError",
1802 "Can not convert Javascript value to" " gint64");
1807 return (gint64) JSValueToNumber (ctx, val, NULL);
1811 * seed_value_from_int64:
1812 * @ctx: A #SeedContext.
1813 * @val: The #gint64 to represent.
1814 * @exception: A reference to a #SeedValue in which to store any exceptions.
1815 * Pass %NULL to ignore exceptions.
1817 * Converts the given #gint64 into a #SeedValue.
1819 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1820 * is raised during the conversion.
1824 seed_value_from_int64 (JSContextRef ctx, gint64 val, JSValueRef * exception)
1826 return JSValueMakeNumber (ctx, (gdouble) val);
1830 * seed_value_to_uint64:
1831 * @ctx: A #SeedContext.
1832 * @val: The #SeedValue to convert.
1833 * @exception: A reference to a #SeedValue in which to store any exceptions.
1834 * Pass %NULL to ignore exceptions.
1836 * Converts the given #SeedValue into a #guint64.
1838 * Return value: The #guint64 represented by @val, or %NULL if an exception
1839 * is raised during the conversion.
1843 seed_value_to_uint64 (JSContextRef ctx,
1844 JSValueRef val, JSValueRef * exception)
1846 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1848 if (!JSValueIsNull (ctx, val))
1849 seed_make_exception (ctx, exception, "ConversionError",
1850 "Can not convert Javascript value to"
1856 return (guint64) JSValueToNumber (ctx, val, NULL);
1860 * seed_value_from_uint64:
1861 * @ctx: A #SeedContext.
1862 * @val: The #guint64 to represent.
1863 * @exception: A reference to a #SeedValue in which to store any exceptions.
1864 * Pass %NULL to ignore exceptions.
1866 * Converts the given #guint64 into a #SeedValue.
1868 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1869 * is raised during the conversion.
1873 seed_value_from_uint64 (JSContextRef ctx, guint64 val, JSValueRef * exception)
1875 return JSValueMakeNumber (ctx, (gdouble) val);
1879 * seed_value_to_float:
1880 * @ctx: A #SeedContext.
1881 * @val: The #SeedValue to convert.
1882 * @exception: A reference to a #SeedValue in which to store any exceptions.
1883 * Pass %NULL to ignore exceptions.
1885 * Converts the given #SeedValue into a #gfloat.
1887 * Return value: The #gfloat represented by @val, or %NULL if an exception
1888 * is raised during the conversion.
1892 seed_value_to_float (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1894 if (!JSValueIsNumber (ctx, val))
1896 if (!JSValueIsNull (ctx, val))
1897 seed_make_exception (ctx, exception, "ConversionError",
1898 "Can not convert Javascript value to" " gfloat");
1902 return (gfloat) JSValueToNumber (ctx, val, NULL);
1906 * seed_value_from_float:
1907 * @ctx: A #SeedContext.
1908 * @val: The #gfloat to represent.
1909 * @exception: A reference to a #SeedValue in which to store any exceptions.
1910 * Pass %NULL to ignore exceptions.
1912 * Converts the given #gfloat into a #SeedValue.
1914 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1915 * is raised during the conversion.
1919 seed_value_from_float (JSContextRef ctx, gfloat val, JSValueRef * exception)
1921 return JSValueMakeNumber (ctx, (gdouble) val);
1925 * seed_value_to_double:
1926 * @ctx: A #SeedContext.
1927 * @val: The #SeedValue to convert.
1928 * @exception: A reference to a #SeedValue in which to store any exceptions.
1929 * Pass %NULL to ignore exceptions.
1931 * Converts the given #SeedValue into a #gdouble.
1933 * Return value: The #gdouble represented by @val, or %NULL if an exception
1934 * is raised during the conversion.
1938 seed_value_to_double (JSContextRef ctx,
1939 JSValueRef val, JSValueRef * exception)
1941 if (!JSValueIsNumber (ctx, val))
1943 if (!JSValueIsNull (ctx, val))
1944 seed_make_exception (ctx, exception, "ConversionError",
1945 "Can not convert Javascript value to" " double");
1949 return (gdouble) JSValueToNumber (ctx, val, NULL);
1953 * seed_value_from_double:
1954 * @ctx: A #SeedContext.
1955 * @val: The #gdouble to represent.
1956 * @exception: A reference to a #SeedValue in which to store any exceptions.
1957 * Pass %NULL to ignore exceptions.
1959 * Converts the given #gdouble into a #SeedValue.
1961 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1962 * is raised during the conversion.
1966 seed_value_from_double (JSContextRef ctx, gdouble val, JSValueRef * exception)
1968 return JSValueMakeNumber (ctx, (gdouble) val);
1972 * seed_value_to_size:
1973 * @ctx: A #SeedContext.
1974 * @val: The #SeedValue to convert.
1975 * @exception: A reference to a #SeedValue in which to store any exceptions.
1976 * Pass %NULL to ignore exceptions.
1978 * Converts the given #SeedValue into a #gsize.
1980 * Return value: The #gsize represented by @val, or %NULL if an exception
1981 * is raised during the conversion.
1985 seed_value_to_size (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1987 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1989 if (!JSValueIsNull (ctx, val))
1990 seed_make_exception (ctx, exception, "ConversionError",
1991 "Can not convert Javascript value to" " gsize");
1995 return (gsize) JSValueToNumber (ctx, val, NULL);
1999 * seed_value_from_size:
2000 * @ctx: A #SeedContext.
2001 * @val: The #gsize to represent.
2002 * @exception: A reference to a #SeedValue in which to store any exceptions.
2003 * Pass %NULL to ignore exceptions.
2005 * Converts the given #gsize into a #SeedValue.
2007 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2008 * is raised during the conversion.
2012 seed_value_from_size (JSContextRef ctx, gsize val, JSValueRef * exception)
2014 return JSValueMakeNumber (ctx, (gdouble) val);
2018 * seed_value_to_ssize:
2019 * @ctx: A #SeedContext.
2020 * @val: The #SeedValue to convert.
2021 * @exception: A reference to a #SeedValue in which to store any exceptions.
2022 * Pass %NULL to ignore exceptions.
2024 * Converts the given #SeedValue into a #gssize.
2026 * Return value: The #gssize represented by @val, or %NULL if an exception
2027 * is raised during the conversion.
2031 seed_value_to_ssize (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
2033 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
2035 if (!JSValueIsNull (ctx, val))
2036 seed_make_exception (ctx, exception, "ConversionError",
2037 "Can not convert Javascript value to" " gssize");
2041 return (gssize) JSValueToNumber (ctx, val, NULL);
2045 * seed_value_from_ssize:
2046 * @ctx: A #SeedContext.
2047 * @val: The #gssize to represent.
2048 * @exception: A reference to a #SeedValue in which to store any exceptions.
2049 * Pass %NULL to ignore exceptions.
2051 * Converts the given #gssize into a #SeedValue.
2053 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2054 * is raised during the conversion.
2058 seed_value_from_ssize (JSContextRef ctx, gssize val, JSValueRef * exception)
2060 return JSValueMakeNumber (ctx, (gdouble) val);
2064 * seed_value_to_string:
2065 * @ctx: A #SeedContext.
2066 * @val: The #SeedValue to convert.
2067 * @exception: A reference to a #SeedValue in which to store any exceptions.
2068 * Pass %NULL to ignore exceptions.
2070 * Converts the given #SeedValue into a #gchar* string. Keep in mind that it's
2071 * up to the caller to free the string.
2073 * If the #SeedValue represents JavaScript's undefined value, this returns
2074 * "[undefined]"; if it represents JavaScript's null value, this returns
2077 * If the #SeedValue is a number or a boolean, it is printed as a double, with
2078 * the printf format string "%.15g".
2080 * If the #SeedValue is an object, the string returned is that obtained by
2081 * calling .toString() on said object.
2083 * Return value: The #gchar* represented by @val, or %NULL if an exception
2084 * is raised during the conversion.
2088 seed_value_to_string (JSContextRef ctx,
2089 JSValueRef val, JSValueRef * exception)
2091 JSStringRef jsstr = NULL;
2092 JSValueRef func, str;
2098 else if (JSValueIsUndefined (ctx, val))
2100 buf = g_strdup ("[undefined]");
2102 else if (JSValueIsNull (ctx, val))
2104 buf = g_strdup ("[null]");
2106 else if (JSValueIsBoolean (ctx, val) || JSValueIsNumber (ctx, val))
2108 buf = g_strdup_printf ("%.15g", JSValueToNumber (ctx, val, NULL));
2112 if (!JSValueIsString (ctx, val)) // In this case,
2116 seed_object_get_property (ctx, (JSObjectRef) val, "toString");
2117 if (!JSValueIsNull (ctx, func) &&
2118 JSValueIsObject (ctx, func) &&
2119 JSObjectIsFunction (ctx, (JSObjectRef) func))
2121 JSObjectCallAsFunction (ctx, (JSObjectRef) func,
2122 (JSObjectRef) val, 0, NULL, NULL);
2125 jsstr = JSValueToStringCopy (ctx, val, NULL);
2126 length = JSStringGetMaximumUTF8CStringSize (jsstr);
2129 buf = g_malloc (length * sizeof (gchar));
2130 JSStringGetUTF8CString (jsstr, buf, length);
2133 JSStringRelease (jsstr);
2140 * seed_value_from_string:
2141 * @ctx: A #SeedContext.
2142 * @val: The #gchar* to represent.
2143 * @exception: A reference to a #SeedValue in which to store any exceptions.
2144 * Pass %NULL to ignore exceptions.
2146 * Converts the given #gchar* string into a #SeedValue.
2148 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2149 * is raised during the conversion.
2153 seed_value_from_string (JSContextRef ctx,
2154 const gchar * val, JSValueRef * exception)
2157 return JSValueMakeNull (ctx);
2160 JSStringRef jsstr = JSStringCreateWithUTF8CString (val);
2161 JSValueRef valstr = JSValueMakeString (ctx, jsstr);
2162 JSStringRelease (jsstr);
2169 * seed_value_from_binary_string:
2170 * @ctx: A #SeedContext.
2171 * @bytes: A string of bytes to represent as a string.
2172 * @n_bytes: The number of bytes from @bytes to convert.
2173 * @exception: A reference to a #SeedValue in which to store any exceptions.
2174 * Pass %NULL to ignore exceptions.
2176 * Converts a string representation of the given binary string
2177 * into a #SeedValue.
2179 * Return value: A #SeedValue which represents @bytes as a string, or %NULL
2180 * if an exception is raised during the conversion.
2184 seed_value_from_binary_string (JSContextRef ctx,
2185 const gchar * bytes,
2186 gint n_bytes, JSValueRef * exception)
2190 gchar *nstr = g_alloca ((n_bytes + 1) * sizeof (gchar));
2191 g_strlcpy (nstr, bytes, n_bytes);
2192 nstr[n_bytes] = '\0';
2194 ret = seed_value_from_string (ctx, nstr, exception);
2200 * seed_value_to_filename:
2201 * @ctx: A #SeedContext.
2202 * @val: The #SeedValue to convert.
2203 * @exception: A reference to a #SeedValue in which to store any exceptions.
2204 * Pass %NULL to ignore exceptions.
2206 * Converts the given #SeedValue into a #gchar*, properly converting to the
2207 * character set used for filenames on the local machine.
2209 * Return value: The #gchar* represented by @val, or %NULL if an exception
2210 * is raised during the conversion.
2214 seed_value_to_filename (JSContextRef ctx,
2215 JSValueRef val, JSValueRef * exception)
2218 gchar *utf8 = seed_value_to_string (ctx, val, exception);
2221 filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, &e);
2225 seed_make_exception_from_gerror (ctx, exception, e);
2234 * seed_value_from_filename:
2235 * @ctx: A #SeedContext.
2236 * @val: The #gchar* filename to represent.
2237 * @exception: A reference to a #SeedValue in which to store any exceptions.
2238 * Pass %NULL to ignore exceptions.
2240 * Converts the given #gchar* filename into a #SeedValue, respecting the
2241 * character set used for filenames on the local machine.
2243 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2244 * is raised during the conversion.
2248 seed_value_from_filename (JSContextRef ctx,
2249 const gchar * val, JSValueRef * exception)
2255 return JSValueMakeNull (ctx);
2258 utf8 = g_filename_to_utf8 (val, -1, NULL, NULL, &e);
2262 seed_make_exception_from_gerror (ctx, exception, e);
2264 return JSValueMakeNull (ctx);
2267 JSValueRef valstr = seed_value_from_string (ctx, utf8, exception);
2276 * seed_value_to_object:
2277 * @ctx: A #SeedContext.
2278 * @val: The #SeedValue to unwrap.
2279 * @exception: A reference to a #SeedValue in which to store any exceptions.
2280 * Pass %NULL to ignore exceptions.
2282 * Given a #SeedValue which is wrapping a #GObject, retrieve the wrapped
2285 * Return value: The #GObject wrapped within @val, or %NULL if an exception
2286 * is raised during the conversion.
2290 seed_value_to_object (JSContextRef ctx,
2291 JSValueRef val, JSValueRef * exception)
2296 * Worth investigating if this is the best way to handle null. Some of
2297 * the existing code depends on null Objects not throwing an exception
2298 * however, needs testing at higher level if value can be null
2302 if (JSValueIsNull (ctx, val))
2304 if (!seed_value_is_gobject (ctx, val))
2306 seed_make_exception (ctx, exception, "ConversionError",
2307 "Attempt to convert from"
2308 " non GObject to GObject");
2312 gobject = (GObject *) JSObjectGetPrivate ((JSObjectRef) val);
2313 g_assert (G_IS_OBJECT (gobject));
2319 * seed_value_from_object:
2320 * @ctx: A #SeedContext.
2321 * @val: The #GObject to wrap.
2322 * @exception: A reference to a #SeedValue in which to store any exceptions.
2323 * Pass %NULL to ignore exceptions.
2325 * Wraps @val in a #SeedValue.
2327 * Return value: A #SeedValue which wraps @val, or %NULL if an exception
2328 * is raised during the conversion.
2332 seed_value_from_object (JSContextRef ctx,
2333 GObject * val, JSValueRef * exception)
2336 return JSValueMakeNull (ctx);
2338 return seed_wrap_object (ctx, val);
2342 seed_validate_enum (GIEnumInfo * info, long val)
2345 GIValueInfo *value_info;
2346 gint value; // TODO: investigate glong/gint mismatch w/ g_value_info_get_value
2348 n = g_enum_info_get_n_values (info);
2349 for (i = 0; i < n; i++)
2351 value_info = g_enum_info_get_value (info, i);
2352 value = g_value_info_get_value (value_info);
2354 g_base_info_unref ((GIBaseInfo *) value_info);
2363 seed_value_from_time_t (JSContextRef ctx, time_t time, JSValueRef * exception)
2367 args[0] = seed_value_from_double (ctx, ((gdouble) time) * 1000, exception);
2368 return JSObjectMakeDate (ctx, 1, args, exception);
2372 seed_value_to_time_t (JSContextRef ctx,
2373 JSValueRef value, JSValueRef * exception)
2375 JSValueRef get_time_method;
2380 if (JSValueIsNumber (ctx, value))
2382 return (unsigned long) seed_value_to_long (ctx, value, exception);
2384 else if (JSValueIsObject (ctx, value))
2386 get_time_method = seed_object_get_property (ctx, (JSObjectRef) value,
2388 if (JSValueIsNull (ctx, get_time_method) ||
2389 !JSValueIsObject (ctx, get_time_method))
2393 jstime = JSObjectCallAsFunction (ctx,
2394 (JSObjectRef) get_time_method,
2395 (JSObjectRef) value,
2396 0, NULL, exception);
2397 time = seed_value_to_double (ctx, jstime, exception);
2398 return (unsigned long) (time / 1000);
2402 seed_make_exception (ctx, exception,
2404 "Unable to convert JavaScript value to time_t");