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"
23 JSClassRef gobject_class;
24 JSClassRef gobject_method_class;
25 JSClassRef gobject_constructor_class;
26 JSClassRef seed_callback_class;
27 JSClassRef gobject_init_method_class;
31 seed_value_is_gobject (JSContextRef ctx, JSValueRef value)
33 if (!JSValueIsObject (ctx, value) || JSValueIsNull (ctx, value))
36 return JSValueIsObjectOfClass (ctx, value, gobject_class);
40 seed_toggle_ref (gpointer data, GObject * object, gboolean is_last_ref)
44 wrapper = (JSValueRef) data;
48 JSValueUnprotect (eng->context, wrapper);
52 JSValueProtect (eng->context, wrapper);
57 seed_gobject_destroyed (gpointer object)
59 JSValueUnprotect (eng->context, (JSValueRef) object);
60 JSObjectSetPrivate ((JSObjectRef) object, 0);
64 seed_make_wrapper_for_type (JSContextRef ctx, GType type)
70 class = seed_gobject_get_class_for_gtype (ctx, type);
72 while (!class && (type = g_type_parent (type)))
73 class = seed_gobject_get_class_for_gtype (ctx, type);
75 prototype = seed_gobject_get_prototype_for_gtype (type);
76 ret = JSObjectMake (ctx, class, NULL);
78 JSObjectSetPrototype (ctx, ret, prototype);
80 g_assert_not_reached ();
86 seed_wrap_object (JSContextRef ctx, GObject * object)
92 type = G_OBJECT_TYPE (object);
94 user_data = (JSValueRef) g_object_get_qdata (object, js_ref_quark);
99 if (seed_next_gobject_wrapper)
100 js_ref = seed_next_gobject_wrapper;
102 js_ref = seed_make_wrapper_for_type (ctx, type);
104 JSObjectSetPrivate (js_ref, object);
106 g_object_set_qdata_full (object, js_ref_quark, (gpointer) js_ref,
107 seed_gobject_destroyed);
109 JSValueProtect (eng->context, js_ref);
110 g_object_add_toggle_ref (object, seed_toggle_ref, (gpointer) js_ref);
112 seed_add_signals_to_object (ctx, js_ref, object);
114 seed_next_gobject_wrapper = NULL;
120 seed_release_arg (GITransfer transfer,
121 GITypeInfo * type_info, GITypeTag type_tag, GArgument * arg)
124 GITypeInfo *param_type;
125 GIBaseInfo *interface_info;
130 case GI_TYPE_TAG_UTF8:
131 case GI_TYPE_TAG_FILENAME:
132 g_free (arg->v_string);
134 case GI_TYPE_TAG_ARRAY:
137 param_type = g_type_info_get_param_type (type_info, 0);
139 switch (g_type_info_get_tag (param_type))
141 case GI_TYPE_TAG_UTF8:
142 if (transfer == GI_TRANSFER_EVERYTHING)
143 g_strfreev (arg->v_pointer);
144 else if (transfer == GI_TRANSFER_CONTAINER)
145 g_free (arg->v_pointer);
147 case GI_TYPE_TAG_GTYPE:
148 case GI_TYPE_TAG_FLOAT:
149 case GI_TYPE_TAG_UINT8:
150 g_free (arg->v_pointer);
152 case GI_TYPE_TAG_INTERFACE:
155 g_assert_not_reached ();
158 g_base_info_unref ((GIBaseInfo *) param_type);
161 case GI_TYPE_TAG_INTERFACE:
165 interface_info = g_type_info_get_interface (type_info);
168 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
171 if (g_type_is_a (gtype, G_TYPE_OBJECT)
172 || g_type_is_a (gtype, G_TYPE_INTERFACE))
175 "Unreffing object of type: %s in"
176 "argument release. Reference count: %d\n",
177 g_type_name (G_OBJECT_TYPE
178 (G_OBJECT (arg->v_pointer))),
179 G_OBJECT (arg->v_pointer)->ref_count);
180 g_object_unref (G_OBJECT (arg->v_pointer));
182 else if (g_type_is_a (gtype, G_TYPE_VALUE))
184 gval = (GValue *) arg->v_pointer;
185 // Free/unref the GValue's contents.
186 g_value_unset (gval);
188 g_slice_free1 (sizeof (GValue), gval);
190 else if (g_type_is_a (gtype, G_TYPE_CLOSURE))
192 g_closure_unref (arg->v_pointer);
195 g_base_info_unref (interface_info);
208 seed_gi_release_arg (GITransfer transfer,
209 GITypeInfo * type_info, GArgument * arg)
213 if (transfer == GI_TRANSFER_NOTHING)
216 type_tag = g_type_info_get_tag ((GITypeInfo *) type_info);
218 return seed_release_arg (transfer, type_info, type_tag, arg);
222 seed_gi_release_in_arg (GITransfer transfer,
223 GITypeInfo * type_info, GArgument * arg)
227 if (transfer == GI_TRANSFER_EVERYTHING)
230 type_tag = g_type_info_get_tag ((GITypeInfo *) type_info);
234 // TODO: FIXME: Leaaaks?
235 case GI_TYPE_TAG_INTERFACE:
237 // TODO: FIXME: Need some safe way to look for GClosure.
240 case GI_TYPE_TAG_UTF8:
241 case GI_TYPE_TAG_FILENAME:
242 case GI_TYPE_TAG_ARRAY:
243 return seed_release_arg (GI_TRANSFER_EVERYTHING,
244 type_info, type_tag, arg);
253 seed_gi_make_jsarray (JSContextRef ctx,
255 GITypeInfo * param_type, JSValueRef * exception)
257 GITypeTag element_type;
258 JSValueRef *elements;
260 gchar **str_array = (gchar **) array;
261 JSValueRef ret = JSValueMakeNull (ctx);
263 element_type = g_type_info_get_tag (param_type);
265 if (element_type == GI_TYPE_TAG_UTF8)
268 length = g_strv_length (str_array);
272 elements = g_alloca (sizeof (JSValueRef) * length);
273 for (i = 0; i < length; ++i)
275 elements[i] = seed_value_from_string (ctx, str_array[i], exception);
278 ret = (JSValueRef) JSObjectMakeArray (ctx, length, elements, exception);
285 seed_gi_make_array (JSContextRef ctx,
288 GITypeInfo * param_type,
289 void **array_p, JSValueRef * exception)
291 GITypeTag element_type;
295 element_type = g_type_info_get_tag (param_type);
297 switch (element_type)
299 case GI_TYPE_TAG_UTF8:
301 gchar **strresult = g_new0 (gchar *, length + 1);
303 for (i = 0; i < length; i++)
305 elem = JSObjectGetPropertyAtIndex (ctx,
308 strresult[i] = seed_value_to_string (ctx, elem, exception);
311 *array_p = strresult;
314 case GI_TYPE_TAG_GTYPE:
318 typeresult = g_new0 (GType, length + 1);
320 for (i = 0; i < length; i++)
322 elem = JSObjectGetPropertyAtIndex (ctx,
325 typeresult[i] = seed_value_to_int (ctx, elem, exception);
328 *array_p = typeresult;
331 case GI_TYPE_TAG_FLOAT:
335 floatresult = g_new0 (gfloat, length + 1);
337 for (i = 0; i < length; i++)
339 elem = JSObjectGetPropertyAtIndex (ctx,
342 floatresult[i] = seed_value_to_float (ctx, elem, exception);
345 *array_p = floatresult;
348 case GI_TYPE_TAG_DOUBLE:
352 dblresult = g_new0 (gdouble, length + 1);
354 for (i = 0; i < length; i++)
356 elem = JSObjectGetPropertyAtIndex (ctx,
359 dblresult[i] = seed_value_to_double (ctx, elem, exception);
362 *array_p = dblresult;
365 case GI_TYPE_TAG_INT:
369 intresult = g_new0 (gint, length + 1);
371 for (i = 0; i < length; i++)
373 elem = JSObjectGetPropertyAtIndex (ctx,
376 intresult[i] = seed_value_to_int (ctx, elem, exception);
379 *array_p = intresult;
382 case GI_TYPE_TAG_UINT8:
384 guint8 *guint8result;
386 guint8result = g_new0 (guint8, length + 1);
388 for (i = 0; i < length; i++)
390 elem = JSObjectGetPropertyAtIndex (ctx,
393 guint8result[i] = seed_value_to_uchar (ctx, elem, exception);
396 *array_p = guint8result;
399 case GI_TYPE_TAG_INTERFACE:
401 GIBaseInfo *interface = g_type_info_get_interface (param_type);
402 GIInfoType interface_type = g_base_info_get_type (interface);
403 if (interface_type == GI_INFO_TYPE_OBJECT
404 || interface_type == GI_INFO_TYPE_INTERFACE
405 || interface_type == GI_INFO_TYPE_STRUCT)
408 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
410 if (g_type_is_a (type, G_TYPE_VALUE))
414 // TODO:FIXME: Robb. Valgrind thinks there's a leak here,
415 // at least while running Same Seed.
416 gvalresult = g_new0 (GValue, length + 1);
418 for (i = 0; i < length; i++)
420 elem = JSObjectGetPropertyAtIndex (ctx,
423 seed_gvalue_from_seed_value (ctx, elem,
425 &gvalresult[i], exception);
427 *array_p = gvalresult;
429 g_base_info_unref (interface);
434 g_base_info_unref (interface);
437 seed_make_exception (ctx, exception, "ArgumentError",
438 "Unhandled array element type");
446 seed_gi_make_argument (JSContextRef ctx,
448 GITypeInfo * type_info,
450 JSValueRef * exception)
452 GITypeTag gi_tag = g_type_info_get_tag (type_info);
454 // FIXME: Some types are not "nullable", also need to check if argument
455 // can be null before doing this.
456 if (!value || JSValueIsNull (ctx, value))
464 case GI_TYPE_TAG_VOID:
466 case GI_TYPE_TAG_BOOLEAN:
467 arg->v_boolean = seed_value_to_boolean (ctx, value, exception);
469 case GI_TYPE_TAG_INT8:
470 arg->v_int8 = seed_value_to_char (ctx, value, exception);
472 case GI_TYPE_TAG_UINT8:
473 arg->v_uint8 = seed_value_to_uchar (ctx, value, exception);
475 case GI_TYPE_TAG_INT16:
476 arg->v_int16 = seed_value_to_int (ctx, value, exception);
478 case GI_TYPE_TAG_UINT16:
479 arg->v_uint16 = seed_value_to_uint (ctx, value, exception);
481 case GI_TYPE_TAG_INT32:
482 arg->v_int32 = seed_value_to_int (ctx, value, exception);
484 case GI_TYPE_TAG_UINT32:
485 arg->v_uint32 = seed_value_to_uint (ctx, value, exception);
487 case GI_TYPE_TAG_LONG:
488 arg->v_long = seed_value_to_long (ctx, value, exception);
490 case GI_TYPE_TAG_INT64:
491 arg->v_int64 = seed_value_to_int64 (ctx, value, exception);
493 case GI_TYPE_TAG_ULONG:
494 arg->v_ulong = seed_value_to_ulong (ctx, value, exception);
496 case GI_TYPE_TAG_UINT64:
497 arg->v_uint64 = seed_value_to_uint64 (ctx, value, exception);
499 case GI_TYPE_TAG_INT:
500 arg->v_int = seed_value_to_int (ctx, value, exception);
502 case GI_TYPE_TAG_UINT:
503 arg->v_uint = seed_value_to_uint (ctx, value, exception);
505 case GI_TYPE_TAG_SIZE:
506 arg->v_size = seed_value_to_size (ctx, value, exception);
508 case GI_TYPE_TAG_SSIZE:
509 arg->v_ssize = seed_value_to_ssize (ctx, value, exception);
511 case GI_TYPE_TAG_FLOAT:
512 arg->v_float = seed_value_to_float (ctx, value, exception);
514 case GI_TYPE_TAG_DOUBLE:
515 arg->v_double = seed_value_to_double (ctx, value, exception);
517 case GI_TYPE_TAG_UTF8:
518 arg->v_string = seed_value_to_string (ctx, value, exception);
520 case GI_TYPE_TAG_FILENAME:
521 arg->v_string = seed_value_to_filename (ctx, value, exception);
523 case GI_TYPE_TAG_GTYPE:
524 arg->v_int = seed_value_to_int (ctx, value, exception);
526 case GI_TYPE_TAG_TIME_T:
527 arg->v_long = seed_value_to_time_t (ctx, value, exception);
529 case GI_TYPE_TAG_INTERFACE:
531 GIBaseInfo *interface;
532 GIInfoType interface_type;
533 GType required_gtype;
536 interface = g_type_info_get_interface (type_info);
537 interface_type = g_base_info_get_type (interface);
539 arg->v_pointer = NULL;
541 if (interface_type == GI_INFO_TYPE_OBJECT
542 || interface_type == GI_INFO_TYPE_INTERFACE)
544 gobject = seed_value_to_object (ctx, value, exception);
546 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
549 // FIXME: Not clear if the g_type_is_a check is desired here.
550 // Possibly 'breaks things' when we don't have introspection
551 // data for some things in an interface hierarchy. Hasn't
552 // provided any problems so far.
554 || !g_type_is_a (G_OBJECT_TYPE (gobject), required_gtype))
556 g_base_info_unref (interface);
560 arg->v_pointer = gobject;
561 g_base_info_unref (interface);
564 else if (interface_type == GI_INFO_TYPE_ENUM ||
565 interface_type == GI_INFO_TYPE_FLAGS)
567 arg->v_long = seed_value_to_long (ctx, value, exception);
568 if (!(interface_type == GI_INFO_TYPE_FLAGS)
569 && !seed_validate_enum ((GIEnumInfo *) interface,
572 seed_make_exception (ctx, exception, "EnumRange",
573 "Enum value: %ld is out of range",
575 g_base_info_unref (interface);
580 g_base_info_unref (interface);
583 else if (interface_type == GI_INFO_TYPE_STRUCT)
585 if (JSValueIsObjectOfClass (ctx, value, seed_struct_class))
586 arg->v_pointer = seed_pointer_get_pointer (ctx, value);
590 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo
594 g_base_info_unref (interface);
597 else if (type == G_TYPE_VALUE)
599 GValue *gval = g_slice_alloc0 (sizeof (GValue));
600 seed_gvalue_from_seed_value (ctx,
604 arg->v_pointer = gval;
606 g_base_info_unref (interface);
609 // Automatically convert between functions and
610 // GClosures where expected.
611 else if (g_type_is_a (type, G_TYPE_CLOSURE))
613 if (JSObjectIsFunction (ctx, (JSObjectRef) value))
616 seed_closure_new (ctx, (JSObjectRef) value, NULL,
623 seed_construct_struct_type_with_parameters (ctx,
627 arg->v_pointer = seed_pointer_get_pointer (ctx, strukt);
630 g_base_info_unref (interface);
633 else if (interface_type == GI_INFO_TYPE_CALLBACK)
635 if (JSValueIsNull (ctx, value))
637 arg->v_pointer = NULL;
638 g_base_info_unref (interface);
641 // Someone passes in a wrapper around a method where a
642 // callback is expected, i.e Clutter.sine_inc_func, as an alpha
643 // Have to dlsym the symbol to be able to do this.
644 // NOTE: Some cases where dlsym(NULL, symbol) doesn't work depending
645 // On how libseed is loaded.
646 else if (JSValueIsObjectOfClass (ctx,
647 value, gobject_method_class))
649 GIFunctionInfo *info =
650 JSObjectGetPrivate ((JSObjectRef) value);
651 const gchar *symbol = g_function_info_get_symbol (info);
656 fp = (void *) dlsym (0, symbol);
657 if ((error = dlerror ()) != NULL)
659 g_critical ("dlerror: %s \n", error);
664 g_base_info_unref (interface);
668 // Somewhat deprecated from when it was necessary to manually
669 // create closure objects...
670 else if (JSValueIsObjectOfClass (ctx,
672 seed_native_callback_class))
674 SeedNativeClosure *privates =
675 (SeedNativeClosure *)
676 JSObjectGetPrivate ((JSObjectRef) value);
677 arg->v_pointer = privates->closure;
678 g_base_info_unref (interface);
681 // Automagically create closure around function passed in as
683 else if (JSObjectIsFunction (ctx, (JSObjectRef) value))
685 SeedNativeClosure *privates = seed_make_native_closure (ctx,
686 (GICallableInfo *) interface,
688 arg->v_pointer = privates->closure;
689 g_base_info_unref (interface);
695 case GI_TYPE_TAG_ARRAY:
697 if (JSValueIsNull (ctx, value))
699 arg->v_pointer = NULL;
702 else if (!JSValueIsObject (ctx, value))
704 // TODO: FIXME: Is this right?
709 GITypeInfo *param_type;
710 //TODO: FIXME: Better array test like the cool one on reddit.
712 seed_value_to_int (ctx, seed_object_get_property (ctx,
719 arg->v_pointer = NULL;
723 param_type = g_type_info_get_param_type (type_info, 0);
724 if (!seed_gi_make_array (ctx, value, length, param_type,
725 &arg->v_pointer, exception))
727 g_base_info_unref ((GIBaseInfo *) param_type);
730 g_base_info_unref ((GIBaseInfo *) param_type);
743 seed_gi_argument_make_js (JSContextRef ctx,
744 GArgument * arg, GITypeInfo * type_info,
745 JSValueRef * exception)
747 GITypeTag gi_tag = g_type_info_get_tag (type_info);
750 case GI_TYPE_TAG_VOID:
751 return JSValueMakeUndefined (ctx);
752 case GI_TYPE_TAG_BOOLEAN:
753 return seed_value_from_boolean (ctx, arg->v_boolean, exception);
754 case GI_TYPE_TAG_INT8:
755 return seed_value_from_char (ctx, arg->v_int8, exception);
756 case GI_TYPE_TAG_UINT8:
757 return seed_value_from_uchar (ctx, arg->v_uint8, exception);
758 case GI_TYPE_TAG_INT16:
759 return seed_value_from_int (ctx, arg->v_int16, exception);
760 case GI_TYPE_TAG_UINT16:
761 return seed_value_from_uint (ctx, arg->v_uint16, exception);
762 case GI_TYPE_TAG_INT32:
763 return seed_value_from_int (ctx, arg->v_int32, exception);
764 case GI_TYPE_TAG_UINT32:
765 return seed_value_from_uint (ctx, arg->v_uint32, exception);
766 case GI_TYPE_TAG_LONG:
767 return seed_value_from_long (ctx, arg->v_long, exception);
768 case GI_TYPE_TAG_INT64:
769 return seed_value_from_int64 (ctx, arg->v_int64, exception);
770 case GI_TYPE_TAG_ULONG:
771 return seed_value_from_ulong (ctx, arg->v_ulong, exception);
772 case GI_TYPE_TAG_UINT64:
773 return seed_value_from_uint64 (ctx, arg->v_uint64, exception);
774 case GI_TYPE_TAG_INT:
775 return seed_value_from_int (ctx, arg->v_int32, exception);
776 case GI_TYPE_TAG_UINT:
777 return seed_value_from_uint (ctx, arg->v_uint32, exception);
778 case GI_TYPE_TAG_SSIZE:
779 return seed_value_from_ssize (ctx, arg->v_ssize, exception);
780 case GI_TYPE_TAG_SIZE:
781 return seed_value_from_size (ctx, arg->v_size, exception);
782 case GI_TYPE_TAG_FLOAT:
783 return seed_value_from_float (ctx, arg->v_float, exception);
784 case GI_TYPE_TAG_DOUBLE:
785 return seed_value_from_double (ctx, arg->v_double, exception);
786 case GI_TYPE_TAG_UTF8:
787 return seed_value_from_string (ctx, arg->v_string, exception);
788 case GI_TYPE_TAG_FILENAME:
789 return seed_value_from_filename (ctx, arg->v_string, exception);
790 case GI_TYPE_TAG_GTYPE:
791 return seed_value_from_int (ctx, arg->v_int, exception);
792 case GI_TYPE_TAG_TIME_T:
793 return seed_value_from_time_t (ctx, arg->v_long, exception);
794 case GI_TYPE_TAG_ARRAY:
796 GITypeInfo *param_type;
799 if (arg->v_pointer == NULL)
800 return JSValueMakeNull (ctx);
801 if (!g_type_info_is_zero_terminated (type_info))
804 param_type = g_type_info_get_param_type (type_info, 0);
806 ret = seed_gi_make_jsarray (ctx, arg->v_pointer, param_type,
809 g_base_info_unref ((GIBaseInfo *) param_type);
813 case GI_TYPE_TAG_INTERFACE:
815 GIBaseInfo *interface;
816 GIInfoType interface_type;
818 interface = g_type_info_get_interface (type_info);
819 interface_type = g_base_info_get_type (interface);
821 if (interface_type == GI_INFO_TYPE_OBJECT ||
822 interface_type == GI_INFO_TYPE_INTERFACE)
824 if (arg->v_pointer == 0)
826 g_base_info_unref (interface);
827 return JSValueMakeNull (ctx);
829 g_base_info_unref (interface);
830 return seed_value_from_object (ctx, arg->v_pointer, exception);
832 else if (interface_type == GI_INFO_TYPE_ENUM
833 || interface_type == GI_INFO_TYPE_FLAGS)
835 g_base_info_unref (interface);
836 return seed_value_from_long (ctx, arg->v_long, exception);
838 else if (interface_type == GI_INFO_TYPE_STRUCT)
842 strukt = seed_make_struct (ctx, arg->v_pointer, interface);
843 g_base_info_unref (interface);
848 case GI_TYPE_TAG_GLIST:
850 GITypeInfo *list_type;
854 GList *list = arg->v_pointer;
856 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
857 list_type = g_type_info_get_param_type (type_info, 0);
859 for (; list != NULL; list = list->next)
863 larg.v_pointer = list->data;
865 (JSValueRef) seed_gi_argument_make_js (ctx, &larg,
866 list_type, exception);
868 ival = JSValueMakeNull (ctx);
869 JSObjectSetPropertyAtIndex (ctx, ret, i, ival, NULL);
875 case GI_TYPE_TAG_GSLIST:
877 GITypeInfo *list_type;
882 GSList *list = arg->v_pointer;
884 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
885 list_type = g_type_info_get_param_type (type_info, 0);
887 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);
909 seed_value_from_gvalue (JSContextRef ctx,
910 GValue * gval, JSValueRef * exception)
912 if (!G_IS_VALUE (gval))
916 switch (G_VALUE_TYPE (gval))
919 return seed_value_from_boolean (ctx,
920 g_value_get_boolean (gval), exception);
922 return seed_value_from_char (ctx, g_value_get_char (gval), exception);
924 return seed_value_from_uchar (ctx, g_value_get_uchar (gval), exception);
926 return seed_value_from_int (ctx, g_value_get_int (gval), exception);
928 return seed_value_from_uint (ctx, g_value_get_uint (gval), exception);
930 return seed_value_from_long (ctx, g_value_get_long (gval), exception);
932 return seed_value_from_ulong (ctx, g_value_get_ulong (gval), exception);
934 return seed_value_from_int64 (ctx, g_value_get_int64 (gval), exception);
936 return seed_value_from_uint64 (ctx, g_value_get_uint64 (gval),
939 return seed_value_from_float (ctx, g_value_get_float (gval), exception);
941 return seed_value_from_double (ctx, g_value_get_double (gval),
944 return seed_value_from_string (ctx, (gchar *)
945 g_value_get_string (gval), exception);
947 return seed_make_pointer (ctx, g_value_get_pointer (gval));
949 // Might need to dup and make a boxed.
950 return seed_make_pointer (ctx, g_value_get_param (gval));
953 if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM) ||
954 g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_FLAGS))
955 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
956 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM))
957 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
958 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_OBJECT))
960 GObject *obj = g_value_get_object (gval);
961 return seed_value_from_object (ctx, obj, exception);
968 info = g_irepository_find_by_gtype (0, G_VALUE_TYPE (gval));
971 type = g_base_info_get_type (info);
973 if (type == GI_INFO_TYPE_UNION)
975 return seed_make_union (ctx, g_value_peek_pointer (gval), info);
977 else if (type == GI_INFO_TYPE_STRUCT)
979 return seed_make_struct (ctx, g_value_peek_pointer (gval), info);
981 else if (type == GI_INFO_TYPE_BOXED)
983 return seed_make_boxed (ctx, g_value_dup_boxed (gval), info);
992 seed_gvalue_from_seed_value (JSContextRef ctx,
994 GType type, GValue * ret, JSValueRef * exception)
996 if (G_IS_VALUE (ret))
999 if (type == G_TYPE_STRV)
1005 if (JSValueIsNull (ctx, val) || !JSValueIsObject (ctx, val))
1008 jslen = seed_object_get_property (ctx, (JSObjectRef) val, "length");
1009 length = seed_value_to_uint (ctx, jslen, exception);
1011 result = g_new0 (gchar *, length+1);
1013 for (i = 0; i < length; i++)
1015 result[i] = seed_value_to_string (ctx,
1016 JSObjectGetPropertyAtIndex (ctx,
1026 g_value_init (ret, G_TYPE_STRV);
1027 g_value_take_boxed (ret, result);
1031 else if (g_type_is_a (type, G_TYPE_ENUM) && JSValueIsNumber (ctx, val))
1033 g_value_init (ret, type);
1034 g_value_set_enum (ret, seed_value_to_long (ctx, val, exception));
1037 else if (g_type_is_a (type, G_TYPE_FLAGS) && JSValueIsNumber (ctx, val))
1039 g_value_init (ret, type);
1040 g_value_set_flags (ret, seed_value_to_long (ctx, val, exception));
1043 else if (g_type_is_a (type, G_TYPE_OBJECT)
1044 && (JSValueIsNull (ctx, val) || seed_value_is_gobject (ctx, val)))
1046 GObject *o = seed_value_to_object (ctx,
1049 if (o == NULL || g_type_is_a (G_OBJECT_TYPE (o), type))
1051 g_value_init (ret, G_TYPE_OBJECT);
1052 g_value_set_object (ret, o);
1057 /* Boxed handling is broken. Will be fixed in struct overhall. */
1058 else if (g_type_is_a (type, G_TYPE_BOXED))
1060 gpointer p = seed_pointer_get_pointer (ctx, val);
1063 g_value_init (ret, type);
1064 g_value_set_boxed (ret, p);
1069 if (JSValueIsObject (ctx, val))
1071 GIBaseInfo *info = g_irepository_find_by_gtype (0, type);
1072 JSObjectRef new_struct;
1077 seed_construct_struct_type_with_parameters (ctx,
1081 p = seed_pointer_get_pointer (ctx, new_struct);
1084 g_value_init (ret, type);
1085 g_value_set_boxed (ret, p);
1086 g_base_info_unref (info);
1089 g_base_info_unref (info);
1096 case G_TYPE_BOOLEAN:
1098 g_value_init (ret, G_TYPE_BOOLEAN);
1099 g_value_set_boolean (ret, seed_value_to_boolean (ctx,
1106 g_value_init (ret, type);
1107 if (type == G_TYPE_INT)
1108 g_value_set_int (ret, seed_value_to_int (ctx, val, exception));
1110 g_value_set_uint (ret, seed_value_to_uint (ctx, val, exception));
1115 g_value_init (ret, G_TYPE_CHAR);
1116 g_value_set_char (ret, seed_value_to_char (ctx, val, exception));
1121 g_value_init (ret, G_TYPE_UCHAR);
1122 g_value_set_uchar (ret, seed_value_to_uchar (ctx, val, exception));
1135 g_value_init (ret, G_TYPE_LONG);
1136 g_value_set_long (ret, seed_value_to_long (ctx, val, exception));
1139 g_value_init (ret, G_TYPE_ULONG);
1140 g_value_set_ulong (ret, seed_value_to_ulong (ctx,
1144 g_value_init (ret, G_TYPE_INT64);
1145 g_value_set_int64 (ret, seed_value_to_int64 (ctx,
1149 g_value_init (ret, G_TYPE_UINT64);
1150 g_value_set_uint64 (ret, seed_value_to_uint64 (ctx,
1154 g_value_init (ret, G_TYPE_FLOAT);
1155 g_value_set_float (ret, seed_value_to_float (ctx,
1159 g_value_init (ret, G_TYPE_DOUBLE);
1160 g_value_set_double (ret, seed_value_to_double (ctx,
1168 gchar *cval = seed_value_to_string (ctx, val, exception);
1170 g_value_init (ret, G_TYPE_STRING);
1171 g_value_take_string (ret, cval);
1177 // TODO: FIXME: This whole undefined type area
1178 // needs some heaaavy improvement.
1180 // Support [GObject.TYPE_INT, 3]
1181 // TODO: FIXME: Might crash.
1182 if (type == 0 && JSValueIsObject (ctx, val))
1184 // TODO: FIXME: Better array test like the cool one on reddit.
1185 guint length = seed_value_to_int (ctx,
1186 seed_object_get_property (ctx,
1194 seed_value_to_int (ctx,
1195 JSObjectGetPropertyAtIndex (ctx,
1201 JSObjectGetPropertyAtIndex (ctx, (JSObjectRef) val, 1,
1203 if (type) // Prevents recursion.
1205 return seed_gvalue_from_seed_value (ctx, val,
1206 type, ret, exception);
1208 // TODO: FIXME: Handle better?
1210 g_assert_not_reached ();
1213 switch (JSValueGetType (ctx, val))
1215 case kJSTypeBoolean:
1217 g_value_init (ret, G_TYPE_BOOLEAN);
1218 g_value_set_boolean (ret,
1219 seed_value_to_boolean (ctx,
1225 g_value_init (ret, G_TYPE_DOUBLE);
1226 g_value_set_double (ret,
1227 seed_value_to_double (ctx, val, exception));
1232 gchar *cv = seed_value_to_string (ctx, val,
1235 g_value_init (ret, G_TYPE_STRING);
1236 g_value_take_string (ret, cv);
1250 * seed_object_get_property
1251 * @ctx: A #SeedContext
1252 * @object: A #SeedObject
1253 * @name: The property to get, should be a valid JavaScript identifier
1255 * Returns: The value of the property or %NULL
1258 seed_object_get_property (JSContextRef ctx,
1259 JSObjectRef val, const gchar * name)
1262 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1263 JSValueRef ret = JSObjectGetProperty (ctx,
1267 JSStringRelease (jname);
1273 * seed_object_set_property
1274 * @ctx: A #SeedContext
1275 * @object: A #SeedObject
1276 * @name: The property to set, should be a valid JavaScript identifier
1277 * @value: The value to set the property to.
1279 * Returns: %TRUE on success, %FALSE otherwise.
1282 seed_object_set_property (JSContextRef ctx, JSObjectRef object,
1283 const gchar * name, JSValueRef value)
1285 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1286 JSValueRef exception = NULL;
1290 JSObjectSetProperty (ctx, (JSObjectRef) object, jname, value, 0,
1294 JSStringRelease (jname);
1299 /* TODO: Make some macros or something for making exceptions, code is littered
1300 with annoyingness right now */
1303 * seed_value_to_boolean:
1304 * @ctx: A #SeedContext.
1305 * @val: The #SeedValue to convert.
1306 * @exception: A reference to a #SeedValue in which to store any exceptions.
1307 * Pass %NULL to ignore exceptions.
1309 * Converts the given #SeedValue into a #gboolean. Keep in mind that this will
1310 * not convert a JavaScript number type, only a boolean.
1312 * Return value: The #gboolean represented by @val, or %NULL if an exception
1313 * is raised during the conversion.
1317 seed_value_to_boolean (JSContextRef ctx,
1318 JSValueRef val, JSValueRef * exception)
1320 if (!JSValueIsBoolean (ctx, val) && !JSValueIsNumber (ctx, val))
1322 if (!JSValueIsNull (ctx, val))
1324 seed_make_exception (eng->context, exception, "ConversionError",
1325 "Can not convert Javascript value to boolean");
1332 return JSValueToBoolean (ctx, val);
1336 * seed_value_from_boolean:
1337 * @ctx: A #SeedContext.
1338 * @val: The #gboolean to represent.
1339 * @exception: A reference to a #SeedValue in which to store any exceptions.
1340 * Pass %NULL to ignore exceptions.
1342 * Converts the given #gboolean into a #SeedValue.
1344 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1345 * is raised during the conversion.
1349 seed_value_from_boolean (JSContextRef ctx,
1350 gboolean val, JSValueRef * exception)
1352 return JSValueMakeBoolean (ctx, val);
1356 * seed_value_to_uint:
1357 * @ctx: A #SeedContext.
1358 * @val: The #SeedValue to convert.
1359 * @exception: A reference to a #SeedValue in which to store any exceptions.
1360 * Pass %NULL to ignore exceptions.
1362 * Converts the given #SeedValue into a #guint.
1364 * Return value: The #guint represented by @val, or %NULL if an exception
1365 * is raised during the conversion.
1369 seed_value_to_uint (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1371 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1373 if (!JSValueIsNull (ctx, val))
1375 seed_make_exception (ctx, exception, "ConversionError",
1376 "Can not convert Javascript value to"
1382 return (guint) JSValueToNumber (ctx, val, NULL);
1386 * seed_value_from_uint:
1387 * @ctx: A #SeedContext.
1388 * @val: The #guint to represent.
1389 * @exception: A reference to a #SeedValue in which to store any exceptions.
1390 * Pass %NULL to ignore exceptions.
1392 * Converts the given #guint into a #SeedValue.
1394 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1395 * is raised during the conversion.
1399 seed_value_from_uint (JSContextRef ctx, guint val, JSValueRef * exception)
1401 return JSValueMakeNumber (ctx, (gdouble) val);
1405 * seed_value_to_int:
1406 * @ctx: A #SeedContext.
1407 * @val: The #SeedValue to convert.
1408 * @exception: A reference to a #SeedValue in which to store any exceptions.
1409 * Pass %NULL to ignore exceptions.
1411 * Converts the given #SeedValue into a #gint.
1413 * Return value: The #gint represented by @val, or %NULL if an exception
1414 * is raised during the conversion.
1418 seed_value_to_int (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1420 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1422 if (!JSValueIsNull (ctx, val))
1423 seed_make_exception (ctx, exception, "ConversionError",
1424 "Can not convert Javascript value to" " int");
1428 return (gint) JSValueToNumber (ctx, val, NULL);
1432 * seed_value_from_int:
1433 * @ctx: A #SeedContext.
1434 * @val: The #gint to represent.
1435 * @exception: A reference to a #SeedValue in which to store any exceptions.
1436 * Pass %NULL to ignore exceptions.
1438 * Converts the given #gint into a #SeedValue.
1440 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1441 * is raised during the conversion.
1445 seed_value_from_int (JSContextRef ctx, gint val, JSValueRef * exception)
1447 return JSValueMakeNumber (ctx, (gdouble) val);
1451 * seed_value_to_char:
1452 * @ctx: A #SeedContext.
1453 * @val: The #SeedValue to convert.
1454 * @exception: A reference to a #SeedValue in which to store any exceptions.
1455 * Pass %NULL to ignore exceptions.
1457 * Converts the given #SeedValue into a #gchar.
1459 * Return value: The #gchar represented by @val, or %NULL if an exception
1460 * is raised during the conversion.
1464 seed_value_to_char (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1468 if (!JSValueIsNumber (ctx, val))
1470 if (!JSValueIsNull (ctx, val))
1471 seed_make_exception (ctx, exception, "ConversionError",
1472 "Can not convert Javascript value to" " gchar");
1476 cv = JSValueToNumber (ctx, val, NULL);
1478 if (cv < G_MININT8 || cv > G_MAXINT8)
1480 seed_make_exception (ctx, exception, "ConversionError",
1481 "Javascript number out of range of gchar");
1489 * seed_value_from_char:
1490 * @ctx: A #SeedContext.
1491 * @val: The #gchar to represent.
1492 * @exception: A reference to a #SeedValue in which to store any exceptions.
1493 * Pass %NULL to ignore exceptions.
1495 * Converts the given #gchar into a #SeedValue.
1497 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1498 * is raised during the conversion.
1502 seed_value_from_char (JSContextRef ctx, gchar val, JSValueRef * exception)
1504 return JSValueMakeNumber (ctx, (gdouble) val);
1508 * seed_value_to_uchar:
1509 * @ctx: A #SeedContext.
1510 * @val: The #SeedValue to convert.
1511 * @exception: A reference to a #SeedValue in which to store any exceptions.
1512 * Pass %NULL to ignore exceptions.
1514 * Converts the given #SeedValue into a #guchar.
1516 * Return value: The #guchar represented by @val, or %NULL if an exception
1517 * is raised during the conversion.
1521 seed_value_to_uchar (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1525 if (!JSValueIsNumber (ctx, val))
1527 if (!JSValueIsNull (ctx, val))
1528 seed_make_exception (ctx, exception, "ConversionError",
1529 "Can not convert Javascript value to" " guchar");
1533 cv = JSValueToNumber (ctx, val, NULL);
1535 if (cv > G_MAXUINT8)
1537 seed_make_exception (ctx, exception, "ConversionError",
1538 "Javascript number out of range of guchar");
1546 * seed_value_from_uchar:
1547 * @ctx: A #SeedContext.
1548 * @val: The #guchar to represent.
1549 * @exception: A reference to a #SeedValue in which to store any exceptions.
1550 * Pass %NULL to ignore exceptions.
1552 * Converts the given #guchar into a #SeedValue.
1554 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1555 * is raised during the conversion.
1559 seed_value_from_uchar (JSContextRef ctx, guchar val, JSValueRef * exception)
1561 return JSValueMakeNumber (ctx, (gdouble) val);
1565 * seed_value_to_short:
1566 * @ctx: A #SeedContext.
1567 * @val: The #SeedValue to convert.
1568 * @exception: A reference to a #SeedValue in which to store any exceptions.
1569 * Pass %NULL to ignore exceptions.
1571 * Converts the given #SeedValue into a #gshort.
1573 * Return value: The #gshort represented by @val, or %NULL if an exception
1574 * is raised during the conversion.
1578 seed_value_to_short (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1580 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1582 if (!JSValueIsNull (ctx, val))
1583 seed_make_exception (ctx, exception, "ConversionError",
1584 "Can not convert Javascript value to" " short");
1588 return (gshort) JSValueToNumber (ctx, val, NULL);
1592 * seed_value_from_short:
1593 * @ctx: A #SeedContext.
1594 * @val: The #gshort to represent.
1595 * @exception: A reference to a #SeedValue in which to store any exceptions.
1596 * Pass %NULL to ignore exceptions.
1598 * Converts the given #gshort into a #SeedValue.
1600 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1601 * is raised during the conversion.
1605 seed_value_from_short (JSContextRef ctx, gshort val, JSValueRef * exception)
1607 return JSValueMakeNumber (ctx, (gdouble) val);
1611 * seed_value_to_ushort:
1612 * @ctx: A #SeedContext.
1613 * @val: The #SeedValue to convert.
1614 * @exception: A reference to a #SeedValue in which to store any exceptions.
1615 * Pass %NULL to ignore exceptions.
1617 * Converts the given #SeedValue into a #gushort.
1619 * Return value: The #gushort represented by @val, or %NULL if an exception
1620 * is raised during the conversion.
1624 seed_value_to_ushort (JSContextRef ctx, JSValueRef val,
1625 JSValueRef * exception)
1627 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1629 if (!JSValueIsNull (ctx, val))
1630 seed_make_exception (ctx, exception, "ConversionError",
1631 "Can not convert Javascript value to" " ushort");
1635 return (gushort) JSValueToNumber (ctx, val, NULL);
1639 * seed_value_from_ushort:
1640 * @ctx: A #SeedContext.
1641 * @val: The #gushort to represent.
1642 * @exception: A reference to a #SeedValue in which to store any exceptions.
1643 * Pass %NULL to ignore exceptions.
1645 * Converts the given #gushort into a #SeedValue.
1647 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1648 * is raised during the conversion.
1652 seed_value_from_ushort (JSContextRef ctx, gushort val, JSValueRef * exception)
1654 return JSValueMakeNumber (ctx, (gdouble) val);
1658 * seed_value_to_long:
1659 * @ctx: A #SeedContext.
1660 * @val: The #SeedValue to convert.
1661 * @exception: A reference to a #SeedValue in which to store any exceptions.
1662 * Pass %NULL to ignore exceptions.
1664 * Converts the given #SeedValue into a #glong.
1666 * Return value: The #glong represented by @val, or %NULL if an exception
1667 * is raised during the conversion.
1671 seed_value_to_long (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1673 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1675 if (!JSValueIsNull (ctx, val))
1676 seed_make_exception (ctx, exception, "ConversionError",
1677 "Can not convert Javascript value to" " long");
1681 return (glong) JSValueToNumber (ctx, val, NULL);
1685 * seed_value_from_long:
1686 * @ctx: A #SeedContext.
1687 * @val: The #glong to represent.
1688 * @exception: A reference to a #SeedValue in which to store any exceptions.
1689 * Pass %NULL to ignore exceptions.
1691 * Converts the given #glong into a #SeedValue.
1693 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1694 * is raised during the conversion.
1698 seed_value_from_long (JSContextRef ctx, glong val, JSValueRef * exception)
1700 return JSValueMakeNumber (ctx, (gdouble) val);
1704 * seed_value_to_ulong:
1705 * @ctx: A #SeedContext.
1706 * @val: The #SeedValue to convert.
1707 * @exception: A reference to a #SeedValue in which to store any exceptions.
1708 * Pass %NULL to ignore exceptions.
1710 * Converts the given #SeedValue into a #gulong.
1712 * Return value: The #gulong represented by @val, or %NULL if an exception
1713 * is raised during the conversion.
1717 seed_value_to_ulong (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1719 if (!JSValueIsNumber (ctx, val))
1721 if (!JSValueIsNull (ctx, val))
1722 seed_make_exception (ctx, exception, "ConversionError",
1723 "Can not convert Javascript value to" " ulong");
1728 return (gulong) JSValueToNumber (ctx, val, NULL);
1732 * seed_value_from_ulong:
1733 * @ctx: A #SeedContext.
1734 * @val: The #gulong to represent.
1735 * @exception: A reference to a #SeedValue in which to store any exceptions.
1736 * Pass %NULL to ignore exceptions.
1738 * Converts the given #gulong into a #SeedValue.
1740 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1741 * is raised during the conversion.
1745 seed_value_from_ulong (JSContextRef ctx, gulong val, JSValueRef * exception)
1747 return JSValueMakeNumber (ctx, (gdouble) val);
1751 * seed_value_to_int64:
1752 * @ctx: A #SeedContext.
1753 * @val: The #SeedValue to convert.
1754 * @exception: A reference to a #SeedValue in which to store any exceptions.
1755 * Pass %NULL to ignore exceptions.
1757 * Converts the given #SeedValue into a #gint64.
1759 * Return value: The #gint64 represented by @val, or %NULL if an exception
1760 * is raised during the conversion.
1764 seed_value_to_int64 (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1766 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1768 if (!JSValueIsNull (ctx, val))
1769 seed_make_exception (ctx, exception, "ConversionError",
1770 "Can not convert Javascript value to" " gint64");
1775 return (gint64) JSValueToNumber (ctx, val, NULL);
1779 * seed_value_from_int64:
1780 * @ctx: A #SeedContext.
1781 * @val: The #gint64 to represent.
1782 * @exception: A reference to a #SeedValue in which to store any exceptions.
1783 * Pass %NULL to ignore exceptions.
1785 * Converts the given #gint64 into a #SeedValue.
1787 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1788 * is raised during the conversion.
1792 seed_value_from_int64 (JSContextRef ctx, gint64 val, JSValueRef * exception)
1794 return JSValueMakeNumber (ctx, (gdouble) val);
1798 * seed_value_to_uint64:
1799 * @ctx: A #SeedContext.
1800 * @val: The #SeedValue to convert.
1801 * @exception: A reference to a #SeedValue in which to store any exceptions.
1802 * Pass %NULL to ignore exceptions.
1804 * Converts the given #SeedValue into a #guint64.
1806 * Return value: The #guint64 represented by @val, or %NULL if an exception
1807 * is raised during the conversion.
1811 seed_value_to_uint64 (JSContextRef ctx,
1812 JSValueRef val, JSValueRef * exception)
1814 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1816 if (!JSValueIsNull (ctx, val))
1817 seed_make_exception (ctx, exception, "ConversionError",
1818 "Can not convert Javascript value to"
1824 return (guint64) JSValueToNumber (ctx, val, NULL);
1828 * seed_value_from_uint64:
1829 * @ctx: A #SeedContext.
1830 * @val: The #guint64 to represent.
1831 * @exception: A reference to a #SeedValue in which to store any exceptions.
1832 * Pass %NULL to ignore exceptions.
1834 * Converts the given #guint64 into a #SeedValue.
1836 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1837 * is raised during the conversion.
1841 seed_value_from_uint64 (JSContextRef ctx, guint64 val, JSValueRef * exception)
1843 return JSValueMakeNumber (ctx, (gdouble) val);
1847 * seed_value_to_float:
1848 * @ctx: A #SeedContext.
1849 * @val: The #SeedValue to convert.
1850 * @exception: A reference to a #SeedValue in which to store any exceptions.
1851 * Pass %NULL to ignore exceptions.
1853 * Converts the given #SeedValue into a #gfloat.
1855 * Return value: The #gfloat represented by @val, or %NULL if an exception
1856 * is raised during the conversion.
1860 seed_value_to_float (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1862 if (!JSValueIsNumber (ctx, val))
1864 if (!JSValueIsNull (ctx, val))
1865 seed_make_exception (ctx, exception, "ConversionError",
1866 "Can not convert Javascript value to" " gfloat");
1870 return (gfloat) JSValueToNumber (ctx, val, NULL);
1874 * seed_value_from_float:
1875 * @ctx: A #SeedContext.
1876 * @val: The #gfloat to represent.
1877 * @exception: A reference to a #SeedValue in which to store any exceptions.
1878 * Pass %NULL to ignore exceptions.
1880 * Converts the given #gfloat into a #SeedValue.
1882 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1883 * is raised during the conversion.
1887 seed_value_from_float (JSContextRef ctx, gfloat val, JSValueRef * exception)
1889 return JSValueMakeNumber (ctx, (gdouble) val);
1893 * seed_value_to_double:
1894 * @ctx: A #SeedContext.
1895 * @val: The #SeedValue to convert.
1896 * @exception: A reference to a #SeedValue in which to store any exceptions.
1897 * Pass %NULL to ignore exceptions.
1899 * Converts the given #SeedValue into a #gdouble.
1901 * Return value: The #gdouble represented by @val, or %NULL if an exception
1902 * is raised during the conversion.
1906 seed_value_to_double (JSContextRef ctx,
1907 JSValueRef val, JSValueRef * exception)
1909 if (!JSValueIsNumber (ctx, val))
1911 if (!JSValueIsNull (ctx, val))
1912 seed_make_exception (ctx, exception, "ConversionError",
1913 "Can not convert Javascript value to" " double");
1917 return (gdouble) JSValueToNumber (ctx, val, NULL);
1921 * seed_value_from_double:
1922 * @ctx: A #SeedContext.
1923 * @val: The #gdouble to represent.
1924 * @exception: A reference to a #SeedValue in which to store any exceptions.
1925 * Pass %NULL to ignore exceptions.
1927 * Converts the given #gdouble into a #SeedValue.
1929 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1930 * is raised during the conversion.
1934 seed_value_from_double (JSContextRef ctx, gdouble val, JSValueRef * exception)
1936 return JSValueMakeNumber (ctx, (gdouble) val);
1940 * seed_value_to_size:
1941 * @ctx: A #SeedContext.
1942 * @val: The #SeedValue to convert.
1943 * @exception: A reference to a #SeedValue in which to store any exceptions.
1944 * Pass %NULL to ignore exceptions.
1946 * Converts the given #SeedValue into a #gsize.
1948 * Return value: The #gsize represented by @val, or %NULL if an exception
1949 * is raised during the conversion.
1953 seed_value_to_size (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1955 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1957 if (!JSValueIsNull (ctx, val))
1958 seed_make_exception (ctx, exception, "ConversionError",
1959 "Can not convert Javascript value to" " gsize");
1963 return (gsize) JSValueToNumber (ctx, val, NULL);
1967 * seed_value_from_size:
1968 * @ctx: A #SeedContext.
1969 * @val: The #gsize to represent.
1970 * @exception: A reference to a #SeedValue in which to store any exceptions.
1971 * Pass %NULL to ignore exceptions.
1973 * Converts the given #gsize into a #SeedValue.
1975 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1976 * is raised during the conversion.
1980 seed_value_from_size (JSContextRef ctx, gsize val, JSValueRef * exception)
1982 return JSValueMakeNumber (ctx, (gdouble) val);
1986 * seed_value_to_ssize:
1987 * @ctx: A #SeedContext.
1988 * @val: The #SeedValue to convert.
1989 * @exception: A reference to a #SeedValue in which to store any exceptions.
1990 * Pass %NULL to ignore exceptions.
1992 * Converts the given #SeedValue into a #gssize.
1994 * Return value: The #gssize represented by @val, or %NULL if an exception
1995 * is raised during the conversion.
1999 seed_value_to_ssize (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
2001 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
2003 if (!JSValueIsNull (ctx, val))
2004 seed_make_exception (ctx, exception, "ConversionError",
2005 "Can not convert Javascript value to" " gssize");
2009 return (gssize) JSValueToNumber (ctx, val, NULL);
2013 * seed_value_from_ssize:
2014 * @ctx: A #SeedContext.
2015 * @val: The #gssize to represent.
2016 * @exception: A reference to a #SeedValue in which to store any exceptions.
2017 * Pass %NULL to ignore exceptions.
2019 * Converts the given #gssize into a #SeedValue.
2021 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2022 * is raised during the conversion.
2026 seed_value_from_ssize (JSContextRef ctx, gssize val, JSValueRef * exception)
2028 return JSValueMakeNumber (ctx, (gdouble) val);
2032 * seed_value_to_string:
2033 * @ctx: A #SeedContext.
2034 * @val: The #SeedValue to convert.
2035 * @exception: A reference to a #SeedValue in which to store any exceptions.
2036 * Pass %NULL to ignore exceptions.
2038 * Converts the given #SeedValue into a #gchar* string. Keep in mind that it's
2039 * up to the caller to free the string.
2041 * If the #SeedValue represents JavaScript's undefined value, this returns
2042 * "[undefined]"; if it represents JavaScript's null value, this returns
2045 * If the #SeedValue is a number or a boolean, it is printed as a double, with
2046 * the printf format string "%.15g".
2048 * If the #SeedValue is an object, the string returned is that obtained by
2049 * calling .toString() on said object.
2051 * Return value: The #gchar* represented by @val, or %NULL if an exception
2052 * is raised during the conversion.
2056 seed_value_to_string (JSContextRef ctx,
2057 JSValueRef val, JSValueRef * exception)
2059 JSStringRef jsstr = NULL;
2060 JSValueRef func, str;
2066 else if (JSValueIsUndefined (ctx, val))
2068 buf = g_strdup ("[undefined]");
2070 else if (JSValueIsNull (ctx, val))
2072 buf = g_strdup ("[null]");
2074 else if (JSValueIsBoolean (ctx, val) || JSValueIsNumber (ctx, val))
2076 buf = g_strdup_printf ("%.15g", JSValueToNumber (ctx, val, NULL));
2080 if (!JSValueIsString (ctx, val)) // In this case,
2084 seed_object_get_property (ctx, (JSObjectRef) val, "toString");
2085 if (!JSValueIsNull (ctx, func) &&
2086 JSValueIsObject (ctx, func) &&
2087 JSObjectIsFunction (ctx, (JSObjectRef) func))
2089 JSObjectCallAsFunction (ctx, (JSObjectRef) func,
2090 (JSObjectRef) val, 0, NULL, NULL);
2093 jsstr = JSValueToStringCopy (ctx, val, NULL);
2094 length = JSStringGetMaximumUTF8CStringSize (jsstr);
2097 buf = g_malloc (length * sizeof (gchar));
2098 JSStringGetUTF8CString (jsstr, buf, length);
2101 JSStringRelease (jsstr);
2108 * seed_value_from_string:
2109 * @ctx: A #SeedContext.
2110 * @val: The #gchar* to represent.
2111 * @exception: A reference to a #SeedValue in which to store any exceptions.
2112 * Pass %NULL to ignore exceptions.
2114 * Converts the given #gchar* string into a #SeedValue.
2116 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2117 * is raised during the conversion.
2121 seed_value_from_string (JSContextRef ctx,
2122 const gchar * val, JSValueRef * exception)
2125 return JSValueMakeNull (ctx);
2128 JSStringRef jsstr = JSStringCreateWithUTF8CString (val);
2129 JSValueRef valstr = JSValueMakeString (ctx, jsstr);
2130 JSStringRelease (jsstr);
2137 * seed_value_from_binary_string:
2138 * @ctx: A #SeedContext.
2139 * @bytes: A string of bytes to represent as a string.
2140 * @n_bytes: The number of bytes from @bytes to convert.
2141 * @exception: A reference to a #SeedValue in which to store any exceptions.
2142 * Pass %NULL to ignore exceptions.
2144 * Converts a string representation of the given binary string
2145 * into a #SeedValue.
2147 * Return value: A #SeedValue which represents @bytes as a string, or %NULL
2148 * if an exception is raised during the conversion.
2152 seed_value_from_binary_string (JSContextRef ctx,
2153 const gchar * bytes,
2154 gint n_bytes, JSValueRef * exception)
2158 gchar *nstr = g_alloca ((n_bytes + 1) * sizeof (gchar));
2159 g_strlcpy (nstr, bytes, n_bytes);
2160 nstr[n_bytes] = '\0';
2162 ret = seed_value_from_string (ctx, nstr, exception);
2168 * seed_value_to_filename:
2169 * @ctx: A #SeedContext.
2170 * @val: The #SeedValue to convert.
2171 * @exception: A reference to a #SeedValue in which to store any exceptions.
2172 * Pass %NULL to ignore exceptions.
2174 * Converts the given #SeedValue into a #gchar*, properly converting to the
2175 * character set used for filenames on the local machine.
2177 * Return value: The #gchar* represented by @val, or %NULL if an exception
2178 * is raised during the conversion.
2182 seed_value_to_filename (JSContextRef ctx,
2183 JSValueRef val, JSValueRef * exception)
2186 gchar *utf8 = seed_value_to_string (ctx, val, exception);
2189 filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, &e);
2193 seed_make_exception_from_gerror (ctx, exception, e);
2202 * seed_value_from_filename:
2203 * @ctx: A #SeedContext.
2204 * @val: The #gchar* filename to represent.
2205 * @exception: A reference to a #SeedValue in which to store any exceptions.
2206 * Pass %NULL to ignore exceptions.
2208 * Converts the given #gchar* filename into a #SeedValue, respecting the
2209 * character set used for filenames on the local machine.
2211 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2212 * is raised during the conversion.
2216 seed_value_from_filename (JSContextRef ctx,
2217 const gchar * val, JSValueRef * exception)
2223 return JSValueMakeNull (ctx);
2226 utf8 = g_filename_to_utf8 (val, -1, NULL, NULL, &e);
2230 seed_make_exception_from_gerror (ctx, exception, e);
2232 return JSValueMakeNull (ctx);
2235 JSValueRef valstr = seed_value_from_string (ctx, utf8, exception);
2244 * seed_value_to_object:
2245 * @ctx: A #SeedContext.
2246 * @val: The #SeedValue to unwrap.
2247 * @exception: A reference to a #SeedValue in which to store any exceptions.
2248 * Pass %NULL to ignore exceptions.
2250 * Given a #SeedValue which is wrapping a #GObject, retrieve the wrapped
2253 * Return value: The #GObject wrapped within @val, or %NULL if an exception
2254 * is raised during the conversion.
2258 seed_value_to_object (JSContextRef ctx,
2259 JSValueRef val, JSValueRef * exception)
2264 * Worth investigating if this is the best way to handle null. Some of
2265 * the existing code depends on null Objects not throwing an exception
2266 * however, needs testing at higher level if value can be null
2270 if (JSValueIsNull (ctx, val))
2272 if (!seed_value_is_gobject (ctx, val))
2274 seed_make_exception (ctx, exception, "ConversionError",
2275 "Attempt to convert from"
2276 " non GObject to GObject");
2280 gobject = (GObject *) JSObjectGetPrivate ((JSObjectRef) val);
2281 g_assert (G_IS_OBJECT (gobject));
2287 * seed_value_from_object:
2288 * @ctx: A #SeedContext.
2289 * @val: The #GObject to wrap.
2290 * @exception: A reference to a #SeedValue in which to store any exceptions.
2291 * Pass %NULL to ignore exceptions.
2293 * Wraps @val in a #SeedValue.
2295 * Return value: A #SeedValue which wraps @val, or %NULL if an exception
2296 * is raised during the conversion.
2300 seed_value_from_object (JSContextRef ctx,
2301 GObject * val, JSValueRef * exception)
2304 return JSValueMakeNull (ctx);
2306 return seed_wrap_object (ctx, val);
2310 seed_validate_enum (GIEnumInfo * info, long val)
2313 GIValueInfo *value_info;
2316 n = g_enum_info_get_n_values (info);
2317 for (i = 0; i < n; i++)
2319 value_info = g_enum_info_get_value (info, i);
2320 value = g_value_info_get_value (value_info);
2322 g_base_info_unref ((GIBaseInfo *) value_info);
2331 seed_value_from_time_t (JSContextRef ctx, time_t time, JSValueRef * exception)
2335 args[0] = seed_value_from_double (ctx, ((gdouble) time) * 1000, exception);
2336 return JSObjectMakeDate (ctx, 1, args, exception);
2340 seed_value_to_time_t (JSContextRef ctx,
2341 JSValueRef value, JSValueRef * exception)
2343 JSValueRef get_time_method;
2348 if (JSValueIsNumber (ctx, value))
2350 return (unsigned long) seed_value_to_long (ctx, value, exception);
2352 else if (JSValueIsObject (ctx, value))
2354 get_time_method = seed_object_get_property (ctx, (JSObjectRef) value,
2356 if (JSValueIsNull (ctx, get_time_method) ||
2357 !JSValueIsObject (ctx, get_time_method))
2361 jstime = JSObjectCallAsFunction (ctx,
2362 (JSObjectRef) get_time_method,
2363 (JSObjectRef) value,
2364 0, NULL, exception);
2365 time = seed_value_to_double (ctx, jstime, exception);
2366 return (unsigned long) (time / 1000);
2370 seed_make_exception (ctx, exception,
2372 "Unable to convert JavaScript value to time_t");