Exemple #1
0
static JSBool
param_new_internal(JSContext *cx,
                   uintN      argc,
                   jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    GParamSpec *pspec = NULL;
    JSBool ret = JS_FALSE;
    gchar *method_name;

    gchar *prop_name;
    JSObject *prop_gtype_jsobj;
    GType prop_gtype;
    GType prop_type;
    gchar *nick;
    gchar *blurb;
    GParamFlags flags;

    if (!gjs_parse_args(cx, "GObject.ParamSpec._new_internal",
                        "!sossi", argc, argv,
                        "prop_name", &prop_name,
                        "prop_gtype", &prop_gtype_jsobj,
                        "nick", &nick,
                        "blurb", &blurb,
                        "flags", &flags))
        return JS_FALSE;

    prop_gtype = gjs_gtype_get_actual_gtype(cx, prop_gtype_jsobj);
    prop_type = G_TYPE_FUNDAMENTAL(prop_gtype);

    method_name = g_strdup_printf("GObject.ParamSpec.%s",
                                  g_type_name(prop_type));

    argv += 5;
    argc -= 5;

    switch (prop_type) {
    case G_TYPE_UCHAR:
    case G_TYPE_CHAR:
	{
	    gchar *minimum, *maximum, *default_value;

            if (!gjs_parse_args(cx, method_name,
                                "sss", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            if (prop_type == G_TYPE_CHAR)
                pspec = g_param_spec_char(prop_name, nick, blurb,
                                          minimum[0], maximum[0], default_value[0],
                                          flags);
            else
                pspec = g_param_spec_uchar(prop_name, nick, blurb,
                                           minimum[0], maximum[0], default_value[0],
                                           flags);
 
            g_free(minimum);
            g_free(maximum);
            g_free(default_value);
	}
	break;
    case G_TYPE_INT:
    case G_TYPE_UINT:
    case G_TYPE_LONG:
    case G_TYPE_ULONG:
    case G_TYPE_INT64:
    case G_TYPE_UINT64:
        {
            gint64 minimum, maximum, default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ttt", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            switch (prop_type) {
            case G_TYPE_INT:
                pspec = g_param_spec_int(prop_name, nick, blurb,
                                         minimum, maximum, default_value, flags);
                break;
            case G_TYPE_UINT:
                pspec = g_param_spec_uint(prop_name, nick, blurb,
                                          minimum, maximum, default_value, flags);
                break;
            case G_TYPE_LONG:
                pspec = g_param_spec_long(prop_name, nick, blurb,
                                          minimum, maximum, default_value, flags);
                break;
            case G_TYPE_ULONG:
                pspec = g_param_spec_ulong(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
                break;
            case G_TYPE_INT64:
                pspec = g_param_spec_int64(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
                break;
            case G_TYPE_UINT64:
                pspec = g_param_spec_uint64(prop_name, nick, blurb,
                                            minimum, maximum, default_value, flags);
                break;
            }
        }
        break;
    case G_TYPE_BOOLEAN:
        {
            gboolean default_value;

            if (!gjs_parse_args(cx, method_name,
                                "b", argc, argv,
                                "default_value", &default_value))
                goto out;

            default_value = JSVAL_TO_BOOLEAN(argv[0]);

            pspec = g_param_spec_boolean(prop_name, nick, blurb,
                                         default_value, flags);
        }
        break;
    case G_TYPE_ENUM:
        {
            JSObject *gtype_jsobj;
            GType gtype;
            GIEnumInfo *info;
            gint64 default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ot", argc, argv,
                                "gtype", &gtype_jsobj,
                                "default_value", &default_value))
                goto out;

            gtype = gjs_gtype_get_actual_gtype(cx, gtype_jsobj);
            if (gtype == G_TYPE_NONE) {
                gjs_throw(cx, "Passed invalid GType to GParamSpecEnum constructor");
                goto out;
            }

            info = g_irepository_find_by_gtype(g_irepository_get_default(), gtype);

            if (!_gjs_enum_value_is_valid(cx, info, default_value))
                goto out;

            pspec = g_param_spec_enum(prop_name, nick, blurb,
                                      gtype, default_value, flags);
        }
        break;
    case G_TYPE_FLAGS:
        {
            JSObject *gtype_jsobj;
            GType gtype;
            gint64 default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ot", argc, argv,
                                "gtype", &gtype_jsobj,
                                "default_value", &default_value))
                goto out;

            gtype = gjs_gtype_get_actual_gtype(cx, gtype_jsobj);
            if (gtype == G_TYPE_NONE) {
                gjs_throw(cx, "Passed invalid GType to GParamSpecFlags constructor");
                goto out;
            }

            if (!_gjs_flags_value_is_valid(cx, gtype, default_value))
                goto out;

            pspec = g_param_spec_flags(prop_name, nick, blurb,
                                       gtype, default_value, flags);
        }
        break;
    case G_TYPE_FLOAT:
    case G_TYPE_DOUBLE:
        {
	    gfloat minimum, maximum, default_value;

            if (!gjs_parse_args(cx, "GObject.ParamSpec.float",
                                "fff", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            if (prop_type == G_TYPE_FLOAT)
                pspec = g_param_spec_float(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
            else
                pspec = g_param_spec_double(prop_name, nick, blurb,
                                            minimum, maximum, default_value, flags);
        }
        break;
    case G_TYPE_STRING:
        {
            gchar *default_value;

            if (!gjs_parse_args(cx, method_name,
                                "s", argc, argv,
                                "default_value", &default_value))
                goto out;

            pspec = g_param_spec_string(prop_name, nick, blurb,
                                        default_value, flags);

            g_free (default_value);
        }
        break;
    case G_TYPE_PARAM:
        pspec = g_param_spec_param(prop_name, nick, blurb, prop_type, flags);
        break;
    case G_TYPE_BOXED:
        pspec = g_param_spec_boxed(prop_name, nick, blurb, prop_type, flags);
        break;
    case G_TYPE_POINTER:
        pspec = g_param_spec_pointer(prop_name, nick, blurb, flags);
        break;
    case G_TYPE_OBJECT:
        pspec = g_param_spec_object(prop_name, nick, blurb, prop_type, flags);
        break;
    default:
        gjs_throw(cx,
                  "Could not create param spec for type '%s'",
                  g_type_name(prop_gtype));
        goto out;
    }

    ret = JS_TRUE;

    jsval foo = OBJECT_TO_JSVAL(gjs_param_from_g_param(cx, pspec));

    JS_SET_RVAL(cx, vp, foo);
 out:

    g_free(method_name);
    g_free(prop_name);
    g_free(nick);
    g_free(blurb);

    return ret;
}
Exemple #2
0
static JSBool
gjs_value_to_g_value_internal(JSContext    *context,
                              jsval         value,
                              GValue       *gvalue,
                              gboolean      no_copy)
{
    GType gtype;

    gtype = G_VALUE_TYPE(gvalue);

    if (gtype == 0) {
        gtype = gjs_value_guess_g_type(context, value);

        if (gtype == G_TYPE_INVALID) {
            gjs_throw(context, "Could not guess unspecified GValue type");
            return JS_FALSE;
        }

        gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                          "Guessed GValue type %s from JS Value",
                          g_type_name(gtype));

        g_value_init(gvalue, gtype);
    }

    gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                      "Converting jsval to gtype %s",
                      g_type_name(gtype));


    if (gtype == G_TYPE_STRING) {
        /* Don't use ValueToString since we don't want to just toString()
         * everything automatically
         */
        if (JSVAL_IS_NULL(value)) {
            g_value_set_string(gvalue, NULL);
        } else if (JSVAL_IS_STRING(value)) {
            gchar *utf8_string;

            if (!gjs_string_to_utf8(context, value, &utf8_string))
                return JS_FALSE;

            g_value_take_string(gvalue, utf8_string);
        } else {
            gjs_throw(context,
                      "Wrong type %s; string expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_CHAR) {
        gint32 i;
        if (JS_ValueToInt32(context, value, &i) && i >= SCHAR_MIN && i <= SCHAR_MAX) {
            g_value_set_schar(gvalue, (signed char)i);
        } else {
            gjs_throw(context,
                      "Wrong type %s; char expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_UCHAR) {
        guint16 i;
        if (JS_ValueToUint16(context, value, &i) && i <= UCHAR_MAX) {
            g_value_set_uchar(gvalue, (unsigned char)i);
        } else {
            gjs_throw(context,
                      "Wrong type %s; unsigned char expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_INT) {
        gint32 i;
        if (JS_ValueToInt32(context, value, &i)) {
            g_value_set_int(gvalue, i);
        } else {
            gjs_throw(context,
                      "Wrong type %s; integer expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_DOUBLE) {
        gdouble d;
        if (JS_ValueToNumber(context, value, &d)) {
            g_value_set_double(gvalue, d);
        } else {
            gjs_throw(context,
                      "Wrong type %s; double expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_FLOAT) {
        gdouble d;
        if (JS_ValueToNumber(context, value, &d)) {
            g_value_set_float(gvalue, d);
        } else {
            gjs_throw(context,
                      "Wrong type %s; float expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_UINT) {
        guint32 i;
        if (JS_ValueToECMAUint32(context, value, &i)) {
            g_value_set_uint(gvalue, i);
        } else {
            gjs_throw(context,
                      "Wrong type %s; unsigned integer expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (gtype == G_TYPE_BOOLEAN) {
        JSBool b;

        /* JS_ValueToBoolean() pretty much always succeeds,
         * which is maybe surprising sometimes, but could
         * be handy also...
         */
        if (JS_ValueToBoolean(context, value, &b)) {
            g_value_set_boolean(gvalue, b);
        } else {
            gjs_throw(context,
                      "Wrong type %s; boolean expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
        GObject *gobj;

        gobj = NULL;
        if (JSVAL_IS_NULL(value)) {
            /* nothing to do */
        } else if (JSVAL_IS_OBJECT(value)) {
            JSObject *obj;
            obj = JSVAL_TO_OBJECT(value);

            if (!gjs_typecheck_object(context, obj,
                                      gtype, JS_TRUE))
                return JS_FALSE;

            gobj = gjs_g_object_from_object(context, obj);
        } else {
            gjs_throw(context,
                      "Wrong type %s; object %s expected",
                      gjs_get_type_name(value),
                      g_type_name(gtype));
            return JS_FALSE;
        }

        g_value_set_object(gvalue, gobj);
    } else if (gtype == G_TYPE_STRV) {
        if (JSVAL_IS_NULL(value)) {
            /* do nothing */
        } else if (gjs_object_has_property(context,
                                           JSVAL_TO_OBJECT(value),
                                           "length")) {
            jsval length_value;
            guint32 length;

            if (!gjs_object_require_property(context,
                                             JSVAL_TO_OBJECT(value), NULL,
                                             "length",
                                             &length_value) ||
                !JS_ValueToECMAUint32(context, length_value, &length)) {
                gjs_throw(context,
                          "Wrong type %s; strv expected",
                          gjs_get_type_name(value));
                return JS_FALSE;
            } else {
                void *result;
                char **strv;

                if (!gjs_array_to_strv (context,
                                        value,
                                        length, &result))
                    return JS_FALSE;
                /* cast to strv in a separate step to avoid type-punning */
                strv = result;
                g_value_take_boxed (gvalue, strv);
            }
        } else {
            gjs_throw(context,
                      "Wrong type %s; strv expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
        void *gboxed;

        gboxed = NULL;
        if (JSVAL_IS_NULL(value)) {
            /* nothing to do */
        } else if (JSVAL_IS_OBJECT(value)) {
            JSObject *obj;
            obj = JSVAL_TO_OBJECT(value);

            if (g_type_is_a(gtype, G_TYPE_ERROR)) {
                /* special case GError */
                if (!gjs_typecheck_gerror(context, obj, JS_TRUE))
                    return JS_FALSE;

                gboxed = gjs_gerror_from_error(context, obj);
            } else {
                /* First try a union, if that fails,
                   assume a boxed struct. Distinguishing
                   which one is expected would require checking
                   the associated GIBaseInfo, which is not necessary
                   possible, if e.g. we see the GType without
                   loading the typelib.
                */
                if (gjs_typecheck_union(context, obj,
                                        NULL, gtype, JS_FALSE)) {
                    gboxed = gjs_c_union_from_union(context, obj);
                } else {
                    if (!gjs_typecheck_boxed(context, obj,
                                             NULL, gtype, JS_TRUE))
                        return JS_FALSE;

                    gboxed = gjs_c_struct_from_boxed(context, obj);
                }
            }
        } else {
            gjs_throw(context,
                      "Wrong type %s; boxed type %s expected",
                      gjs_get_type_name(value),
                      g_type_name(gtype));
            return JS_FALSE;
        }

        if (no_copy)
            g_value_set_static_boxed(gvalue, gboxed);
        else
            g_value_set_boxed(gvalue, gboxed);
    } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
        GVariant *variant = NULL;

        if (JSVAL_IS_NULL(value)) {
            /* nothing to do */
        } else if (JSVAL_IS_OBJECT(value)) {
            JSObject *obj = JSVAL_TO_OBJECT(value);

            if (!gjs_typecheck_boxed(context, obj,
                                     NULL, G_TYPE_VARIANT, JS_TRUE))
                return JS_FALSE;

            variant = gjs_c_struct_from_boxed(context, obj);
        } else {
            gjs_throw(context,
                      "Wrong type %s; boxed type %s expected",
                      gjs_get_type_name(value),
                      g_type_name(gtype));
            return JS_FALSE;
        }

        g_value_set_variant (gvalue, variant);
    } else if (g_type_is_a(gtype, G_TYPE_ENUM)) {
        gint64 value_int64;

        if (gjs_value_to_int64 (context, value, &value_int64)) {
            GEnumValue *v;

            /* See arg.c:_gjs_enum_to_int() */
            v = g_enum_get_value(G_ENUM_CLASS(g_type_class_peek(gtype)),
                                 (int)value_int64);
            if (v == NULL) {
                gjs_throw(context,
                          "%d is not a valid value for enumeration %s",
                          JSVAL_TO_INT(value), g_type_name(gtype));
                return JS_FALSE;
            }

            g_value_set_enum(gvalue, v->value);
        } else {
            gjs_throw(context,
                         "Wrong type %s; enum %s expected",
                         gjs_get_type_name(value),
                         g_type_name(gtype));
            return JS_FALSE;
        }
    } else if (g_type_is_a(gtype, G_TYPE_FLAGS)) {
        gint64 value_int64;

        if (gjs_value_to_int64 (context, value, &value_int64)) {
            if (!_gjs_flags_value_is_valid(context, gtype, value_int64))
                return JS_FALSE;

            /* See arg.c:_gjs_enum_to_int() */
            g_value_set_flags(gvalue, (int)value_int64);
        } else {
            gjs_throw(context,
                      "Wrong type %s; flags %s expected",
                      gjs_get_type_name(value),
                      g_type_name(gtype));
            return JS_FALSE;
        }
    } else if (g_type_is_a(gtype, G_TYPE_PARAM)) {
        void *gparam;

        gparam = NULL;
        if (JSVAL_IS_NULL(value)) {
            /* nothing to do */
        } else if (JSVAL_IS_OBJECT(value)) {
            JSObject *obj;
            obj = JSVAL_TO_OBJECT(value);

            if (!gjs_typecheck_param(context, obj, gtype, JS_TRUE))
                return JS_FALSE;

            gparam = gjs_g_param_from_param(context, obj);
        } else {
            gjs_throw(context,
                      "Wrong type %s; param type %s expected",
                      gjs_get_type_name(value),
                      g_type_name(gtype));
            return JS_FALSE;
        }

        g_value_set_param(gvalue, gparam);
    } else if (g_type_is_a(gtype, G_TYPE_GTYPE)) {
        GType type;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Wrong type %s; expect a GType object",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }

        type = gjs_gtype_get_actual_gtype(context, JSVAL_TO_OBJECT(value));
        g_value_set_gtype(gvalue, type);
    } else if (g_type_is_a(gtype, G_TYPE_POINTER)) {
        if (JSVAL_IS_NULL(value)) {
            /* Nothing to do */
        } else {
            gjs_throw(context,
                      "Cannot convert non-null JS value to G_POINTER");
            return JS_FALSE;
        }
    } else if (JSVAL_IS_NUMBER(value) &&
               g_value_type_transformable(G_TYPE_INT, gtype)) {
        /* Only do this crazy gvalue transform stuff after we've
         * exhausted everything else. Adding this for
         * e.g. ClutterUnit.
         */
        gint32 i;
        if (JS_ValueToInt32(context, value, &i)) {
            GValue int_value = { 0, };
            g_value_init(&int_value, G_TYPE_INT);
            g_value_set_int(&int_value, i);
            g_value_transform(&int_value, gvalue);
        } else {
            gjs_throw(context,
                      "Wrong type %s; integer expected",
                      gjs_get_type_name(value));
            return JS_FALSE;
        }
    } else {
        gjs_debug(GJS_DEBUG_GCLOSURE, "jsval is number %d gtype fundamental %d transformable to int %d from int %d",
                  JSVAL_IS_NUMBER(value),
                  G_TYPE_IS_FUNDAMENTAL(gtype),
                  g_value_type_transformable(gtype, G_TYPE_INT),
                  g_value_type_transformable(G_TYPE_INT, gtype));

        gjs_throw(context,
                  "Don't know how to convert JavaScript object to GType %s",
                  g_type_name(gtype));
        return JS_FALSE;
    }

    return JS_TRUE;
}