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 case GI_TYPE_TAG_INT64:
489 arg->v_int64 = seed_value_to_long (ctx, value, exception);
491 case GI_TYPE_TAG_ULONG:
492 case GI_TYPE_TAG_UINT64:
493 arg->v_uint64 = seed_value_to_ulong (ctx, value, exception);
495 case GI_TYPE_TAG_INT:
496 arg->v_int = seed_value_to_int (ctx, value, exception);
498 case GI_TYPE_TAG_UINT:
499 arg->v_uint = seed_value_to_uint (ctx, value, exception);
501 case GI_TYPE_TAG_SIZE:
502 case GI_TYPE_TAG_SSIZE:
503 arg->v_int = seed_value_to_int (ctx, value, exception);
505 case GI_TYPE_TAG_FLOAT:
506 arg->v_float = seed_value_to_float (ctx, value, exception);
508 case GI_TYPE_TAG_DOUBLE:
509 arg->v_double = seed_value_to_double (ctx, value, exception);
511 case GI_TYPE_TAG_UTF8:
512 arg->v_string = seed_value_to_string (ctx, value, exception);
514 case GI_TYPE_TAG_FILENAME:
515 arg->v_string = seed_value_to_filename (ctx, value, exception);
517 case GI_TYPE_TAG_GTYPE:
518 arg->v_int = seed_value_to_int (ctx, value, exception);
520 case GI_TYPE_TAG_TIME_T:
521 arg->v_long = seed_value_to_time_t (ctx, value, exception);
523 case GI_TYPE_TAG_INTERFACE:
525 GIBaseInfo *interface;
526 GIInfoType interface_type;
527 GType required_gtype;
530 interface = g_type_info_get_interface (type_info);
531 interface_type = g_base_info_get_type (interface);
533 arg->v_pointer = NULL;
535 if (interface_type == GI_INFO_TYPE_OBJECT
536 || interface_type == GI_INFO_TYPE_INTERFACE)
538 gobject = seed_value_to_object (ctx, value, exception);
540 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)
543 // FIXME: Not clear if the g_type_is_a check is desired here.
544 // Possibly 'breaks things' when we don't have introspection
545 // data for some things in an interface hierarchy. Hasn't
546 // provided any problems so far.
548 || !g_type_is_a (G_OBJECT_TYPE (gobject), required_gtype))
550 g_base_info_unref (interface);
554 arg->v_pointer = gobject;
555 g_base_info_unref (interface);
558 else if (interface_type == GI_INFO_TYPE_ENUM ||
559 interface_type == GI_INFO_TYPE_FLAGS)
561 arg->v_long = seed_value_to_long (ctx, value, exception);
562 if (!(interface_type == GI_INFO_TYPE_FLAGS)
563 && !seed_validate_enum ((GIEnumInfo *) interface,
566 seed_make_exception (ctx, exception, "EnumRange",
567 "Enum value: %ld is out of range",
569 g_base_info_unref (interface);
574 g_base_info_unref (interface);
577 else if (interface_type == GI_INFO_TYPE_STRUCT)
579 if (JSValueIsObjectOfClass (ctx, value, seed_struct_class))
580 arg->v_pointer = seed_pointer_get_pointer (ctx, value);
584 g_registered_type_info_get_g_type ((GIRegisteredTypeInfo
588 g_base_info_unref (interface);
591 else if (type == G_TYPE_VALUE)
593 GValue *gval = g_slice_alloc0 (sizeof (GValue));
594 seed_gvalue_from_seed_value (ctx,
598 arg->v_pointer = gval;
600 g_base_info_unref (interface);
603 // Automatically convert between functions and
604 // GClosures where expected.
605 else if (g_type_is_a (type, G_TYPE_CLOSURE))
607 if (JSObjectIsFunction (ctx, (JSObjectRef) value))
610 seed_closure_new (ctx, (JSObjectRef) value, NULL,
617 seed_construct_struct_type_with_parameters (ctx,
621 arg->v_pointer = seed_pointer_get_pointer (ctx, strukt);
624 g_base_info_unref (interface);
627 else if (interface_type == GI_INFO_TYPE_CALLBACK)
629 if (JSValueIsNull (ctx, value))
631 arg->v_pointer = NULL;
632 g_base_info_unref (interface);
635 // Someone passes in a wrapper around a method where a
636 // callback is expected, i.e Clutter.sine_inc_func, as an alpha
637 // Have to dlsym the symbol to be able to do this.
638 // NOTE: Some cases where dlsym(NULL, symbol) doesn't work depending
639 // On how libseed is loaded.
640 else if (JSValueIsObjectOfClass (ctx,
641 value, gobject_method_class))
643 GIFunctionInfo *info =
644 JSObjectGetPrivate ((JSObjectRef) value);
645 const gchar *symbol = g_function_info_get_symbol (info);
650 fp = (void *) dlsym (0, symbol);
651 if ((error = dlerror ()) != NULL)
653 g_critical ("dlerror: %s \n", error);
658 g_base_info_unref (interface);
662 // Somewhat deprecated from when it was necessary to manually
663 // create closure objects...
664 else if (JSValueIsObjectOfClass (ctx,
666 seed_native_callback_class))
668 SeedNativeClosure *privates =
669 (SeedNativeClosure *)
670 JSObjectGetPrivate ((JSObjectRef) value);
671 arg->v_pointer = privates->closure;
672 g_base_info_unref (interface);
675 // Automagically create closure around function passed in as
677 else if (JSObjectIsFunction (ctx, (JSObjectRef) value))
679 SeedNativeClosure *privates = seed_make_native_closure (ctx,
680 (GICallableInfo *) interface,
683 arg->v_pointer = privates->closure;
684 g_base_info_unref (interface);
690 case GI_TYPE_TAG_ARRAY:
692 if (JSValueIsNull (ctx, value))
694 arg->v_pointer = NULL;
697 else if (!JSValueIsObject (ctx, value))
699 // TODO: FIXME: Is this right?
704 GITypeInfo *param_type;
705 //TODO: FIXME: Better array test like the cool one on reddit.
707 seed_value_to_int (ctx, seed_object_get_property (ctx,
714 arg->v_pointer = NULL;
718 param_type = g_type_info_get_param_type (type_info, 0);
719 if (!seed_gi_make_array (ctx, value, length, param_type,
720 &arg->v_pointer, exception))
722 g_base_info_unref ((GIBaseInfo *) param_type);
725 g_base_info_unref ((GIBaseInfo *) param_type);
738 seed_gi_argument_make_js (JSContextRef ctx,
739 GArgument * arg, GITypeInfo * type_info,
740 JSValueRef * exception)
742 GITypeTag gi_tag = g_type_info_get_tag (type_info);
745 case GI_TYPE_TAG_VOID:
746 return JSValueMakeUndefined (ctx);
747 case GI_TYPE_TAG_BOOLEAN:
748 return seed_value_from_boolean (ctx, arg->v_boolean, exception);
749 case GI_TYPE_TAG_INT8:
750 return seed_value_from_char (ctx, arg->v_int8, exception);
751 case GI_TYPE_TAG_UINT8:
752 return seed_value_from_uchar (ctx, arg->v_uint8, exception);
753 case GI_TYPE_TAG_INT16:
754 return seed_value_from_int (ctx, arg->v_int16, exception);
755 case GI_TYPE_TAG_UINT16:
756 return seed_value_from_uint (ctx, arg->v_uint16, exception);
757 case GI_TYPE_TAG_INT32:
758 return seed_value_from_int (ctx, arg->v_int32, exception);
759 case GI_TYPE_TAG_UINT32:
760 return seed_value_from_uint (ctx, arg->v_uint32, exception);
761 case GI_TYPE_TAG_LONG:
762 case GI_TYPE_TAG_INT64:
763 return seed_value_from_long (ctx, arg->v_int64, exception);
764 case GI_TYPE_TAG_ULONG:
765 case GI_TYPE_TAG_UINT64:
766 return seed_value_from_ulong (ctx, arg->v_uint64, exception);
767 case GI_TYPE_TAG_INT:
768 return seed_value_from_int (ctx, arg->v_int32, exception);
769 case GI_TYPE_TAG_UINT:
770 return seed_value_from_uint (ctx, arg->v_uint32, exception);
771 case GI_TYPE_TAG_SSIZE:
772 case GI_TYPE_TAG_SIZE:
773 return seed_value_from_int (ctx, arg->v_int, exception);
774 case GI_TYPE_TAG_FLOAT:
775 return seed_value_from_float (ctx, arg->v_float, exception);
776 case GI_TYPE_TAG_DOUBLE:
777 return seed_value_from_double (ctx, arg->v_double, exception);
778 case GI_TYPE_TAG_UTF8:
779 return seed_value_from_string (ctx, arg->v_string, exception);
780 case GI_TYPE_TAG_FILENAME:
781 return seed_value_from_filename (ctx, arg->v_string, exception);
782 case GI_TYPE_TAG_GTYPE:
783 return seed_value_from_int (ctx, arg->v_int, exception);
784 case GI_TYPE_TAG_TIME_T:
785 return seed_value_from_time_t (ctx, arg->v_long, exception);
786 case GI_TYPE_TAG_ARRAY:
788 GITypeInfo *param_type;
791 if (arg->v_pointer == NULL)
792 return JSValueMakeNull (ctx);
793 if (!g_type_info_is_zero_terminated (type_info))
796 param_type = g_type_info_get_param_type (type_info, 0);
798 ret = seed_gi_make_jsarray (ctx, arg->v_pointer, param_type,
801 g_base_info_unref ((GIBaseInfo *) param_type);
805 case GI_TYPE_TAG_INTERFACE:
807 GIBaseInfo *interface;
808 GIInfoType interface_type;
810 interface = g_type_info_get_interface (type_info);
811 interface_type = g_base_info_get_type (interface);
813 if (interface_type == GI_INFO_TYPE_OBJECT ||
814 interface_type == GI_INFO_TYPE_INTERFACE)
816 if (arg->v_pointer == 0)
818 g_base_info_unref (interface);
819 return JSValueMakeNull (ctx);
821 g_base_info_unref (interface);
822 return seed_value_from_object (ctx, arg->v_pointer, exception);
824 else if (interface_type == GI_INFO_TYPE_ENUM
825 || interface_type == GI_INFO_TYPE_FLAGS)
827 g_base_info_unref (interface);
828 return seed_value_from_long (ctx, arg->v_long, exception);
830 else if (interface_type == GI_INFO_TYPE_STRUCT)
834 strukt = seed_make_struct (ctx, arg->v_pointer, interface);
835 g_base_info_unref (interface);
840 case GI_TYPE_TAG_GLIST:
842 GITypeInfo *list_type;
846 GList *list = arg->v_pointer;
848 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
849 list_type = g_type_info_get_param_type (type_info, 0);
851 for (; list != NULL; list = list->next)
855 larg.v_pointer = list->data;
857 (JSValueRef) seed_gi_argument_make_js (ctx, &larg,
858 list_type, exception);
860 ival = JSValueMakeNull (ctx);
861 JSObjectSetPropertyAtIndex (ctx, ret, i, ival, NULL);
867 case GI_TYPE_TAG_GSLIST:
869 GITypeInfo *list_type;
874 GSList *list = arg->v_pointer;
876 ret = JSObjectMakeArray (ctx, 0, NULL, exception);
877 list_type = g_type_info_get_param_type (type_info, 0);
879 for (; list != NULL; list = list->next)
881 larg.v_pointer = list->data;
883 (JSValueRef) seed_gi_argument_make_js (ctx, &larg,
884 list_type, exception);
886 ival = JSValueMakeNull (ctx);
887 JSObjectSetPropertyAtIndex (ctx, ret, i, ival, NULL);
901 seed_value_from_gvalue (JSContextRef ctx,
902 GValue * gval, JSValueRef * exception)
904 if (!G_IS_VALUE (gval))
908 switch (G_VALUE_TYPE (gval))
911 return seed_value_from_boolean (ctx,
912 g_value_get_boolean (gval), exception);
914 return seed_value_from_char (ctx, g_value_get_char (gval), exception);
916 return seed_value_from_uchar (ctx, g_value_get_uchar (gval), exception);
918 return seed_value_from_int (ctx, g_value_get_int (gval), exception);
920 return seed_value_from_uint (ctx, g_value_get_uint (gval), exception);
922 return seed_value_from_long (ctx, g_value_get_long (gval), exception);
924 return seed_value_from_ulong (ctx, g_value_get_ulong (gval), exception);
926 return seed_value_from_int64 (ctx, g_value_get_int64 (gval), exception);
928 return seed_value_from_uint64 (ctx, g_value_get_uint64 (gval),
931 return seed_value_from_float (ctx, g_value_get_float (gval), exception);
933 return seed_value_from_double (ctx, g_value_get_double (gval),
936 return seed_value_from_string (ctx, (gchar *)
937 g_value_get_string (gval), exception);
939 return seed_make_pointer (ctx, g_value_get_pointer (gval));
941 // Might need to dup and make a boxed.
942 return seed_make_pointer (ctx, g_value_get_param (gval));
945 if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM) ||
946 g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_FLAGS))
947 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
948 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_ENUM))
949 return seed_value_from_long (ctx, gval->data[0].v_long, exception);
950 else if (g_type_is_a (G_VALUE_TYPE (gval), G_TYPE_OBJECT))
952 GObject *obj = g_value_get_object (gval);
953 return seed_value_from_object (ctx, obj, exception);
960 info = g_irepository_find_by_gtype (0, G_VALUE_TYPE (gval));
963 type = g_base_info_get_type (info);
965 if (type == GI_INFO_TYPE_UNION)
967 return seed_make_union (ctx, g_value_peek_pointer (gval), info);
969 else if (type == GI_INFO_TYPE_STRUCT)
971 return seed_make_struct (ctx, g_value_peek_pointer (gval), info);
973 else if (type == GI_INFO_TYPE_BOXED)
975 return seed_make_boxed (ctx, g_value_dup_boxed (gval), info);
984 seed_gvalue_from_seed_value (JSContextRef ctx,
986 GType type, GValue * ret, JSValueRef * exception)
988 if (G_IS_VALUE (ret))
991 if (type == G_TYPE_STRV)
997 if (JSValueIsNull (ctx, val) || !JSValueIsObject (ctx, val))
1000 jslen = seed_object_get_property (ctx, (JSObjectRef) val, "length");
1001 length = seed_value_to_uint (ctx, jslen, exception);
1003 result = g_new0 (gchar *, length+1);
1005 for (i = 0; i < length; i++)
1007 result[i] = seed_value_to_string (ctx,
1008 JSObjectGetPropertyAtIndex (ctx,
1018 g_value_init (ret, G_TYPE_STRV);
1019 g_value_take_boxed (ret, result);
1023 else if (g_type_is_a (type, G_TYPE_ENUM) && JSValueIsNumber (ctx, val))
1025 g_value_init (ret, type);
1026 g_value_set_enum (ret, seed_value_to_long (ctx, val, exception));
1029 else if (g_type_is_a (type, G_TYPE_FLAGS) && JSValueIsNumber (ctx, val))
1031 g_value_init (ret, type);
1032 g_value_set_flags (ret, seed_value_to_long (ctx, val, exception));
1035 else if (g_type_is_a (type, G_TYPE_OBJECT)
1036 && (JSValueIsNull (ctx, val) || seed_value_is_gobject (ctx, val)))
1038 GObject *o = seed_value_to_object (ctx,
1041 if (o == NULL || g_type_is_a (G_OBJECT_TYPE (o), type))
1043 g_value_init (ret, G_TYPE_OBJECT);
1044 g_value_set_object (ret, o);
1049 /* Boxed handling is broken. Will be fixed in struct overhall. */
1050 else if (g_type_is_a (type, G_TYPE_BOXED))
1052 gpointer p = seed_pointer_get_pointer (ctx, val);
1055 g_value_init (ret, type);
1056 g_value_set_boxed (ret, p);
1061 if (JSValueIsObject (ctx, val))
1063 GIBaseInfo *info = g_irepository_find_by_gtype (0, type);
1064 JSObjectRef new_struct;
1069 seed_construct_struct_type_with_parameters (ctx,
1073 p = seed_pointer_get_pointer (ctx, new_struct);
1076 g_value_init (ret, type);
1077 g_value_set_boxed (ret, p);
1078 g_base_info_unref (info);
1081 g_base_info_unref (info);
1088 case G_TYPE_BOOLEAN:
1090 g_value_init (ret, G_TYPE_BOOLEAN);
1091 g_value_set_boolean (ret, seed_value_to_boolean (ctx,
1098 g_value_init (ret, type);
1099 if (type == G_TYPE_INT)
1100 g_value_set_int (ret, seed_value_to_int (ctx, val, exception));
1102 g_value_set_uint (ret, seed_value_to_uint (ctx, val, exception));
1107 g_value_init (ret, G_TYPE_CHAR);
1108 g_value_set_char (ret, seed_value_to_char (ctx, val, exception));
1113 g_value_init (ret, G_TYPE_UCHAR);
1114 g_value_set_uchar (ret, seed_value_to_uchar (ctx, val, exception));
1127 g_value_init (ret, G_TYPE_LONG);
1128 g_value_set_long (ret, seed_value_to_long (ctx, val, exception));
1131 g_value_init (ret, G_TYPE_ULONG);
1132 g_value_set_ulong (ret, seed_value_to_ulong (ctx,
1136 g_value_init (ret, G_TYPE_INT64);
1137 g_value_set_int64 (ret, seed_value_to_int64 (ctx,
1141 g_value_init (ret, G_TYPE_UINT64);
1142 g_value_set_uint64 (ret, seed_value_to_uint64 (ctx,
1146 g_value_init (ret, G_TYPE_FLOAT);
1147 g_value_set_float (ret, seed_value_to_float (ctx,
1151 g_value_init (ret, G_TYPE_DOUBLE);
1152 g_value_set_double (ret, seed_value_to_double (ctx,
1160 gchar *cval = seed_value_to_string (ctx, val, exception);
1162 g_value_init (ret, G_TYPE_STRING);
1163 g_value_take_string (ret, cval);
1169 // TODO: FIXME: This whole undefined type area
1170 // needs some heaaavy improvement.
1172 // Support [GObject.TYPE_INT, 3]
1173 // TODO: FIXME: Might crash.
1174 if (type == 0 && JSValueIsObject (ctx, val))
1176 // TODO: FIXME: Better array test like the cool one on reddit.
1177 guint length = seed_value_to_int (ctx,
1178 seed_object_get_property (ctx,
1186 seed_value_to_int (ctx,
1187 JSObjectGetPropertyAtIndex (ctx,
1193 JSObjectGetPropertyAtIndex (ctx, (JSObjectRef) val, 1,
1195 if (type) // Prevents recursion.
1197 return seed_gvalue_from_seed_value (ctx, val,
1198 type, ret, exception);
1200 // TODO: FIXME: Handle better?
1202 g_assert_not_reached ();
1205 switch (JSValueGetType (ctx, val))
1207 case kJSTypeBoolean:
1209 g_value_init (ret, G_TYPE_BOOLEAN);
1210 g_value_set_boolean (ret,
1211 seed_value_to_boolean (ctx,
1217 g_value_init (ret, G_TYPE_DOUBLE);
1218 g_value_set_double (ret,
1219 seed_value_to_double (ctx, val, exception));
1224 gchar *cv = seed_value_to_string (ctx, val,
1227 g_value_init (ret, G_TYPE_STRING);
1228 g_value_take_string (ret, cv);
1242 * seed_object_get_property
1243 * @ctx: A #SeedContext
1244 * @object: A #SeedObject
1245 * @name: The property to get, should be a valid JavaScript identifier
1247 * Returns: The value of the property or %NULL
1250 seed_object_get_property (JSContextRef ctx,
1251 JSObjectRef val, const gchar * name)
1254 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1255 JSValueRef ret = JSObjectGetProperty (ctx,
1259 JSStringRelease (jname);
1265 * seed_object_set_property
1266 * @ctx: A #SeedContext
1267 * @object: A #SeedObject
1268 * @name: The property to set, should be a valid JavaScript identifier
1269 * @value: The value to set the property to.
1271 * Returns: %TRUE on success, %FALSE otherwise.
1274 seed_object_set_property (JSContextRef ctx, JSObjectRef object,
1275 const gchar * name, JSValueRef value)
1277 JSStringRef jname = JSStringCreateWithUTF8CString (name);
1278 JSValueRef exception = NULL;
1282 JSObjectSetProperty (ctx, (JSObjectRef) object, jname, value, 0,
1286 JSStringRelease (jname);
1291 /* TODO: Make some macros or something for making exceptions, code is littered
1292 with annoyingness right now */
1295 * seed_value_to_boolean:
1296 * @ctx: A #SeedContext.
1297 * @val: The #SeedValue to convert.
1298 * @exception: A reference to a #SeedValue in which to store any exceptions.
1299 * Pass %NULL to ignore exceptions.
1301 * Converts the given #SeedValue into a #gboolean. Keep in mind that this will
1302 * not convert a JavaScript number type, only a boolean.
1304 * Return value: The #gboolean represented by @val, or %NULL if an exception
1305 * is raised during the conversion.
1309 seed_value_to_boolean (JSContextRef ctx,
1310 JSValueRef val, JSValueRef * exception)
1312 if (!JSValueIsBoolean (ctx, val) && !JSValueIsNumber (ctx, val))
1314 if (!JSValueIsNull (ctx, val))
1316 seed_make_exception (eng->context, exception, "ConversionError",
1317 "Can not convert Javascript value to boolean");
1324 return JSValueToBoolean (ctx, val);
1328 * seed_value_from_boolean:
1329 * @ctx: A #SeedContext.
1330 * @val: The #gboolean to represent.
1331 * @exception: A reference to a #SeedValue in which to store any exceptions.
1332 * Pass %NULL to ignore exceptions.
1334 * Converts the given #gboolean into a #SeedValue.
1336 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1337 * is raised during the conversion.
1341 seed_value_from_boolean (JSContextRef ctx,
1342 gboolean val, JSValueRef * exception)
1344 return JSValueMakeBoolean (ctx, val);
1348 * seed_value_to_uint:
1349 * @ctx: A #SeedContext.
1350 * @val: The #SeedValue to convert.
1351 * @exception: A reference to a #SeedValue in which to store any exceptions.
1352 * Pass %NULL to ignore exceptions.
1354 * Converts the given #SeedValue into a #guint.
1356 * Return value: The #guint represented by @val, or %NULL if an exception
1357 * is raised during the conversion.
1361 seed_value_to_uint (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1363 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1365 if (!JSValueIsNull (ctx, val))
1367 seed_make_exception (ctx, exception, "ConversionError",
1368 "Can not convert Javascript value to"
1374 return (guint) JSValueToNumber (ctx, val, NULL);
1378 * seed_value_from_uint:
1379 * @ctx: A #SeedContext.
1380 * @val: The #guint to represent.
1381 * @exception: A reference to a #SeedValue in which to store any exceptions.
1382 * Pass %NULL to ignore exceptions.
1384 * Converts the given #guint into a #SeedValue.
1386 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1387 * is raised during the conversion.
1391 seed_value_from_uint (JSContextRef ctx, guint val, JSValueRef * exception)
1393 return JSValueMakeNumber (ctx, (gdouble) val);
1397 * seed_value_to_int:
1398 * @ctx: A #SeedContext.
1399 * @val: The #SeedValue to convert.
1400 * @exception: A reference to a #SeedValue in which to store any exceptions.
1401 * Pass %NULL to ignore exceptions.
1403 * Converts the given #SeedValue into a #gint.
1405 * Return value: The #gint represented by @val, or %NULL if an exception
1406 * is raised during the conversion.
1410 seed_value_to_int (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1412 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1414 if (!JSValueIsNull (ctx, val))
1415 seed_make_exception (ctx, exception, "ConversionError",
1416 "Can not convert Javascript value to" " int");
1420 return (gint) JSValueToNumber (ctx, val, NULL);
1424 * seed_value_from_int:
1425 * @ctx: A #SeedContext.
1426 * @val: The #gint to represent.
1427 * @exception: A reference to a #SeedValue in which to store any exceptions.
1428 * Pass %NULL to ignore exceptions.
1430 * Converts the given #gint into a #SeedValue.
1432 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1433 * is raised during the conversion.
1437 seed_value_from_int (JSContextRef ctx, gint val, JSValueRef * exception)
1439 return JSValueMakeNumber (ctx, (gdouble) val);
1443 * seed_value_to_char:
1444 * @ctx: A #SeedContext.
1445 * @val: The #SeedValue to convert.
1446 * @exception: A reference to a #SeedValue in which to store any exceptions.
1447 * Pass %NULL to ignore exceptions.
1449 * Converts the given #SeedValue into a #gchar.
1451 * Return value: The #gchar represented by @val, or %NULL if an exception
1452 * is raised during the conversion.
1456 seed_value_to_char (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1460 if (!JSValueIsNumber (ctx, val))
1462 if (!JSValueIsNull (ctx, val))
1463 seed_make_exception (ctx, exception, "ConversionError",
1464 "Can not convert Javascript value to" " gchar");
1468 cv = JSValueToNumber (ctx, val, NULL);
1470 if (cv < G_MININT8 || cv > G_MAXINT8)
1472 seed_make_exception (ctx, exception, "ConversionError",
1473 "Javascript number out of range of gchar");
1481 * seed_value_from_char:
1482 * @ctx: A #SeedContext.
1483 * @val: The #gchar to represent.
1484 * @exception: A reference to a #SeedValue in which to store any exceptions.
1485 * Pass %NULL to ignore exceptions.
1487 * Converts the given #gchar into a #SeedValue.
1489 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1490 * is raised during the conversion.
1494 seed_value_from_char (JSContextRef ctx, gchar val, JSValueRef * exception)
1496 return JSValueMakeNumber (ctx, (gdouble) val);
1500 * seed_value_to_uchar:
1501 * @ctx: A #SeedContext.
1502 * @val: The #SeedValue to convert.
1503 * @exception: A reference to a #SeedValue in which to store any exceptions.
1504 * Pass %NULL to ignore exceptions.
1506 * Converts the given #SeedValue into a #guchar.
1508 * Return value: The #guchar represented by @val, or %NULL if an exception
1509 * is raised during the conversion.
1513 seed_value_to_uchar (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1517 if (!JSValueIsNumber (ctx, val))
1519 if (!JSValueIsNull (ctx, val))
1520 seed_make_exception (ctx, exception, "ConversionError",
1521 "Can not convert Javascript value to" " guchar");
1525 cv = JSValueToNumber (ctx, val, NULL);
1527 if (cv > G_MAXUINT8)
1529 seed_make_exception (ctx, exception, "ConversionError",
1530 "Javascript number out of range of guchar");
1538 * seed_value_from_uchar:
1539 * @ctx: A #SeedContext.
1540 * @val: The #guchar to represent.
1541 * @exception: A reference to a #SeedValue in which to store any exceptions.
1542 * Pass %NULL to ignore exceptions.
1544 * Converts the given #guchar into a #SeedValue.
1546 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1547 * is raised during the conversion.
1551 seed_value_from_uchar (JSContextRef ctx, guchar val, JSValueRef * exception)
1553 return JSValueMakeNumber (ctx, (gdouble) val);
1557 * seed_value_to_short:
1558 * @ctx: A #SeedContext.
1559 * @val: The #SeedValue to convert.
1560 * @exception: A reference to a #SeedValue in which to store any exceptions.
1561 * Pass %NULL to ignore exceptions.
1563 * Converts the given #SeedValue into a #gshort.
1565 * Return value: The #gshort represented by @val, or %NULL if an exception
1566 * is raised during the conversion.
1570 seed_value_to_short (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1572 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1574 if (!JSValueIsNull (ctx, val))
1575 seed_make_exception (ctx, exception, "ConversionError",
1576 "Can not convert Javascript value to" " short");
1580 return (gshort) JSValueToNumber (ctx, val, NULL);
1584 * seed_value_from_short:
1585 * @ctx: A #SeedContext.
1586 * @val: The #gshort to represent.
1587 * @exception: A reference to a #SeedValue in which to store any exceptions.
1588 * Pass %NULL to ignore exceptions.
1590 * Converts the given #gshort into a #SeedValue.
1592 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1593 * is raised during the conversion.
1597 seed_value_from_short (JSContextRef ctx, gshort val, JSValueRef * exception)
1599 return JSValueMakeNumber (ctx, (gdouble) val);
1603 * seed_value_to_ushort:
1604 * @ctx: A #SeedContext.
1605 * @val: The #SeedValue to convert.
1606 * @exception: A reference to a #SeedValue in which to store any exceptions.
1607 * Pass %NULL to ignore exceptions.
1609 * Converts the given #SeedValue into a #gushort.
1611 * Return value: The #gushort represented by @val, or %NULL if an exception
1612 * is raised during the conversion.
1616 seed_value_to_ushort (JSContextRef ctx, JSValueRef val,
1617 JSValueRef * exception)
1619 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1621 if (!JSValueIsNull (ctx, val))
1622 seed_make_exception (ctx, exception, "ConversionError",
1623 "Can not convert Javascript value to" " ushort");
1627 return (gushort) JSValueToNumber (ctx, val, NULL);
1631 * seed_value_from_ushort:
1632 * @ctx: A #SeedContext.
1633 * @val: The #gushort to represent.
1634 * @exception: A reference to a #SeedValue in which to store any exceptions.
1635 * Pass %NULL to ignore exceptions.
1637 * Converts the given #gushort into a #SeedValue.
1639 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1640 * is raised during the conversion.
1644 seed_value_from_ushort (JSContextRef ctx, gushort val, JSValueRef * exception)
1646 return JSValueMakeNumber (ctx, (gdouble) val);
1650 * seed_value_to_long:
1651 * @ctx: A #SeedContext.
1652 * @val: The #SeedValue to convert.
1653 * @exception: A reference to a #SeedValue in which to store any exceptions.
1654 * Pass %NULL to ignore exceptions.
1656 * Converts the given #SeedValue into a #glong.
1658 * Return value: The #glong represented by @val, or %NULL if an exception
1659 * is raised during the conversion.
1663 seed_value_to_long (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1665 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1667 if (!JSValueIsNull (ctx, val))
1668 seed_make_exception (ctx, exception, "ConversionError",
1669 "Can not convert Javascript value to" " long");
1673 return (glong) JSValueToNumber (ctx, val, NULL);
1677 * seed_value_from_long:
1678 * @ctx: A #SeedContext.
1679 * @val: The #glong to represent.
1680 * @exception: A reference to a #SeedValue in which to store any exceptions.
1681 * Pass %NULL to ignore exceptions.
1683 * Converts the given #glong into a #SeedValue.
1685 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1686 * is raised during the conversion.
1690 seed_value_from_long (JSContextRef ctx, glong val, JSValueRef * exception)
1692 return JSValueMakeNumber (ctx, (gdouble) val);
1696 * seed_value_to_ulong:
1697 * @ctx: A #SeedContext.
1698 * @val: The #SeedValue to convert.
1699 * @exception: A reference to a #SeedValue in which to store any exceptions.
1700 * Pass %NULL to ignore exceptions.
1702 * Converts the given #SeedValue into a #gulong.
1704 * Return value: The #gulong represented by @val, or %NULL if an exception
1705 * is raised during the conversion.
1709 seed_value_to_ulong (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1711 if (!JSValueIsNumber (ctx, val))
1713 if (!JSValueIsNull (ctx, val))
1714 seed_make_exception (ctx, exception, "ConversionError",
1715 "Can not convert Javascript value to" " ulong");
1720 return (gulong) JSValueToNumber (ctx, val, NULL);
1724 * seed_value_from_ulong:
1725 * @ctx: A #SeedContext.
1726 * @val: The #gulong to represent.
1727 * @exception: A reference to a #SeedValue in which to store any exceptions.
1728 * Pass %NULL to ignore exceptions.
1730 * Converts the given #gulong into a #SeedValue.
1732 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1733 * is raised during the conversion.
1737 seed_value_from_ulong (JSContextRef ctx, gulong val, JSValueRef * exception)
1739 return JSValueMakeNumber (ctx, (gdouble) val);
1743 * seed_value_to_int64:
1744 * @ctx: A #SeedContext.
1745 * @val: The #SeedValue to convert.
1746 * @exception: A reference to a #SeedValue in which to store any exceptions.
1747 * Pass %NULL to ignore exceptions.
1749 * Converts the given #SeedValue into a #gint64.
1751 * Return value: The #gint64 represented by @val, or %NULL if an exception
1752 * is raised during the conversion.
1756 seed_value_to_int64 (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1758 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1760 if (!JSValueIsNull (ctx, val))
1761 seed_make_exception (ctx, exception, "ConversionError",
1762 "Can not convert Javascript value to" " gint64");
1767 return (gint64) JSValueToNumber (ctx, val, NULL);
1771 * seed_value_from_int64:
1772 * @ctx: A #SeedContext.
1773 * @val: The #gint64 to represent.
1774 * @exception: A reference to a #SeedValue in which to store any exceptions.
1775 * Pass %NULL to ignore exceptions.
1777 * Converts the given #gint64 into a #SeedValue.
1779 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1780 * is raised during the conversion.
1784 seed_value_from_int64 (JSContextRef ctx, gint64 val, JSValueRef * exception)
1786 return JSValueMakeNumber (ctx, (gdouble) val);
1790 * seed_value_to_uint64:
1791 * @ctx: A #SeedContext.
1792 * @val: The #SeedValue to convert.
1793 * @exception: A reference to a #SeedValue in which to store any exceptions.
1794 * Pass %NULL to ignore exceptions.
1796 * Converts the given #SeedValue into a #guint64.
1798 * Return value: The #guint64 represented by @val, or %NULL if an exception
1799 * is raised during the conversion.
1803 seed_value_to_uint64 (JSContextRef ctx,
1804 JSValueRef val, JSValueRef * exception)
1806 if (!JSValueIsNumber (ctx, val) && !JSValueIsBoolean (ctx, val))
1808 if (!JSValueIsNull (ctx, val))
1809 seed_make_exception (ctx, exception, "ConversionError",
1810 "Can not convert Javascript value to"
1816 return (guint64) JSValueToNumber (ctx, val, NULL);
1820 * seed_value_from_uint64:
1821 * @ctx: A #SeedContext.
1822 * @val: The #guint64 to represent.
1823 * @exception: A reference to a #SeedValue in which to store any exceptions.
1824 * Pass %NULL to ignore exceptions.
1826 * Converts the given #guint64 into a #SeedValue.
1828 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1829 * is raised during the conversion.
1833 seed_value_from_uint64 (JSContextRef ctx, guint64 val, JSValueRef * exception)
1835 return JSValueMakeNumber (ctx, (gdouble) val);
1839 * seed_value_to_float:
1840 * @ctx: A #SeedContext.
1841 * @val: The #SeedValue to convert.
1842 * @exception: A reference to a #SeedValue in which to store any exceptions.
1843 * Pass %NULL to ignore exceptions.
1845 * Converts the given #SeedValue into a #gfloat.
1847 * Return value: The #gfloat represented by @val, or %NULL if an exception
1848 * is raised during the conversion.
1852 seed_value_to_float (JSContextRef ctx, JSValueRef val, JSValueRef * exception)
1854 if (!JSValueIsNumber (ctx, val))
1856 if (!JSValueIsNull (ctx, val))
1857 seed_make_exception (ctx, exception, "ConversionError",
1858 "Can not convert Javascript value to" " gfloat");
1862 return (gfloat) JSValueToNumber (ctx, val, NULL);
1866 * seed_value_from_float:
1867 * @ctx: A #SeedContext.
1868 * @val: The #gfloat to represent.
1869 * @exception: A reference to a #SeedValue in which to store any exceptions.
1870 * Pass %NULL to ignore exceptions.
1872 * Converts the given #gfloat into a #SeedValue.
1874 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1875 * is raised during the conversion.
1879 seed_value_from_float (JSContextRef ctx, gfloat val, JSValueRef * exception)
1881 return JSValueMakeNumber (ctx, (gdouble) val);
1885 * seed_value_to_double:
1886 * @ctx: A #SeedContext.
1887 * @val: The #SeedValue to convert.
1888 * @exception: A reference to a #SeedValue in which to store any exceptions.
1889 * Pass %NULL to ignore exceptions.
1891 * Converts the given #SeedValue into a #gdouble.
1893 * Return value: The #gdouble represented by @val, or %NULL if an exception
1894 * is raised during the conversion.
1898 seed_value_to_double (JSContextRef ctx,
1899 JSValueRef val, JSValueRef * exception)
1901 if (!JSValueIsNumber (ctx, val))
1903 if (!JSValueIsNull (ctx, val))
1904 seed_make_exception (ctx, exception, "ConversionError",
1905 "Can not convert Javascript value to" " double");
1909 return (gdouble) JSValueToNumber (ctx, val, NULL);
1913 * seed_value_from_double:
1914 * @ctx: A #SeedContext.
1915 * @val: The #gdouble to represent.
1916 * @exception: A reference to a #SeedValue in which to store any exceptions.
1917 * Pass %NULL to ignore exceptions.
1919 * Converts the given #gdouble into a #SeedValue.
1921 * Return value: A #SeedValue which represents @val, or %NULL if an exception
1922 * is raised during the conversion.
1926 seed_value_from_double (JSContextRef ctx, gdouble val, JSValueRef * exception)
1928 return JSValueMakeNumber (ctx, (gdouble) val);
1932 * seed_value_to_string:
1933 * @ctx: A #SeedContext.
1934 * @val: The #SeedValue to convert.
1935 * @exception: A reference to a #SeedValue in which to store any exceptions.
1936 * Pass %NULL to ignore exceptions.
1938 * Converts the given #SeedValue into a #gchar* string. Keep in mind that it's
1939 * up to the caller to free the string.
1941 * If the #SeedValue represents JavaScript's undefined value, this returns
1942 * "[undefined]"; if it represents JavaScript's null value, this returns
1945 * If the #SeedValue is a number or a boolean, it is printed as a double, with
1946 * the printf format string "%.15g".
1948 * If the #SeedValue is an object, the string returned is that obtained by
1949 * calling .toString() on said object.
1951 * Return value: The #gchar* represented by @val, or %NULL if an exception
1952 * is raised during the conversion.
1956 seed_value_to_string (JSContextRef ctx,
1957 JSValueRef val, JSValueRef * exception)
1959 JSStringRef jsstr = NULL;
1960 JSValueRef func, str;
1966 else if (JSValueIsUndefined (ctx, val))
1968 buf = g_strdup ("[undefined]");
1970 else if (JSValueIsNull (ctx, val))
1972 buf = g_strdup ("[null]");
1974 else if (JSValueIsBoolean (ctx, val) || JSValueIsNumber (ctx, val))
1976 buf = g_strdup_printf ("%.15g", JSValueToNumber (ctx, val, NULL));
1980 if (!JSValueIsString (ctx, val)) // In this case,
1984 seed_object_get_property (ctx, (JSObjectRef) val, "toString");
1985 if (!JSValueIsNull (ctx, func) &&
1986 JSValueIsObject (ctx, func) &&
1987 JSObjectIsFunction (ctx, (JSObjectRef) func))
1989 JSObjectCallAsFunction (ctx, (JSObjectRef) func,
1990 (JSObjectRef) val, 0, NULL, NULL);
1993 jsstr = JSValueToStringCopy (ctx, val, NULL);
1994 length = JSStringGetMaximumUTF8CStringSize (jsstr);
1997 buf = g_malloc (length * sizeof (gchar));
1998 JSStringGetUTF8CString (jsstr, buf, length);
2001 JSStringRelease (jsstr);
2008 * seed_value_from_string:
2009 * @ctx: A #SeedContext.
2010 * @val: The #gchar* to represent.
2011 * @exception: A reference to a #SeedValue in which to store any exceptions.
2012 * Pass %NULL to ignore exceptions.
2014 * Converts the given #gchar* string into a #SeedValue.
2016 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2017 * is raised during the conversion.
2021 seed_value_from_string (JSContextRef ctx,
2022 const gchar * val, JSValueRef * exception)
2025 return JSValueMakeNull (ctx);
2028 JSStringRef jsstr = JSStringCreateWithUTF8CString (val);
2029 JSValueRef valstr = JSValueMakeString (ctx, jsstr);
2030 JSStringRelease (jsstr);
2037 * seed_value_from_binary_string:
2038 * @ctx: A #SeedContext.
2039 * @bytes: A string of bytes to represent as a string.
2040 * @n_bytes: The number of bytes from @bytes to convert.
2041 * @exception: A reference to a #SeedValue in which to store any exceptions.
2042 * Pass %NULL to ignore exceptions.
2044 * Converts a string representation of the given binary string
2045 * into a #SeedValue.
2047 * Return value: A #SeedValue which represents @bytes as a string, or %NULL
2048 * if an exception is raised during the conversion.
2052 seed_value_from_binary_string (JSContextRef ctx,
2053 const gchar * bytes,
2054 gint n_bytes, JSValueRef * exception)
2058 gchar *nstr = g_alloca ((n_bytes + 1) * sizeof (gchar));
2059 g_strlcpy (nstr, bytes, n_bytes);
2060 nstr[n_bytes] = '\0';
2062 ret = seed_value_from_string (ctx, nstr, exception);
2068 * seed_value_to_filename:
2069 * @ctx: A #SeedContext.
2070 * @val: The #SeedValue to convert.
2071 * @exception: A reference to a #SeedValue in which to store any exceptions.
2072 * Pass %NULL to ignore exceptions.
2074 * Converts the given #SeedValue into a #gchar*, properly converting to the
2075 * character set used for filenames on the local machine.
2077 * Return value: The #gchar* represented by @val, or %NULL if an exception
2078 * is raised during the conversion.
2082 seed_value_to_filename (JSContextRef ctx,
2083 JSValueRef val, JSValueRef * exception)
2086 gchar *utf8 = seed_value_to_string (ctx, val, exception);
2089 filename = g_filename_from_utf8 (utf8, -1, NULL, NULL, &e);
2093 seed_make_exception_from_gerror (ctx, exception, e);
2102 * seed_value_from_filename:
2103 * @ctx: A #SeedContext.
2104 * @val: The #gchar* filename to represent.
2105 * @exception: A reference to a #SeedValue in which to store any exceptions.
2106 * Pass %NULL to ignore exceptions.
2108 * Converts the given #gchar* filename into a #SeedValue, respecting the
2109 * character set used for filenames on the local machine.
2111 * Return value: A #SeedValue which represents @val, or %NULL if an exception
2112 * is raised during the conversion.
2116 seed_value_from_filename (JSContextRef ctx,
2117 const gchar * val, JSValueRef * exception)
2123 return JSValueMakeNull (ctx);
2126 utf8 = g_filename_to_utf8 (val, -1, NULL, NULL, &e);
2130 seed_make_exception_from_gerror (ctx, exception, e);
2132 return JSValueMakeNull (ctx);
2135 JSValueRef valstr = seed_value_from_string (ctx, utf8, exception);
2144 * seed_value_to_object:
2145 * @ctx: A #SeedContext.
2146 * @val: The #SeedValue to unwrap.
2147 * @exception: A reference to a #SeedValue in which to store any exceptions.
2148 * Pass %NULL to ignore exceptions.
2150 * Given a #SeedValue which is wrapping a #GObject, retrieve the wrapped
2153 * Return value: The #GObject wrapped within @val, or %NULL if an exception
2154 * is raised during the conversion.
2158 seed_value_to_object (JSContextRef ctx,
2159 JSValueRef val, JSValueRef * exception)
2164 * Worth investigating if this is the best way to handle null. Some of
2165 * the existing code depends on null Objects not throwing an exception
2166 * however, needs testing at higher level if value can be null
2170 if (JSValueIsNull (ctx, val))
2172 if (!seed_value_is_gobject (ctx, val))
2174 seed_make_exception (ctx, exception, "ConversionError",
2175 "Attempt to convert from"
2176 " non GObject to GObject");
2180 gobject = (GObject *) JSObjectGetPrivate ((JSObjectRef) val);
2181 g_assert (G_IS_OBJECT (gobject));
2187 * seed_value_from_object:
2188 * @ctx: A #SeedContext.
2189 * @val: The #GObject to wrap.
2190 * @exception: A reference to a #SeedValue in which to store any exceptions.
2191 * Pass %NULL to ignore exceptions.
2193 * Wraps @val in a #SeedValue.
2195 * Return value: A #SeedValue which wraps @val, or %NULL if an exception
2196 * is raised during the conversion.
2200 seed_value_from_object (JSContextRef ctx,
2201 GObject * val, JSValueRef * exception)
2204 return JSValueMakeNull (ctx);
2206 return seed_wrap_object (ctx, val);
2210 seed_validate_enum (GIEnumInfo * info, long val)
2213 GIValueInfo *value_info;
2216 n = g_enum_info_get_n_values (info);
2217 for (i = 0; i < n; i++)
2219 value_info = g_enum_info_get_value (info, i);
2220 value = g_value_info_get_value (value_info);
2222 g_base_info_unref ((GIBaseInfo *) value_info);
2231 seed_value_from_time_t (JSContextRef ctx, time_t time, JSValueRef * exception)
2235 args[0] = seed_value_from_double (ctx, ((gdouble) time) * 1000, exception);
2236 return JSObjectMakeDate (ctx, 1, args, exception);
2240 seed_value_to_time_t (JSContextRef ctx,
2241 JSValueRef value, JSValueRef * exception)
2243 JSValueRef get_time_method;
2248 if (JSValueIsNumber (ctx, value))
2250 return (unsigned long) seed_value_to_long (ctx, value, exception);
2252 else if (JSValueIsObject (ctx, value))
2254 get_time_method = seed_object_get_property (ctx, (JSObjectRef) value,
2256 if (JSValueIsNull (ctx, get_time_method) ||
2257 !JSValueIsObject (ctx, get_time_method))
2261 jstime = JSObjectCallAsFunction (ctx,
2262 (JSObjectRef) get_time_method,
2263 (JSObjectRef) value,
2264 0, NULL, exception);
2265 time = seed_value_to_double (ctx, jstime, exception);
2266 return (unsigned long) (time / 1000);
2270 seed_make_exception (ctx, exception,
2272 "Unable to convert JavaScript value to time_t");